From 5be7aba864225afa0538d166e6166ffe05af4288 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Fri, 10 Nov 2006 20:41:49 +0000 Subject: 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). --- ldso/ldso/dl-hash.c | 62 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 20 deletions(-) (limited to 'ldso/ldso/dl-hash.c') 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; } } } -- cgit v1.2.3