diff options
Diffstat (limited to 'ldso/ldso/dl-hash.c')
-rw-r--r-- | ldso/ldso/dl-hash.c | 88 |
1 files changed, 48 insertions, 40 deletions
diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 0454d61bf..2ec883a86 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -146,7 +146,6 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, tpnt->chains = hash_addr; } tpnt->loadaddr = loadaddr; - tpnt->mapaddr = DL_RELOC_ADDR(loadaddr, 0); for (i = 0; i < DYNAMIC_SIZE; i++) tpnt->dynamic_info[i] = dynamic_info[i]; return tpnt; @@ -268,16 +267,18 @@ _dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long * This function resolves externals, and this is either called when we process * relocations or when we call an entry in the PLT table for the first time. */ -char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, +char *_dl_find_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt, int type_class, struct symbol_ref *sym_ref) { struct elf_resolve *tpnt = NULL; ElfW(Sym) *symtab; + int i = 0; unsigned long elf_hash_number = 0xffffffff; const ElfW(Sym) *sym = NULL; char *weak_result = NULL; + struct r_scope_elem *loop_scope; #ifdef __LDSO_GNU_HASH_SUPPORT__ unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name); @@ -288,57 +289,64 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve * if (mytpnt) tpnt = mytpnt; } else - for (; rpnt; rpnt = rpnt->next) { - tpnt = rpnt->dyn; - - if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) { - if (mytpnt == tpnt) - ; - else { - struct init_fini_list *tmp; - - for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) { - if (tmp->tpnt == tpnt) - break; + for (loop_scope = scope; loop_scope && !sym; loop_scope = loop_scope->next) { + for (i = 0; i < loop_scope->r_nlist; i++) { + tpnt = loop_scope->r_list[i]; + + if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) { + if (mytpnt == tpnt) + ; + else { + struct init_fini_list *tmp; + + for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) { + if (tmp->tpnt == tpnt) + break; + } + if (!tmp) + continue; } - if (!tmp) - continue; } - } - /* Don't search the executable when resolving a copy reloc. */ - if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable) - continue; + /* Don't search the executable when resolving a copy reloc. */ + if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable) + continue; - /* If the hash table is empty there is nothing to do here. */ - if (tpnt->nbucket == 0) - continue; + /* If the hash table is empty there is nothing to do here. */ + if (tpnt->nbucket == 0) + continue; - symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); + symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); #ifdef __LDSO_GNU_HASH_SUPPORT__ - /* Prefer GNU hash style, if any */ - if (tpnt->l_gnu_bitmask) { - sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class); - if (sym != NULL) - /* If sym has been found, do not search further */ - break; - } else { + /* Prefer GNU hash style, if any */ + if (tpnt->l_gnu_bitmask) { + sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class); + if (sym != NULL) + /* If sym has been found, do not search further */ + break; + } else { #endif - /* Use the old SysV-style hash table */ + /* Use the old SysV-style hash table */ - /* Calculate the old sysv hash number only once */ - if (elf_hash_number == 0xffffffff) - elf_hash_number = _dl_elf_hash((const unsigned char *)name); + /* Calculate the old sysv hash number only once */ + if (elf_hash_number == 0xffffffff) + elf_hash_number = _dl_elf_hash((const unsigned char *)name); - sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class); - if (sym != NULL) - break; + sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class); + if (sym != NULL) + /* If sym has been found, do not search further */ + break; #ifdef __LDSO_GNU_HASH_SUPPORT__ - } + } #endif - } /* end of for (; rpnt; rpnt = rpnt->next) { */ + } /* End of inner for */ + } if (sym) { + if (sym_ref) { + sym_ref->sym = sym; + sym_ref->tpnt = tpnt; + } /* At this point we have found the requested symbol, do binding */ #if defined(USE_TLS) && USE_TLS if (ELF_ST_TYPE(sym->st_info) == STT_TLS) { |