summaryrefslogtreecommitdiff
path: root/ldso/ldso/dl-hash.c
diff options
context:
space:
mode:
authorAustin Foxley <austinf@cetoncorp.com>2009-09-19 10:04:05 -0700
committerAustin Foxley <austinf@cetoncorp.com>2009-09-26 09:37:18 -0700
commit534661b91c98492995274c364c8177c45efc63db (patch)
tree333c655a3159fdb72a693a7335ba347094dfd57a /ldso/ldso/dl-hash.c
parentd21497f9fba95688e464ae712bd6b4c0fbc4ea13 (diff)
ldso/: tls support for dynamic linker
Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
Diffstat (limited to 'ldso/ldso/dl-hash.c')
-rw-r--r--ldso/ldso/dl-hash.c87
1 files changed, 44 insertions, 43 deletions
diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c
index 4809c4348..3103d9f0b 100644
--- a/ldso/ldso/dl-hash.c
+++ b/ldso/ldso/dl-hash.c
@@ -157,18 +157,29 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
static __attribute_noinline__ const ElfW(Sym) *
check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int type_class)
{
- if (type_class & (sym->st_shndx == SHN_UNDEF))
- /* undefined symbol itself */
- return NULL;
-#ifdef __mips__
- if (sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT))
- return NULL;
-#endif
-
- if (sym->st_value == 0)
- /* No value */
- return NULL;
+#if USE_TLS
+ if((sym->st_value == 0 && (ELF_ST_TYPE(sym->st_info) != STT_TLS))
+ || (type_class & (sym->st_shndx == SHN_UNDEF)))
+ /* No value or undefined symbol itself */
+ return NULL;
+
+ if(ELF_ST_TYPE(sym->st_info) > STT_FUNC
+ && ELF_ST_TYPE(sym->st_info) != STT_COMMON
+ && ELF_ST_TYPE(sym->st_info) != STT_TLS)
+ /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC and STT_COMMON
+ * entries (and STT_TLS if TLS is supported) since these
+ * are no code/data definitions.
+ */
+ return NULL;
+#else
+ if (type_class & (sym->st_shndx == SHN_UNDEF))
+ /* undefined symbol itself */
+ return NULL;
+
+ if (sym->st_value == 0)
+ /* No value */
+ return NULL;
if (ELF_ST_TYPE(sym->st_info) > STT_FUNC
&& ELF_ST_TYPE(sym->st_info) != STT_COMMON)
@@ -177,7 +188,7 @@ check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int typ
* code/data definitions
*/
return NULL;
-
+#endif
if (_dl_strcmp(strtab + sym->st_name, undef_name) != 0)
return NULL;
@@ -257,12 +268,11 @@ _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_lookup_hash(const char *name, struct dyn_elf *rpnt,
- struct elf_resolve *mytpnt, int type_class
-#ifdef __FDPIC__
- , struct elf_resolve **tpntp
-#endif
- )
+char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, int type_class
+#if USE_TLS
+,struct elf_resolve **tls_tpnt
+#endif
+)
{
struct elf_resolve *tpnt = NULL;
ElfW(Sym) *symtab;
@@ -270,8 +280,7 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt,
unsigned long elf_hash_number = 0xffffffff;
const ElfW(Sym) *sym = NULL;
- const ElfW(Sym) *weak_sym = 0;
- struct elf_resolve *weak_tpnt = 0;
+ char *weak_result = NULL;
#ifdef __LDSO_GNU_HASH_SUPPORT__
unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name);
@@ -329,37 +338,29 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt,
if (sym) {
/* At this point we have found the requested symbol, do binding */
+#if USE_TLS
+ if(ELF_ST_TYPE(sym->st_info) == STT_TLS) {
+ _dl_assert((tls_tpnt != NULL));
+ *tls_tpnt = tpnt;
+
+ return (char*)sym->st_value;
+ }
+#endif
+
switch (ELF_ST_BIND(sym->st_info)) {
case STB_WEAK:
#if 0
-/* Perhaps we should support old style weak symbol handling
- * per what glibc does when you export LD_DYNAMIC_WEAK */
- if (!weak_sym) {
- weak_tpnt = tpnt;
- weak_sym = sym;
- }
+ /* 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 *)tpnt->loadaddr + sym->st_value;
break;
#endif
case STB_GLOBAL:
-#ifdef __FDPIC__
- if (tpntp)
- *tpntp = tpnt;
-#endif
- return (char *) DL_FIND_HASH_VALUE (tpnt, type_class, sym);
+ return (char*)tpnt->loadaddr + sym->st_value;
default: /* Local symbols not handled here */
break;
}
}
- if (weak_sym) {
-#ifdef __FDPIC__
- if (tpntp)
- *tpntp = weak_tpnt;
-#endif
- return (char *) DL_FIND_HASH_VALUE (weak_tpnt, type_class, weak_sym);
- }
-#ifdef __FDPIC__
- if (tpntp)
- *tpntp = NULL;
-#endif
- return NULL;
+ return weak_result;
}