summaryrefslogtreecommitdiff
path: root/ldso/ldso/dl-hash.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2006-11-10 20:41:49 +0000
committerEric Andersen <andersen@codepoet.org>2006-11-10 20:41:49 +0000
commit5be7aba864225afa0538d166e6166ffe05af4288 (patch)
tree79000b2a1e5e81757da1ca77bbd7380e26b89720 /ldso/ldso/dl-hash.c
parent90c3c3ed5eec1062168d1ac0beb41044a9de7c58 (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.c62
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;
}
}
}