Add RTLD_NODELETE flag support

Bug: https://code.google.com/p/android/issues/detail?id=64069
Change-Id: Ie5f90482feae86391172be4b32d6cb7d76f446fb
This commit is contained in:
Dmitriy Ivanov
2014-05-19 15:06:58 -07:00
parent 1f7d5ac538
commit 1b20dafdbe
8 changed files with 226 additions and 10 deletions

View File

@@ -976,6 +976,11 @@ static soinfo* find_library(const char* name, int rtld_flags, const android_dlex
}
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) {
TRACE("unloading '%s'", si->name);
si->CallDestructors();
@@ -1034,7 +1039,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) {
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);
return nullptr;
}
@@ -1794,6 +1799,9 @@ const char* soinfo::get_string(ElfW(Word) index) const {
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
/dev/null. */
static int nullify_closed_stdio() {
@@ -2062,9 +2070,13 @@ bool soinfo::PrelinkImage() {
if ((d->d_un.d_val & DF_1_GLOBAL) != 0) {
rtld_flags |= RTLD_GLOBAL;
}
if ((d->d_un.d_val & DF_1_NODELETE) != 0) {
rtld_flags |= RTLD_NODELETE;
}
// 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));
}
break;

View File

@@ -134,7 +134,7 @@ struct soinfo {
#endif
soinfo* next;
unsigned flags;
uint32_t flags;
private:
const char* strtab;
@@ -143,8 +143,8 @@ struct soinfo {
size_t nbucket;
size_t nchain;
unsigned* bucket;
unsigned* chain;
uint32_t* bucket;
uint32_t* chain;
#if defined(__mips__) || !defined(__LP64__)
// This is only used by mips and mips64, but needs to be here for
@@ -179,12 +179,12 @@ struct soinfo {
#if defined(__arm__)
// ARM EABI section used for stack unwinding.
unsigned* ARM_exidx;
uint32_t* ARM_exidx;
size_t ARM_exidx_count;
#elif defined(__mips__)
unsigned mips_symtabno;
unsigned mips_local_gotno;
unsigned mips_gotsym;
uint32_t mips_symtabno;
uint32_t mips_local_gotno;
uint32_t mips_gotsym;
#endif
size_t ref_count;
@@ -225,10 +225,12 @@ struct soinfo {
ElfW(Addr) resolve_symbol_address(ElfW(Sym)* s);
const char* get_string(ElfW(Word) index) const;
bool can_unload() const;
bool inline has_min_version(uint32_t min_version) const {
return (flags & FLAG_NEW_SOINFO) != 0 && version >= min_version;
}
private:
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);
@@ -258,7 +260,7 @@ struct soinfo {
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_update_LD_LIBRARY_PATH(const char* ld_library_path);