Merge "Rename soinfo methods and fields"
This commit is contained in:
commit
c490b5029f
@ -238,14 +238,14 @@ static soinfo __libdl_info("libdl.so", nullptr, 0, RTLD_GLOBAL);
|
|||||||
soinfo* get_libdl_info() {
|
soinfo* get_libdl_info() {
|
||||||
if ((__libdl_info.flags & FLAG_LINKED) == 0) {
|
if ((__libdl_info.flags & FLAG_LINKED) == 0) {
|
||||||
__libdl_info.flags |= FLAG_LINKED;
|
__libdl_info.flags |= FLAG_LINKED;
|
||||||
__libdl_info.strtab = ANDROID_LIBDL_STRTAB;
|
__libdl_info.strtab_ = ANDROID_LIBDL_STRTAB;
|
||||||
__libdl_info.symtab = g_libdl_symtab;
|
__libdl_info.symtab_ = g_libdl_symtab;
|
||||||
__libdl_info.nbucket = sizeof(g_libdl_buckets)/sizeof(unsigned);
|
__libdl_info.nbucket_ = sizeof(g_libdl_buckets)/sizeof(unsigned);
|
||||||
__libdl_info.nchain = sizeof(g_libdl_chains)/sizeof(unsigned);
|
__libdl_info.nchain_ = sizeof(g_libdl_chains)/sizeof(unsigned);
|
||||||
__libdl_info.bucket = g_libdl_buckets;
|
__libdl_info.bucket_ = g_libdl_buckets;
|
||||||
__libdl_info.chain = g_libdl_chains;
|
__libdl_info.chain_ = g_libdl_chains;
|
||||||
__libdl_info.ref_count = 1;
|
__libdl_info.ref_count = 1;
|
||||||
__libdl_info.strtab_size = sizeof(ANDROID_LIBDL_STRTAB);
|
__libdl_info.strtab_size_ = sizeof(ANDROID_LIBDL_STRTAB);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &__libdl_info;
|
return &__libdl_info;
|
||||||
|
@ -434,11 +434,11 @@ static bool is_symbol_global_and_defined(const soinfo* si, const ElfW(Sym)* s) {
|
|||||||
|
|
||||||
ElfW(Sym)* soinfo::gnu_lookup(SymbolName& symbol_name) {
|
ElfW(Sym)* soinfo::gnu_lookup(SymbolName& symbol_name) {
|
||||||
uint32_t hash = symbol_name.gnu_hash();
|
uint32_t hash = symbol_name.gnu_hash();
|
||||||
uint32_t h2 = hash >> gnu_shift2;
|
uint32_t h2 = hash >> gnu_shift2_;
|
||||||
|
|
||||||
uint32_t bloom_mask_bits = sizeof(ElfW(Addr))*8;
|
uint32_t bloom_mask_bits = sizeof(ElfW(Addr))*8;
|
||||||
uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords;
|
uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords_;
|
||||||
ElfW(Addr) bloom_word = gnu_bloom_filter[word_num];
|
ElfW(Addr) bloom_word = gnu_bloom_filter_[word_num];
|
||||||
|
|
||||||
// test against bloom filter
|
// test against bloom filter
|
||||||
if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {
|
if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {
|
||||||
@ -446,20 +446,20 @@ ElfW(Sym)* soinfo::gnu_lookup(SymbolName& symbol_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bloom test says "probably yes"...
|
// bloom test says "probably yes"...
|
||||||
uint32_t n = bucket[hash % nbucket];
|
uint32_t n = bucket_[hash % nbucket_];
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ElfW(Sym)* s = symtab + n;
|
ElfW(Sym)* s = symtab_ + n;
|
||||||
if (((chain[n] ^ hash) >> 1) == 0 &&
|
if (((chain_[n] ^ hash) >> 1) == 0 &&
|
||||||
strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
|
strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
|
||||||
is_symbol_global_and_defined(this, s)) {
|
is_symbol_global_and_defined(this, s)) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
} while ((chain[n++] & 1) == 0);
|
} while ((chain_[n++] & 1) == 0);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -468,10 +468,10 @@ ElfW(Sym)* soinfo::elf_lookup(SymbolName& symbol_name) {
|
|||||||
uint32_t hash = symbol_name.elf_hash();
|
uint32_t hash = symbol_name.elf_hash();
|
||||||
|
|
||||||
TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
|
TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
|
||||||
symbol_name.get_name(), name, reinterpret_cast<void*>(base), hash, hash % nbucket);
|
symbol_name.get_name(), name, reinterpret_cast<void*>(base), hash, hash % nbucket_);
|
||||||
|
|
||||||
for (uint32_t n = bucket[hash % nbucket]; n != 0; n = chain[n]) {
|
for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {
|
||||||
ElfW(Sym)* s = symtab + n;
|
ElfW(Sym)* s = symtab_ + n;
|
||||||
if (strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 && is_symbol_global_and_defined(this, s)) {
|
if (strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 && is_symbol_global_and_defined(this, s)) {
|
||||||
TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
|
TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
|
||||||
symbol_name.get_name(), name, reinterpret_cast<void*>(s->st_value),
|
symbol_name.get_name(), name, reinterpret_cast<void*>(s->st_value),
|
||||||
@ -481,7 +481,7 @@ ElfW(Sym)* soinfo::elf_lookup(SymbolName& symbol_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
|
TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
|
||||||
symbol_name.get_name(), name, reinterpret_cast<void*>(base), hash, hash % nbucket);
|
symbol_name.get_name(), name, reinterpret_cast<void*>(base), hash, hash % nbucket_);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -491,15 +491,15 @@ soinfo::soinfo(const char* name, const struct stat* file_stat, off64_t file_offs
|
|||||||
|
|
||||||
strlcpy(this->name, name, sizeof(this->name));
|
strlcpy(this->name, name, sizeof(this->name));
|
||||||
flags = FLAG_NEW_SOINFO;
|
flags = FLAG_NEW_SOINFO;
|
||||||
version = SOINFO_VERSION;
|
version_ = SOINFO_VERSION;
|
||||||
|
|
||||||
if (file_stat != nullptr) {
|
if (file_stat != nullptr) {
|
||||||
this->st_dev = file_stat->st_dev;
|
this->st_dev_ = file_stat->st_dev;
|
||||||
this->st_ino = file_stat->st_ino;
|
this->st_ino_ = file_stat->st_ino;
|
||||||
this->file_offset = file_offset;
|
this->file_offset_ = file_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->rtld_flags = rtld_flags;
|
this->rtld_flags_ = rtld_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -793,19 +793,19 @@ static bool symbol_matches_soaddr(const ElfW(Sym)* sym, ElfW(Addr) soaddr) {
|
|||||||
ElfW(Sym)* soinfo::gnu_addr_lookup(const void* addr) {
|
ElfW(Sym)* soinfo::gnu_addr_lookup(const void* addr) {
|
||||||
ElfW(Addr) soaddr = reinterpret_cast<ElfW(Addr)>(addr) - base;
|
ElfW(Addr) soaddr = reinterpret_cast<ElfW(Addr)>(addr) - base;
|
||||||
|
|
||||||
for (size_t i = 0; i < nbucket; ++i) {
|
for (size_t i = 0; i < nbucket_; ++i) {
|
||||||
uint32_t n = bucket[i];
|
uint32_t n = bucket_[i];
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ElfW(Sym)* sym = symtab + n;
|
ElfW(Sym)* sym = symtab_ + n;
|
||||||
if (symbol_matches_soaddr(sym, soaddr)) {
|
if (symbol_matches_soaddr(sym, soaddr)) {
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
} while ((chain[n++] & 1) == 0);
|
} while ((chain_[n++] & 1) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -816,8 +816,8 @@ ElfW(Sym)* soinfo::elf_addr_lookup(const void* addr) {
|
|||||||
|
|
||||||
// Search the library's symbol table for any defined symbol which
|
// Search the library's symbol table for any defined symbol which
|
||||||
// contains this address.
|
// contains this address.
|
||||||
for (size_t i = 0; i < nchain; ++i) {
|
for (size_t i = 0; i < nchain_; ++i) {
|
||||||
ElfW(Sym)* sym = symtab + i;
|
ElfW(Sym)* sym = symtab_ + i;
|
||||||
if (symbol_matches_soaddr(sym, soaddr)) {
|
if (symbol_matches_soaddr(sym, soaddr)) {
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
@ -948,7 +948,7 @@ static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld
|
|||||||
si->phnum = elf_reader.phdr_count();
|
si->phnum = elf_reader.phdr_count();
|
||||||
si->phdr = elf_reader.loaded_phdr();
|
si->phdr = elf_reader.loaded_phdr();
|
||||||
|
|
||||||
if (!si->PrelinkImage()) {
|
if (!si->prelink_image()) {
|
||||||
soinfo_free(si);
|
soinfo_free(si);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -1104,7 +1104,7 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
|
|||||||
|
|
||||||
bool linked = local_group.visit([&](soinfo* si) {
|
bool linked = local_group.visit([&](soinfo* si) {
|
||||||
if ((si->flags & FLAG_LINKED) == 0) {
|
if ((si->flags & FLAG_LINKED) == 0) {
|
||||||
if (!si->LinkImage(global_group, local_group, extinfo)) {
|
if (!si->link_image(global_group, local_group, extinfo)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
si->flags |= FLAG_LINKED;
|
si->flags |= FLAG_LINKED;
|
||||||
@ -1143,7 +1143,7 @@ static void soinfo_unload(soinfo* si) {
|
|||||||
|
|
||||||
if (si->ref_count == 1) {
|
if (si->ref_count == 1) {
|
||||||
TRACE("unloading '%s'", si->name);
|
TRACE("unloading '%s'", si->name);
|
||||||
si->CallDestructors();
|
si->call_destructors();
|
||||||
|
|
||||||
if (si->has_min_version(0)) {
|
if (si->has_min_version(0)) {
|
||||||
soinfo* child = nullptr;
|
soinfo* child = nullptr;
|
||||||
@ -1217,7 +1217,7 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
|
|||||||
protect_data(PROT_READ | PROT_WRITE);
|
protect_data(PROT_READ | PROT_WRITE);
|
||||||
soinfo* si = find_library(name, flags, extinfo);
|
soinfo* si = find_library(name, flags, extinfo);
|
||||||
if (si != nullptr) {
|
if (si != nullptr) {
|
||||||
si->CallConstructors();
|
si->call_constructors();
|
||||||
}
|
}
|
||||||
protect_data(PROT_READ);
|
protect_data(PROT_READ);
|
||||||
return si;
|
return si;
|
||||||
@ -1239,7 +1239,7 @@ static ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_RELA)
|
#if defined(USE_RELA)
|
||||||
int soinfo::Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
|
int soinfo::relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
|
||||||
for (size_t idx = 0; idx < count; ++idx, ++rela) {
|
for (size_t idx = 0; idx < count; ++idx, ++rela) {
|
||||||
unsigned type = ELFW(R_TYPE)(rela->r_info);
|
unsigned type = ELFW(R_TYPE)(rela->r_info);
|
||||||
unsigned sym = ELFW(R_SYM)(rela->r_info);
|
unsigned sym = ELFW(R_SYM)(rela->r_info);
|
||||||
@ -1256,11 +1256,11 @@ int soinfo::Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& glob
|
|||||||
soinfo* lsi = nullptr;
|
soinfo* lsi = nullptr;
|
||||||
|
|
||||||
if (sym != 0) {
|
if (sym != 0) {
|
||||||
sym_name = get_string(symtab[sym].st_name);
|
sym_name = get_string(symtab_[sym].st_name);
|
||||||
s = soinfo_do_lookup(this, sym_name, &lsi, global_group,local_group);
|
s = soinfo_do_lookup(this, sym_name, &lsi, global_group,local_group);
|
||||||
if (s == nullptr) {
|
if (s == nullptr) {
|
||||||
// We only allow an undefined symbol if this is a weak reference...
|
// We only allow an undefined symbol if this is a weak reference...
|
||||||
s = &symtab[sym];
|
s = &symtab_[sym];
|
||||||
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
|
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
|
||||||
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, name);
|
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, name);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1516,7 +1516,7 @@ int soinfo::Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& glob
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else // REL, not RELA.
|
#else // REL, not RELA.
|
||||||
int soinfo::Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
|
int soinfo::relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
|
||||||
for (size_t idx = 0; idx < count; ++idx, ++rel) {
|
for (size_t idx = 0; idx < count; ++idx, ++rel) {
|
||||||
unsigned type = ELFW(R_TYPE)(rel->r_info);
|
unsigned type = ELFW(R_TYPE)(rel->r_info);
|
||||||
// TODO: don't use unsigned for 'sym'. Use uint32_t or ElfW(Addr) instead.
|
// TODO: don't use unsigned for 'sym'. Use uint32_t or ElfW(Addr) instead.
|
||||||
@ -1534,11 +1534,11 @@ int soinfo::Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global
|
|||||||
soinfo* lsi = nullptr;
|
soinfo* lsi = nullptr;
|
||||||
|
|
||||||
if (sym != 0) {
|
if (sym != 0) {
|
||||||
sym_name = get_string(symtab[sym].st_name);
|
sym_name = get_string(symtab_[sym].st_name);
|
||||||
s = soinfo_do_lookup(this, sym_name, &lsi, global_group, local_group);
|
s = soinfo_do_lookup(this, sym_name, &lsi, global_group, local_group);
|
||||||
if (s == nullptr) {
|
if (s == nullptr) {
|
||||||
// We only allow an undefined symbol if this is a weak reference...
|
// We only allow an undefined symbol if this is a weak reference...
|
||||||
s = &symtab[sym];
|
s = &symtab_[sym];
|
||||||
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
|
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
|
||||||
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, name);
|
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, name);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1722,13 +1722,10 @@ int soinfo::Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global
|
|||||||
|
|
||||||
#if defined(__mips__)
|
#if defined(__mips__)
|
||||||
bool soinfo::mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
|
bool soinfo::mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
|
||||||
ElfW(Addr)** got = plt_got;
|
ElfW(Addr)** got = plt_got_;
|
||||||
if (got == nullptr) {
|
if (got == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
unsigned local_gotno = mips_local_gotno;
|
|
||||||
unsigned gotsym = mips_gotsym;
|
|
||||||
unsigned symtabno = mips_symtabno;
|
|
||||||
|
|
||||||
// got[0] is the address of the lazy resolver function.
|
// got[0] is the address of the lazy resolver function.
|
||||||
// got[1] may be used for a GNU extension.
|
// got[1] may be used for a GNU extension.
|
||||||
@ -1741,22 +1738,22 @@ bool soinfo::mips_relocate_got(const soinfo_list_t& global_group, const soinfo_l
|
|||||||
got[g++] = reinterpret_cast<ElfW(Addr)*>(0xdeadfeed);
|
got[g++] = reinterpret_cast<ElfW(Addr)*>(0xdeadfeed);
|
||||||
}
|
}
|
||||||
// Relocate the local GOT entries.
|
// Relocate the local GOT entries.
|
||||||
for (; g < local_gotno; g++) {
|
for (; g < mips_local_gotno_; g++) {
|
||||||
got[g] = reinterpret_cast<ElfW(Addr)*>(reinterpret_cast<uintptr_t>(got[g]) + load_bias);
|
got[g] = reinterpret_cast<ElfW(Addr)*>(reinterpret_cast<uintptr_t>(got[g]) + load_bias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now for the global GOT entries...
|
// Now for the global GOT entries...
|
||||||
ElfW(Sym)* sym = symtab + gotsym;
|
ElfW(Sym)* sym = symtab_ + mips_gotsym_;
|
||||||
got = plt_got + local_gotno;
|
got = plt_got_ + mips_local_gotno_;
|
||||||
for (size_t g = gotsym; g < symtabno; g++, sym++, got++) {
|
for (size_t g = mips_gotsym_; g < mips_symtabno_; g++, sym++, got++) {
|
||||||
// This is an undefined reference... try to locate it.
|
// This is an undefined reference... try to locate it.
|
||||||
const char* sym_name = get_string(sym->st_name);
|
const char* sym_name = get_string(sym->st_name);
|
||||||
soinfo* lsi = nullptr;
|
soinfo* lsi = nullptr;
|
||||||
ElfW(Sym)* s = soinfo_do_lookup(this, sym_name, &lsi, global_group, local_group);
|
ElfW(Sym)* s = soinfo_do_lookup(this, sym_name, &lsi, global_group, local_group);
|
||||||
if (s == nullptr) {
|
if (s == nullptr) {
|
||||||
// We only allow an undefined symbol if this is a weak reference.
|
// We only allow an undefined symbol if this is a weak reference.
|
||||||
s = &symtab[g];
|
s = &symtab_[g];
|
||||||
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
|
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
|
||||||
DL_ERR("cannot locate \"%s\"...", sym_name);
|
DL_ERR("cannot locate \"%s\"...", sym_name);
|
||||||
return false;
|
return false;
|
||||||
@ -1773,7 +1770,7 @@ bool soinfo::mips_relocate_got(const soinfo_list_t& global_group, const soinfo_l
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void soinfo::CallArray(const char* array_name __unused, linker_function_t* functions, size_t count, bool reverse) {
|
void soinfo::call_array(const char* array_name __unused, linker_function_t* functions, size_t count, bool reverse) {
|
||||||
if (functions == nullptr) {
|
if (functions == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1786,13 +1783,13 @@ void soinfo::CallArray(const char* array_name __unused, linker_function_t* funct
|
|||||||
|
|
||||||
for (int i = begin; i != end; i += step) {
|
for (int i = begin; i != end; i += step) {
|
||||||
TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]);
|
TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]);
|
||||||
CallFunction("function", functions[i]);
|
call_function("function", functions[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("[ Done calling %s for '%s' ]", array_name, name);
|
TRACE("[ Done calling %s for '%s' ]", array_name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void soinfo::CallFunction(const char* function_name __unused, linker_function_t function) {
|
void soinfo::call_function(const char* function_name __unused, linker_function_t function) {
|
||||||
if (function == nullptr || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
|
if (function == nullptr || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1806,13 +1803,13 @@ void soinfo::CallFunction(const char* function_name __unused, linker_function_t
|
|||||||
protect_data(PROT_READ | PROT_WRITE);
|
protect_data(PROT_READ | PROT_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void soinfo::CallPreInitConstructors() {
|
void soinfo::call_pre_init_constructors() {
|
||||||
// DT_PREINIT_ARRAY functions are called before any other constructors for executables,
|
// DT_PREINIT_ARRAY functions are called before any other constructors for executables,
|
||||||
// but ignored in a shared library.
|
// but ignored in a shared library.
|
||||||
CallArray("DT_PREINIT_ARRAY", preinit_array, preinit_array_count, false);
|
call_array("DT_PREINIT_ARRAY", preinit_array_, preinit_array_count_, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void soinfo::CallConstructors() {
|
void soinfo::call_constructors() {
|
||||||
if (constructors_called) {
|
if (constructors_called) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1829,34 +1826,34 @@ void soinfo::CallConstructors() {
|
|||||||
// out above, the libc constructor will be called again (recursively!).
|
// out above, the libc constructor will be called again (recursively!).
|
||||||
constructors_called = true;
|
constructors_called = true;
|
||||||
|
|
||||||
if ((flags & FLAG_EXE) == 0 && preinit_array != nullptr) {
|
if ((flags & FLAG_EXE) == 0 && preinit_array_ != nullptr) {
|
||||||
// The GNU dynamic linker silently ignores these, but we warn the developer.
|
// The GNU dynamic linker silently ignores these, but we warn the developer.
|
||||||
PRINT("\"%s\": ignoring %zd-entry DT_PREINIT_ARRAY in shared library!",
|
PRINT("\"%s\": ignoring %zd-entry DT_PREINIT_ARRAY in shared library!",
|
||||||
name, preinit_array_count);
|
name, preinit_array_count_);
|
||||||
}
|
}
|
||||||
|
|
||||||
get_children().for_each([] (soinfo* si) {
|
get_children().for_each([] (soinfo* si) {
|
||||||
si->CallConstructors();
|
si->call_constructors();
|
||||||
});
|
});
|
||||||
|
|
||||||
TRACE("\"%s\": calling constructors", name);
|
TRACE("\"%s\": calling constructors", name);
|
||||||
|
|
||||||
// DT_INIT should be called before DT_INIT_ARRAY if both are present.
|
// DT_INIT should be called before DT_INIT_ARRAY if both are present.
|
||||||
CallFunction("DT_INIT", init_func);
|
call_function("DT_INIT", init_func_);
|
||||||
CallArray("DT_INIT_ARRAY", init_array, init_array_count, false);
|
call_array("DT_INIT_ARRAY", init_array_, init_array_count_, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void soinfo::CallDestructors() {
|
void soinfo::call_destructors() {
|
||||||
if (!constructors_called) {
|
if (!constructors_called) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TRACE("\"%s\": calling destructors", name);
|
TRACE("\"%s\": calling destructors", name);
|
||||||
|
|
||||||
// DT_FINI_ARRAY must be parsed in reverse order.
|
// DT_FINI_ARRAY must be parsed in reverse order.
|
||||||
CallArray("DT_FINI_ARRAY", fini_array, fini_array_count, true);
|
call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true);
|
||||||
|
|
||||||
// DT_FINI should be called after DT_FINI_ARRAY if both are present.
|
// DT_FINI should be called after DT_FINI_ARRAY if both are present.
|
||||||
CallFunction("DT_FINI", fini_func);
|
call_function("DT_FINI", fini_func_);
|
||||||
|
|
||||||
// This is needed on second call to dlopen
|
// This is needed on second call to dlopen
|
||||||
// after library has been unloaded with RTLD_NODELETE
|
// after library has been unloaded with RTLD_NODELETE
|
||||||
@ -1865,8 +1862,8 @@ void soinfo::CallDestructors() {
|
|||||||
|
|
||||||
void soinfo::add_child(soinfo* child) {
|
void soinfo::add_child(soinfo* child) {
|
||||||
if (has_min_version(0)) {
|
if (has_min_version(0)) {
|
||||||
child->parents.push_back(this);
|
child->parents_.push_back(this);
|
||||||
this->children.push_back(child);
|
this->children_.push_back(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1876,26 +1873,26 @@ void soinfo::remove_all_links() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1. Untie connected soinfos from 'this'.
|
// 1. Untie connected soinfos from 'this'.
|
||||||
children.for_each([&] (soinfo* child) {
|
children_.for_each([&] (soinfo* child) {
|
||||||
child->parents.remove_if([&] (const soinfo* parent) {
|
child->parents_.remove_if([&] (const soinfo* parent) {
|
||||||
return parent == this;
|
return parent == this;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
parents.for_each([&] (soinfo* parent) {
|
parents_.for_each([&] (soinfo* parent) {
|
||||||
parent->children.remove_if([&] (const soinfo* child) {
|
parent->children_.remove_if([&] (const soinfo* child) {
|
||||||
return child == this;
|
return child == this;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2. Once everything untied - clear local lists.
|
// 2. Once everything untied - clear local lists.
|
||||||
parents.clear();
|
parents_.clear();
|
||||||
children.clear();
|
children_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_t soinfo::get_st_dev() const {
|
dev_t soinfo::get_st_dev() const {
|
||||||
if (has_min_version(0)) {
|
if (has_min_version(0)) {
|
||||||
return st_dev;
|
return st_dev_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1903,7 +1900,7 @@ dev_t soinfo::get_st_dev() const {
|
|||||||
|
|
||||||
ino_t soinfo::get_st_ino() const {
|
ino_t soinfo::get_st_ino() const {
|
||||||
if (has_min_version(0)) {
|
if (has_min_version(0)) {
|
||||||
return st_ino;
|
return st_ino_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1911,7 +1908,7 @@ ino_t soinfo::get_st_ino() const {
|
|||||||
|
|
||||||
off64_t soinfo::get_file_offset() const {
|
off64_t soinfo::get_file_offset() const {
|
||||||
if (has_min_version(1)) {
|
if (has_min_version(1)) {
|
||||||
return file_offset;
|
return file_offset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1919,7 +1916,7 @@ off64_t soinfo::get_file_offset() const {
|
|||||||
|
|
||||||
uint32_t soinfo::get_rtld_flags() const {
|
uint32_t soinfo::get_rtld_flags() const {
|
||||||
if (has_min_version(1)) {
|
if (has_min_version(1)) {
|
||||||
return rtld_flags;
|
return rtld_flags_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1927,7 +1924,7 @@ uint32_t soinfo::get_rtld_flags() const {
|
|||||||
|
|
||||||
uint32_t soinfo::get_dt_flags_1() const {
|
uint32_t soinfo::get_dt_flags_1() const {
|
||||||
if (has_min_version(1)) {
|
if (has_min_version(1)) {
|
||||||
return dt_flags_1;
|
return dt_flags_1_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1935,14 +1932,14 @@ uint32_t soinfo::get_dt_flags_1() const {
|
|||||||
void soinfo::set_dt_flags_1(uint32_t dt_flags_1) {
|
void soinfo::set_dt_flags_1(uint32_t dt_flags_1) {
|
||||||
if (has_min_version(1)) {
|
if (has_min_version(1)) {
|
||||||
if ((dt_flags_1 & DF_1_GLOBAL) != 0) {
|
if ((dt_flags_1 & DF_1_GLOBAL) != 0) {
|
||||||
rtld_flags |= RTLD_GLOBAL;
|
rtld_flags_ |= RTLD_GLOBAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dt_flags_1 & DF_1_NODELETE) != 0) {
|
if ((dt_flags_1 & DF_1_NODELETE) != 0) {
|
||||||
rtld_flags |= RTLD_NODELETE;
|
rtld_flags_ |= RTLD_NODELETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->dt_flags_1 = dt_flags_1;
|
dt_flags_1_ = dt_flags_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1952,18 +1949,18 @@ static soinfo::soinfo_list_t g_empty_list;
|
|||||||
|
|
||||||
soinfo::soinfo_list_t& soinfo::get_children() {
|
soinfo::soinfo_list_t& soinfo::get_children() {
|
||||||
if (has_min_version(0)) {
|
if (has_min_version(0)) {
|
||||||
return this->children;
|
return children_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_empty_list;
|
return g_empty_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
soinfo::soinfo_list_t& soinfo::get_parents() {
|
soinfo::soinfo_list_t& soinfo::get_parents() {
|
||||||
if ((this->flags & FLAG_NEW_SOINFO) == 0) {
|
if (has_min_version(0)) {
|
||||||
return g_empty_list;
|
return parents_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->parents;
|
return g_empty_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfW(Addr) soinfo::resolve_symbol_address(ElfW(Sym)* s) {
|
ElfW(Addr) soinfo::resolve_symbol_address(ElfW(Sym)* s) {
|
||||||
@ -1975,11 +1972,11 @@ ElfW(Addr) soinfo::resolve_symbol_address(ElfW(Sym)* s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* soinfo::get_string(ElfW(Word) index) const {
|
const char* soinfo::get_string(ElfW(Word) index) const {
|
||||||
if (has_min_version(1) && (index >= strtab_size)) {
|
if (has_min_version(1) && (index >= strtab_size_)) {
|
||||||
__libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d", name, strtab_size, index);
|
__libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d", name, strtab_size_, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return strtab + index;
|
return strtab_ + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool soinfo::is_gnu_hash() const {
|
bool soinfo::is_gnu_hash() const {
|
||||||
@ -2051,7 +2048,7 @@ static int nullify_closed_stdio() {
|
|||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool soinfo::PrelinkImage() {
|
bool soinfo::prelink_image() {
|
||||||
/* Extract dynamic section */
|
/* Extract dynamic section */
|
||||||
ElfW(Word) dynamic_flags = 0;
|
ElfW(Word) dynamic_flags = 0;
|
||||||
phdr_table_get_dynamic_section(phdr, phnum, load_bias, &dynamic, &dynamic_flags);
|
phdr_table_get_dynamic_section(phdr, phnum, load_bias, &dynamic, &dynamic_flags);
|
||||||
@ -2091,52 +2088,52 @@ bool soinfo::PrelinkImage() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_HASH:
|
case DT_HASH:
|
||||||
if (nbucket != 0) {
|
if (nbucket_ != 0) {
|
||||||
// in case of --hash-style=both, we prefer gnu
|
// in case of --hash-style=both, we prefer gnu
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
|
nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
|
||||||
nchain = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
|
nchain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
|
||||||
bucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8);
|
bucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8);
|
||||||
chain = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8 + nbucket * 4);
|
chain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8 + nbucket_ * 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_GNU_HASH:
|
case DT_GNU_HASH:
|
||||||
if (nbucket != 0) {
|
if (nbucket_ != 0) {
|
||||||
// in case of --hash-style=both, we prefer gnu
|
// in case of --hash-style=both, we prefer gnu
|
||||||
nchain = 0;
|
nchain_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
|
nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
|
||||||
// skip symndx
|
// skip symndx
|
||||||
gnu_maskwords = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[2];
|
gnu_maskwords_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[2];
|
||||||
gnu_shift2 = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[3];
|
gnu_shift2_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[3];
|
||||||
|
|
||||||
gnu_bloom_filter = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
|
gnu_bloom_filter_ = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
|
||||||
bucket = reinterpret_cast<uint32_t*>(gnu_bloom_filter + gnu_maskwords);
|
bucket_ = reinterpret_cast<uint32_t*>(gnu_bloom_filter_ + gnu_maskwords_);
|
||||||
// amend chain for symndx = header[1]
|
// amend chain for symndx = header[1]
|
||||||
chain = bucket + nbucket - reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
|
chain_ = bucket_ + nbucket_ - reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
|
||||||
|
|
||||||
if (!powerof2(gnu_maskwords)) {
|
if (!powerof2(gnu_maskwords_)) {
|
||||||
DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two", gnu_maskwords, name);
|
DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two", gnu_maskwords_, name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
--gnu_maskwords;
|
--gnu_maskwords_;
|
||||||
|
|
||||||
flags |= FLAG_GNU_HASH;
|
flags |= FLAG_GNU_HASH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_STRTAB:
|
case DT_STRTAB:
|
||||||
strtab = reinterpret_cast<const char*>(load_bias + d->d_un.d_ptr);
|
strtab_ = reinterpret_cast<const char*>(load_bias + d->d_un.d_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_STRSZ:
|
case DT_STRSZ:
|
||||||
strtab_size = d->d_un.d_val;
|
strtab_size_ = d->d_un.d_val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_SYMTAB:
|
case DT_SYMTAB:
|
||||||
symtab = reinterpret_cast<ElfW(Sym)*>(load_bias + d->d_un.d_ptr);
|
symtab_ = reinterpret_cast<ElfW(Sym)*>(load_bias + d->d_un.d_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_SYMENT:
|
case DT_SYMENT:
|
||||||
@ -2162,24 +2159,24 @@ bool soinfo::PrelinkImage() {
|
|||||||
|
|
||||||
case DT_JMPREL:
|
case DT_JMPREL:
|
||||||
#if defined(USE_RELA)
|
#if defined(USE_RELA)
|
||||||
plt_rela = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
|
plt_rela_ = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
|
||||||
#else
|
#else
|
||||||
plt_rel = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
|
plt_rel_ = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_PLTRELSZ:
|
case DT_PLTRELSZ:
|
||||||
#if defined(USE_RELA)
|
#if defined(USE_RELA)
|
||||||
plt_rela_count = d->d_un.d_val / sizeof(ElfW(Rela));
|
plt_rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
|
||||||
#else
|
#else
|
||||||
plt_rel_count = d->d_un.d_val / sizeof(ElfW(Rel));
|
plt_rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_PLTGOT:
|
case DT_PLTGOT:
|
||||||
#if defined(__mips__)
|
#if defined(__mips__)
|
||||||
// Used by mips and mips64.
|
// Used by mips and mips64.
|
||||||
plt_got = reinterpret_cast<ElfW(Addr)**>(load_bias + d->d_un.d_ptr);
|
plt_got_ = reinterpret_cast<ElfW(Addr)**>(load_bias + d->d_un.d_ptr);
|
||||||
#endif
|
#endif
|
||||||
// Ignore for other platforms... (because RTLD_LAZY is not supported)
|
// Ignore for other platforms... (because RTLD_LAZY is not supported)
|
||||||
break;
|
break;
|
||||||
@ -2199,11 +2196,11 @@ bool soinfo::PrelinkImage() {
|
|||||||
#endif
|
#endif
|
||||||
#if defined(USE_RELA)
|
#if defined(USE_RELA)
|
||||||
case DT_RELA:
|
case DT_RELA:
|
||||||
rela = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
|
rela_ = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_RELASZ:
|
case DT_RELASZ:
|
||||||
rela_count = d->d_un.d_val / sizeof(ElfW(Rela));
|
rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_RELAENT:
|
case DT_RELAENT:
|
||||||
@ -2226,11 +2223,11 @@ bool soinfo::PrelinkImage() {
|
|||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
case DT_REL:
|
case DT_REL:
|
||||||
rel = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
|
rel_ = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_RELSZ:
|
case DT_RELSZ:
|
||||||
rel_count = d->d_un.d_val / sizeof(ElfW(Rel));
|
rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_RELENT:
|
case DT_RELENT:
|
||||||
@ -2252,40 +2249,40 @@ bool soinfo::PrelinkImage() {
|
|||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
case DT_INIT:
|
case DT_INIT:
|
||||||
init_func = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
|
init_func_ = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
|
||||||
DEBUG("%s constructors (DT_INIT) found at %p", name, init_func);
|
DEBUG("%s constructors (DT_INIT) found at %p", name, init_func_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_FINI:
|
case DT_FINI:
|
||||||
fini_func = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
|
fini_func_ = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
|
||||||
DEBUG("%s destructors (DT_FINI) found at %p", name, fini_func);
|
DEBUG("%s destructors (DT_FINI) found at %p", name, fini_func_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_INIT_ARRAY:
|
case DT_INIT_ARRAY:
|
||||||
init_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
|
init_array_ = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
|
||||||
DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", name, init_array);
|
DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", name, init_array_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_INIT_ARRAYSZ:
|
case DT_INIT_ARRAYSZ:
|
||||||
init_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
|
init_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_FINI_ARRAY:
|
case DT_FINI_ARRAY:
|
||||||
fini_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
|
fini_array_ = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
|
||||||
DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", name, fini_array);
|
DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", name, fini_array_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_FINI_ARRAYSZ:
|
case DT_FINI_ARRAYSZ:
|
||||||
fini_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
|
fini_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_PREINIT_ARRAY:
|
case DT_PREINIT_ARRAY:
|
||||||
preinit_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
|
preinit_array_ = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
|
||||||
DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", name, preinit_array);
|
DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", name, preinit_array_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_PREINIT_ARRAYSZ:
|
case DT_PREINIT_ARRAYSZ:
|
||||||
preinit_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
|
preinit_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_TEXTREL:
|
case DT_TEXTREL:
|
||||||
@ -2342,15 +2339,15 @@ bool soinfo::PrelinkImage() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_MIPS_SYMTABNO:
|
case DT_MIPS_SYMTABNO:
|
||||||
mips_symtabno = d->d_un.d_val;
|
mips_symtabno_ = d->d_un.d_val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_MIPS_LOCAL_GOTNO:
|
case DT_MIPS_LOCAL_GOTNO:
|
||||||
mips_local_gotno = d->d_un.d_val;
|
mips_local_gotno_ = d->d_un.d_val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_MIPS_GOTSYM:
|
case DT_MIPS_GOTSYM:
|
||||||
mips_gotsym = d->d_un.d_val;
|
mips_gotsym_ = d->d_un.d_val;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
// Ignored: "Its use has been superseded by the DF_BIND_NOW flag"
|
// Ignored: "Its use has been superseded by the DF_BIND_NOW flag"
|
||||||
@ -2373,29 +2370,29 @@ bool soinfo::PrelinkImage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
|
DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
|
||||||
reinterpret_cast<void*>(base), strtab, symtab);
|
reinterpret_cast<void*>(base), strtab_, symtab_);
|
||||||
|
|
||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
if (relocating_linker && needed_count != 0) {
|
if (relocating_linker && needed_count != 0) {
|
||||||
DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");
|
DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (nbucket == 0) {
|
if (nbucket_ == 0) {
|
||||||
DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" (new hash type from the future?)", name);
|
DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" (new hash type from the future?)", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (strtab == 0) {
|
if (strtab_ == 0) {
|
||||||
DL_ERR("empty/missing DT_STRTAB in \"%s\"", name);
|
DL_ERR("empty/missing DT_STRTAB in \"%s\"", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (symtab == 0) {
|
if (symtab_ == 0) {
|
||||||
DL_ERR("empty/missing DT_SYMTAB in \"%s\"", name);
|
DL_ERR("empty/missing DT_SYMTAB in \"%s\"", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool soinfo::LinkImage(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo) {
|
bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo) {
|
||||||
|
|
||||||
#if !defined(__LP64__)
|
#if !defined(__LP64__)
|
||||||
if (has_text_relocations) {
|
if (has_text_relocations) {
|
||||||
@ -2412,28 +2409,28 @@ bool soinfo::LinkImage(const soinfo_list_t& global_group, const soinfo_list_t& l
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_RELA)
|
#if defined(USE_RELA)
|
||||||
if (rela != nullptr) {
|
if (rela_ != nullptr) {
|
||||||
DEBUG("[ relocating %s ]", name);
|
DEBUG("[ relocating %s ]", name);
|
||||||
if (Relocate(rela, rela_count, global_group, local_group)) {
|
if (relocate(rela_, rela_count_, global_group, local_group)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (plt_rela != nullptr) {
|
if (plt_rela_ != nullptr) {
|
||||||
DEBUG("[ relocating %s plt ]", name);
|
DEBUG("[ relocating %s plt ]", name);
|
||||||
if (Relocate(plt_rela, plt_rela_count, global_group, local_group)) {
|
if (relocate(plt_rela_, plt_rela_count_, global_group, local_group)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (rel != nullptr) {
|
if (rel_ != nullptr) {
|
||||||
DEBUG("[ relocating %s ]", name);
|
DEBUG("[ relocating %s ]", name);
|
||||||
if (Relocate(rel, rel_count, global_group, local_group)) {
|
if (relocate(rel_, rel_count_, global_group, local_group)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (plt_rel != nullptr) {
|
if (plt_rel_ != nullptr) {
|
||||||
DEBUG("[ relocating %s plt ]", name);
|
DEBUG("[ relocating %s plt ]", name);
|
||||||
if (Relocate(plt_rel, plt_rel_count, global_group, local_group)) {
|
if (relocate(plt_rel_, plt_rel_count_, global_group, local_group)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2506,8 +2503,8 @@ static void add_vdso(KernelArgumentBlock& args __unused) {
|
|||||||
si->size = phdr_table_get_load_size(si->phdr, si->phnum);
|
si->size = phdr_table_get_load_size(si->phdr, si->phnum);
|
||||||
si->load_bias = get_elf_exec_load_bias(ehdr_vdso);
|
si->load_bias = get_elf_exec_load_bias(ehdr_vdso);
|
||||||
|
|
||||||
si->PrelinkImage();
|
si->prelink_image();
|
||||||
si->LinkImage(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr);
|
si->link_image(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2636,7 +2633,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
|
|||||||
|
|
||||||
somain = si;
|
somain = si;
|
||||||
|
|
||||||
si->PrelinkImage();
|
si->prelink_image();
|
||||||
|
|
||||||
// add somain to global group
|
// add somain to global group
|
||||||
si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
|
si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
|
||||||
@ -2667,15 +2664,15 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
|
|||||||
|
|
||||||
add_vdso(args);
|
add_vdso(args);
|
||||||
|
|
||||||
si->CallPreInitConstructors();
|
si->call_pre_init_constructors();
|
||||||
|
|
||||||
/* After the PrelinkImage, the si->load_bias is initialized.
|
/* After the prelink_image, the si->load_bias is initialized.
|
||||||
* For so lib, the map->l_addr will be updated in notify_gdb_of_load.
|
* For so lib, the map->l_addr will be updated in notify_gdb_of_load.
|
||||||
* We need to update this value for so exe here. So Unwind_Backtrace
|
* We need to update this value for so exe here. So Unwind_Backtrace
|
||||||
* for some arch like x86 could work correctly within so exe.
|
* for some arch like x86 could work correctly within so exe.
|
||||||
*/
|
*/
|
||||||
map->l_addr = si->load_bias;
|
map->l_addr = si->load_bias;
|
||||||
si->CallConstructors();
|
si->call_constructors();
|
||||||
|
|
||||||
#if TIMING
|
#if TIMING
|
||||||
gettimeofday(&t1, nullptr);
|
gettimeofday(&t1, nullptr);
|
||||||
@ -2790,7 +2787,7 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
|
|||||||
// itself without having to look into local_group and (2) allocators
|
// itself without having to look into local_group and (2) allocators
|
||||||
// are not yet initialized, and therefore we cannot use linked_list.push_*
|
// are not yet initialized, and therefore we cannot use linked_list.push_*
|
||||||
// functions at this point.
|
// functions at this point.
|
||||||
if (!(linker_so.PrelinkImage() && linker_so.LinkImage(g_empty_list, g_empty_list, nullptr))) {
|
if (!(linker_so.prelink_image() && linker_so.link_image(g_empty_list, g_empty_list, nullptr))) {
|
||||||
// It would be nice to print an error message, but if the linker
|
// It would be nice to print an error message, but if the linker
|
||||||
// can't link itself, there's no guarantee that we'll be able to
|
// can't link itself, there's no guarantee that we'll be able to
|
||||||
// call write() (because it involves a GOT reference). We may as
|
// call write() (because it involves a GOT reference). We may as
|
||||||
@ -2805,7 +2802,7 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
|
|||||||
__libc_init_tls(args);
|
__libc_init_tls(args);
|
||||||
|
|
||||||
// Initialize the linker's own global variables
|
// Initialize the linker's own global variables
|
||||||
linker_so.CallConstructors();
|
linker_so.call_constructors();
|
||||||
|
|
||||||
// Initialize static variables. Note that in order to
|
// Initialize static variables. Note that in order to
|
||||||
// get correct libdl_info we need to call constructors
|
// get correct libdl_info we need to call constructors
|
||||||
|
101
linker/linker.h
101
linker/linker.h
@ -164,60 +164,60 @@ struct soinfo {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* strtab;
|
const char* strtab_;
|
||||||
ElfW(Sym)* symtab;
|
ElfW(Sym)* symtab_;
|
||||||
|
|
||||||
size_t nbucket;
|
size_t nbucket_;
|
||||||
size_t nchain;
|
size_t nchain_;
|
||||||
uint32_t* bucket;
|
uint32_t* bucket_;
|
||||||
uint32_t* chain;
|
uint32_t* chain_;
|
||||||
|
|
||||||
public:
|
|
||||||
#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
|
||||||
// all 32-bit architectures to preserve binary compatibility.
|
// all 32-bit architectures to preserve binary compatibility.
|
||||||
ElfW(Addr)** plt_got;
|
ElfW(Addr)** plt_got_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_RELA)
|
#if defined(USE_RELA)
|
||||||
ElfW(Rela)* plt_rela;
|
ElfW(Rela)* plt_rela_;
|
||||||
size_t plt_rela_count;
|
size_t plt_rela_count_;
|
||||||
|
|
||||||
ElfW(Rela)* rela;
|
ElfW(Rela)* rela_;
|
||||||
size_t rela_count;
|
size_t rela_count_;
|
||||||
#else
|
#else
|
||||||
ElfW(Rel)* plt_rel;
|
ElfW(Rel)* plt_rel_;
|
||||||
size_t plt_rel_count;
|
size_t plt_rel_count_;
|
||||||
|
|
||||||
ElfW(Rel)* rel;
|
ElfW(Rel)* rel_;
|
||||||
size_t rel_count;
|
size_t rel_count_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
linker_function_t* preinit_array;
|
linker_function_t* preinit_array_;
|
||||||
size_t preinit_array_count;
|
size_t preinit_array_count_;
|
||||||
|
|
||||||
linker_function_t* init_array;
|
linker_function_t* init_array_;
|
||||||
size_t init_array_count;
|
size_t init_array_count_;
|
||||||
linker_function_t* fini_array;
|
linker_function_t* fini_array_;
|
||||||
size_t fini_array_count;
|
size_t fini_array_count_;
|
||||||
|
|
||||||
linker_function_t init_func;
|
linker_function_t init_func_;
|
||||||
linker_function_t fini_func;
|
linker_function_t fini_func_;
|
||||||
|
|
||||||
|
public:
|
||||||
#if defined(__arm__)
|
#if defined(__arm__)
|
||||||
// ARM EABI section used for stack unwinding.
|
// ARM EABI section used for stack unwinding.
|
||||||
uint32_t* ARM_exidx;
|
uint32_t* ARM_exidx;
|
||||||
size_t ARM_exidx_count;
|
size_t ARM_exidx_count;
|
||||||
#elif defined(__mips__)
|
#elif defined(__mips__)
|
||||||
private:
|
private:
|
||||||
uint32_t mips_symtabno;
|
uint32_t mips_symtabno_;
|
||||||
uint32_t mips_local_gotno;
|
uint32_t mips_local_gotno_;
|
||||||
uint32_t mips_gotsym;
|
uint32_t mips_gotsym_;
|
||||||
bool mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
bool mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
||||||
|
|
||||||
public:
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
size_t ref_count;
|
size_t ref_count;
|
||||||
link_map link_map_head;
|
link_map link_map_head;
|
||||||
|
|
||||||
@ -232,13 +232,14 @@ struct soinfo {
|
|||||||
#endif
|
#endif
|
||||||
bool has_DT_SYMBOLIC;
|
bool has_DT_SYMBOLIC;
|
||||||
|
|
||||||
|
public:
|
||||||
soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags);
|
soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags);
|
||||||
|
|
||||||
void CallConstructors();
|
void call_constructors();
|
||||||
void CallDestructors();
|
void call_destructors();
|
||||||
void CallPreInitConstructors();
|
void call_pre_init_constructors();
|
||||||
bool PrelinkImage();
|
bool prelink_image();
|
||||||
bool LinkImage(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo);
|
bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo);
|
||||||
|
|
||||||
void add_child(soinfo* child);
|
void add_child(soinfo* child);
|
||||||
void remove_all_links();
|
void remove_all_links();
|
||||||
@ -263,7 +264,7 @@ struct soinfo {
|
|||||||
bool is_gnu_hash() const;
|
bool is_gnu_hash() 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:
|
||||||
@ -272,38 +273,38 @@ struct soinfo {
|
|||||||
ElfW(Sym)* gnu_lookup(SymbolName& symbol_name);
|
ElfW(Sym)* gnu_lookup(SymbolName& symbol_name);
|
||||||
ElfW(Sym)* gnu_addr_lookup(const void* addr);
|
ElfW(Sym)* gnu_addr_lookup(const void* addr);
|
||||||
|
|
||||||
void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
|
void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
|
||||||
void CallFunction(const char* function_name, linker_function_t function);
|
void call_function(const char* function_name, linker_function_t function);
|
||||||
#if defined(USE_RELA)
|
#if defined(USE_RELA)
|
||||||
int Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
int relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
||||||
#else
|
#else
|
||||||
int Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
int relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This part of the structure is only available
|
// This part of the structure is only available
|
||||||
// when FLAG_NEW_SOINFO is set in this->flags.
|
// when FLAG_NEW_SOINFO is set in this->flags.
|
||||||
uint32_t version;
|
uint32_t version_;
|
||||||
|
|
||||||
// version >= 0
|
// version >= 0
|
||||||
dev_t st_dev;
|
dev_t st_dev_;
|
||||||
ino_t st_ino;
|
ino_t st_ino_;
|
||||||
|
|
||||||
// dependency graph
|
// dependency graph
|
||||||
soinfo_list_t children;
|
soinfo_list_t children_;
|
||||||
soinfo_list_t parents;
|
soinfo_list_t parents_;
|
||||||
|
|
||||||
// version >= 1
|
// version >= 1
|
||||||
off64_t file_offset;
|
off64_t file_offset_;
|
||||||
uint32_t rtld_flags;
|
uint32_t rtld_flags_;
|
||||||
uint32_t dt_flags_1;
|
uint32_t dt_flags_1_;
|
||||||
size_t strtab_size;
|
size_t strtab_size_;
|
||||||
|
|
||||||
// version >= 2
|
// version >= 2
|
||||||
uint32_t gnu_maskwords;
|
uint32_t gnu_maskwords_;
|
||||||
uint32_t gnu_shift2;
|
uint32_t gnu_shift2_;
|
||||||
|
|
||||||
ElfW(Addr)* gnu_bloom_filter;
|
ElfW(Addr)* gnu_bloom_filter_;
|
||||||
|
|
||||||
friend soinfo* get_libdl_info();
|
friend soinfo* get_libdl_info();
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user