Revert "Revert "Add RTLD_NODELETE flag support""
This reverts commit 69c5d108a5.
			
			
This commit is contained in:
		@@ -64,6 +64,7 @@ enum {
 | 
				
			|||||||
  RTLD_GLOBAL = 2,
 | 
					  RTLD_GLOBAL = 2,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  RTLD_NOLOAD = 4,
 | 
					  RTLD_NOLOAD = 4,
 | 
				
			||||||
 | 
					  RTLD_NODELETE = 0x01000,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined (__LP64__)
 | 
					#if defined (__LP64__)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -987,6 +987,11 @@ static soinfo* find_library(const char* name, int rtld_flags, const android_dlex
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void soinfo_unload(soinfo* si) {
 | 
					static void soinfo_unload(soinfo* si) {
 | 
				
			||||||
 | 
					  if (!si->can_unload()) {
 | 
				
			||||||
 | 
					    TRACE("not unloading '%s' - the binary is flagged with NODELETE", si->name);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (si->ref_count == 1) {
 | 
					  if (si->ref_count == 1) {
 | 
				
			||||||
    TRACE("unloading '%s'", si->name);
 | 
					    TRACE("unloading '%s'", si->name);
 | 
				
			||||||
    si->CallDestructors();
 | 
					    si->CallDestructors();
 | 
				
			||||||
@@ -1045,7 +1050,7 @@ void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) {
 | 
					soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) {
 | 
				
			||||||
  if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NOLOAD)) != 0) {
 | 
					  if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
 | 
				
			||||||
    DL_ERR("invalid flags to dlopen: %x", flags);
 | 
					    DL_ERR("invalid flags to dlopen: %x", flags);
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1808,6 +1813,9 @@ const char* soinfo::get_string(ElfW(Word) index) const {
 | 
				
			|||||||
  return strtab + index;
 | 
					  return strtab + index;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool soinfo::can_unload() const {
 | 
				
			||||||
 | 
					  return (rtld_flags & (RTLD_NODELETE | RTLD_GLOBAL)) == 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/* Force any of the closed stdin, stdout and stderr to be associated with
 | 
					/* Force any of the closed stdin, stdout and stderr to be associated with
 | 
				
			||||||
   /dev/null. */
 | 
					   /dev/null. */
 | 
				
			||||||
static int nullify_closed_stdio() {
 | 
					static int nullify_closed_stdio() {
 | 
				
			||||||
@@ -2111,9 +2119,13 @@ bool soinfo::PrelinkImage() {
 | 
				
			|||||||
        if ((d->d_un.d_val & DF_1_GLOBAL) != 0) {
 | 
					        if ((d->d_un.d_val & DF_1_GLOBAL) != 0) {
 | 
				
			||||||
          rtld_flags |= RTLD_GLOBAL;
 | 
					          rtld_flags |= RTLD_GLOBAL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((d->d_un.d_val & DF_1_NODELETE) != 0) {
 | 
				
			||||||
 | 
					          rtld_flags |= RTLD_NODELETE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        // TODO: Implement other flags
 | 
					        // TODO: Implement other flags
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((d->d_un.d_val & ~(DF_1_NOW | DF_1_GLOBAL)) != 0) {
 | 
					        if ((d->d_un.d_val & ~(DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE)) != 0) {
 | 
				
			||||||
          DL_WARN("Unsupported flags DT_FLAGS_1=%p", reinterpret_cast<void*>(d->d_un.d_val));
 | 
					          DL_WARN("Unsupported flags DT_FLAGS_1=%p", reinterpret_cast<void*>(d->d_un.d_val));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -134,7 +134,7 @@ struct soinfo {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo* next;
 | 
					  soinfo* next;
 | 
				
			||||||
  unsigned flags;
 | 
					  uint32_t flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
  const char* strtab;
 | 
					  const char* strtab;
 | 
				
			||||||
@@ -143,8 +143,8 @@ struct soinfo {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  size_t nbucket;
 | 
					  size_t nbucket;
 | 
				
			||||||
  size_t nchain;
 | 
					  size_t nchain;
 | 
				
			||||||
  unsigned* bucket;
 | 
					  uint32_t* bucket;
 | 
				
			||||||
  unsigned* chain;
 | 
					  uint32_t* chain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__mips__) || !defined(__LP64__)
 | 
					#if defined(__mips__) || !defined(__LP64__)
 | 
				
			||||||
  // This is only used by mips and mips64, but needs to be here for
 | 
					  // This is only used by mips and mips64, but needs to be here for
 | 
				
			||||||
@@ -179,12 +179,12 @@ struct soinfo {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if defined(__arm__)
 | 
					#if defined(__arm__)
 | 
				
			||||||
  // ARM EABI section used for stack unwinding.
 | 
					  // ARM EABI section used for stack unwinding.
 | 
				
			||||||
  unsigned* ARM_exidx;
 | 
					  uint32_t* ARM_exidx;
 | 
				
			||||||
  size_t ARM_exidx_count;
 | 
					  size_t ARM_exidx_count;
 | 
				
			||||||
#elif defined(__mips__)
 | 
					#elif defined(__mips__)
 | 
				
			||||||
  unsigned mips_symtabno;
 | 
					  uint32_t mips_symtabno;
 | 
				
			||||||
  unsigned mips_local_gotno;
 | 
					  uint32_t mips_local_gotno;
 | 
				
			||||||
  unsigned mips_gotsym;
 | 
					  uint32_t mips_gotsym;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  size_t ref_count;
 | 
					  size_t ref_count;
 | 
				
			||||||
@@ -224,10 +224,12 @@ struct soinfo {
 | 
				
			|||||||
  ElfW(Addr) resolve_symbol_address(ElfW(Sym)* s);
 | 
					  ElfW(Addr) resolve_symbol_address(ElfW(Sym)* s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char* get_string(ElfW(Word) index) const;
 | 
					  const char* get_string(ElfW(Word) index) const;
 | 
				
			||||||
 | 
					  bool can_unload() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool inline has_min_version(uint32_t min_version) const {
 | 
					  bool inline has_min_version(uint32_t min_version) const {
 | 
				
			||||||
    return (flags & FLAG_NEW_SOINFO) != 0 && version >= min_version;
 | 
					    return (flags & FLAG_NEW_SOINFO) != 0 && version >= min_version;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
  void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
 | 
					  void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
 | 
				
			||||||
  void CallFunction(const char* function_name, linker_function_t function);
 | 
					  void CallFunction(const char* function_name, linker_function_t function);
 | 
				
			||||||
@@ -258,7 +260,7 @@ struct soinfo {
 | 
				
			|||||||
  friend soinfo* get_libdl_info();
 | 
					  friend soinfo* get_libdl_info();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern soinfo* get_libdl_info();
 | 
					soinfo* get_libdl_info();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void do_android_get_LD_LIBRARY_PATH(char*, size_t);
 | 
					void do_android_get_LD_LIBRARY_PATH(char*, size_t);
 | 
				
			||||||
void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
 | 
					void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,10 +232,15 @@ TEST(dlfcn, dlopen_check_rtld_global) {
 | 
				
			|||||||
  ASSERT_TRUE(sym == nullptr);
 | 
					  ASSERT_TRUE(sym == nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_GLOBAL);
 | 
					  void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_GLOBAL);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
				
			||||||
  sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
 | 
					  sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
 | 
				
			||||||
  ASSERT_TRUE(sym != nullptr) << dlerror();
 | 
					  ASSERT_TRUE(sym != nullptr) << dlerror();
 | 
				
			||||||
  ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
 | 
					  ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
 | 
				
			||||||
  dlclose(handle);
 | 
					  dlclose(handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // RTLD_GLOBAL implies RTLD_NODELETE, let's check that
 | 
				
			||||||
 | 
					  void* sym_after_dlclose = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
 | 
				
			||||||
 | 
					  ASSERT_EQ(sym, sym_after_dlclose);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so ->
 | 
					// libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so ->
 | 
				
			||||||
@@ -263,6 +268,81 @@ TEST(dlfcn, dlopen_check_loop) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(dlfcn, dlopen_nodelete) {
 | 
				
			||||||
 | 
					  static bool is_unloaded = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void* handle = dlopen("libtest_nodelete_1.so", RTLD_NOW | RTLD_NODELETE);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  void (*set_unload_flag_ptr)(bool*);
 | 
				
			||||||
 | 
					  set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_1_set_unload_flag_ptr"));
 | 
				
			||||||
 | 
					  ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  set_unload_flag_ptr(&is_unloaded);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
 | 
				
			||||||
 | 
					  ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  ASSERT_EQ(1729U, *taxicab_number);
 | 
				
			||||||
 | 
					  *taxicab_number = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dlclose(handle);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(!is_unloaded);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t* taxicab_number_after_dlclose = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
 | 
				
			||||||
 | 
					  ASSERT_EQ(taxicab_number_after_dlclose, taxicab_number);
 | 
				
			||||||
 | 
					  ASSERT_EQ(2U, *taxicab_number_after_dlclose);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handle = dlopen("libtest_nodelete_1.so", RTLD_NOW);
 | 
				
			||||||
 | 
					  uint32_t* taxicab_number2 = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
 | 
				
			||||||
 | 
					  ASSERT_EQ(taxicab_number2, taxicab_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ASSERT_EQ(2U, *taxicab_number2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dlclose(handle);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(!is_unloaded);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(dlfcn, dlopen_nodelete_on_second_dlopen) {
 | 
				
			||||||
 | 
					  static bool is_unloaded = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void* handle = dlopen("libtest_nodelete_2.so", RTLD_NOW);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  void (*set_unload_flag_ptr)(bool*);
 | 
				
			||||||
 | 
					  set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_2_set_unload_flag_ptr"));
 | 
				
			||||||
 | 
					  ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  set_unload_flag_ptr(&is_unloaded);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_2_taxicab_number"));
 | 
				
			||||||
 | 
					  ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ASSERT_EQ(1729U, *taxicab_number);
 | 
				
			||||||
 | 
					  *taxicab_number = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // This RTLD_NODELETE should be ignored
 | 
				
			||||||
 | 
					  void* handle1 = dlopen("libtest_nodelete_2.so", RTLD_NOW | RTLD_NODELETE);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle1 != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  ASSERT_EQ(handle, handle1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dlclose(handle1);
 | 
				
			||||||
 | 
					  dlclose(handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ASSERT_TRUE(is_unloaded);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(dlfcn, dlopen_nodelete_dt_flags_1) {
 | 
				
			||||||
 | 
					  static bool is_unloaded = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void* handle = dlopen("libtest_nodelete_dt_flags_1.so", RTLD_NOW);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  void (*set_unload_flag_ptr)(bool*);
 | 
				
			||||||
 | 
					  set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_dt_flags_1_set_unload_flag_ptr"));
 | 
				
			||||||
 | 
					  ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  set_unload_flag_ptr(&is_unloaded);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dlclose(handle);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(!is_unloaded);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlopen_failure) {
 | 
					TEST(dlfcn, dlopen_failure) {
 | 
				
			||||||
  void* self = dlopen("/does/not/exist", RTLD_NOW);
 | 
					  void* self = dlopen("/does/not/exist", RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(self == NULL);
 | 
					  ASSERT_TRUE(self == NULL);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -120,6 +120,35 @@ libtest_simple_src_files := \
 | 
				
			|||||||
module := libtest_simple
 | 
					module := libtest_simple
 | 
				
			||||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Library used by dlfcn nodelete tests
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					libtest_nodelete_1_src_files := \
 | 
				
			||||||
 | 
					    dlopen_nodelete_1.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module := libtest_nodelete_1
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Library used by dlfcn nodelete tests
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					libtest_nodelete_2_src_files := \
 | 
				
			||||||
 | 
					    dlopen_nodelete_2.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module := libtest_nodelete_2
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Library used by dlfcn nodelete tests
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					libtest_nodelete_dt_flags_1_src_files := \
 | 
				
			||||||
 | 
					    dlopen_nodelete_dt_flags_1.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libtest_nodelete_dt_flags_1_ldflags := -Wl,-z,nodelete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module := libtest_nodelete_dt_flags_1
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
# Libraries used by dlfcn tests to verify correct load order:
 | 
					# Libraries used by dlfcn tests to verify correct load order:
 | 
				
			||||||
# libtest_check_order_2_right.so
 | 
					# libtest_check_order_2_right.so
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								tests/libs/dlopen_nodelete_1.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/libs/dlopen_nodelete_1.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t dlopen_nodelete_1_taxicab_number = 1729;
 | 
				
			||||||
 | 
					static bool* unload_flag_ptr = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" void dlopen_nodelete_1_set_unload_flag_ptr(bool* ptr) {
 | 
				
			||||||
 | 
					  unload_flag_ptr = ptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __attribute__((destructor)) unload_guard() {
 | 
				
			||||||
 | 
					  if (unload_flag_ptr != nullptr) {
 | 
				
			||||||
 | 
					    *unload_flag_ptr = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								tests/libs/dlopen_nodelete_2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/libs/dlopen_nodelete_2.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t dlopen_nodelete_2_taxicab_number = 1729;
 | 
				
			||||||
 | 
					static bool* unload_flag_ptr = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" void dlopen_nodelete_2_set_unload_flag_ptr(bool* ptr) {
 | 
				
			||||||
 | 
					  unload_flag_ptr = ptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __attribute__((destructor)) unload_guard() {
 | 
				
			||||||
 | 
					  if (unload_flag_ptr != nullptr) {
 | 
				
			||||||
 | 
					    *unload_flag_ptr = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								tests/libs/dlopen_nodelete_dt_flags_1.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/libs/dlopen_nodelete_dt_flags_1.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool* unload_flag_ptr = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" void dlopen_nodelete_dt_flags_1_set_unload_flag_ptr(bool* ptr) {
 | 
				
			||||||
 | 
					  unload_flag_ptr = ptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __attribute__((destructor)) unload_guard() {
 | 
				
			||||||
 | 
					  if (unload_flag_ptr != nullptr) {
 | 
				
			||||||
 | 
					    *unload_flag_ptr = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user