diff options
author | Eric Andersen <andersen@codepoet.org> | 2006-11-10 20:41:49 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2006-11-10 20:41:49 +0000 |
commit | 5be7aba864225afa0538d166e6166ffe05af4288 (patch) | |
tree | 79000b2a1e5e81757da1ca77bbd7380e26b89720 /ldso/ldso/dl-hash.c | |
parent | 90c3c3ed5eec1062168d1ac0beb41044a9de7c58 (diff) |
This change reimplements the ARM _dl_linux_resolve entry point - this is
called to resolve DLL PLT entries. The assembler is changed to be thumb
compatible and slightly faster, the C function, _dl_linux_resolver (note
the extra r) is changed to take a byte address in place of an 8 byte
count (faster in caller and callee, and slightly easier to understand).
Diffstat (limited to 'ldso/ldso/dl-hash.c')
-rw-r--r-- | ldso/ldso/dl-hash.c | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 4fd7ba0b7..26022ff79 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -123,7 +123,6 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, return tpnt; } - /* * 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. @@ -167,30 +166,53 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve * strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) { + char *result; sym = &symtab[si]; - if (type_class & (sym->st_shndx == SHN_UNDEF)) - continue; - if (_dl_strcmp(strtab + sym->st_name, name) != 0) - continue; - if (sym->st_value == 0) - continue; - if (ELF_ST_TYPE(sym->st_info) > STT_FUNC) - continue; - - switch (ELF_ST_BIND(sym->st_info)) { - case STB_WEAK: + if (sym->st_shndx == SHN_UNDEF) + continue; + if (ELF_ST_TYPE(sym->st_info) > STT_FUNC +#if defined(__arm__) || defined(__thumb__) + /* On ARM (only) STT_ARM_TFUNC is a function + * and has a value >STT_FUNC, so this must + * be checked specially. + */ + && ELF_ST_TYPE(sym->st_info) != STT_ARM_TFUNC +#endif + ) + continue; + if (_dl_strcmp(strtab + sym->st_name, name) != 0) + continue; #if 0 -/* Perhaps we should support old style weak symbol handling - * per what glibc does when you export LD_DYNAMIC_WEAK */ - if (!weak_result) - weak_result = (char *) DL_RELOC_ADDR(tpnt->loadaddr, sym->st_value); - break; + /* I don't know how to write this test - need to test shndx + * to see if it is the PLT for this module. + */ + if ((type_class & ELF_RTYPE_CLASS_PLT) && some test) + continue; +#endif + +#if defined(__arm__) || defined(__thumb__) + /* On ARM the caller needs to know that STT_ARM_TFUNC + * is a thumb function call, this is now indicated by + * setting the low bit of the value (and newer binutils + * will do this and record STT_FUNC). + */ + result = (char*)tpnt->loadaddr + (sym->st_value | + (ELF_ST_TYPE(sym->st_info) == STT_ARM_TFUNC)); +#else + result = (char*)tpnt->loadaddr + sym->st_value; #endif - case STB_GLOBAL: - return (char*) DL_RELOC_ADDR(tpnt->loadaddr, sym->st_value); + switch (ELF_ST_BIND(sym->st_info)) { + case STB_WEAK: + /* Record for use later if we can't find a global. */ + if (!weak_result) + weak_result = result; + break; + + case STB_GLOBAL: + return result; default: /* Local symbols not handled here */ - break; + break; } } } |