diff options
| author | Austin Foxley <austinf@cetoncorp.com> | 2009-09-23 11:49:50 -0700 |
|---|---|---|
| committer | Austin Foxley <austinf@cetoncorp.com> | 2009-09-23 11:50:00 -0700 |
| commit | 7fbbd4a33770e98118f81dfcb92cb0da630a5806 (patch) | |
| tree | aeba90bc0539149530d8881775f6a827cbfd6bb8 | |
| parent | d74b8a68d450072ee3c6e6b586d32ff38e88f840 (diff) | |
| download | uClibc-alpine-7fbbd4a33770e98118f81dfcb92cb0da630a5806.tar.bz2 uClibc-alpine-7fbbd4a33770e98118f81dfcb92cb0da630a5806.tar.xz | |
add i386 ldso tls support
only for the basic reloc types for now
Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
| -rw-r--r-- | ldso/ldso/i386/dl-sysdep.h | 4 | ||||
| -rw-r--r-- | ldso/ldso/i386/elfinterp.c | 30 |
2 files changed, 31 insertions, 3 deletions
diff --git a/ldso/ldso/i386/dl-sysdep.h b/ldso/ldso/i386/dl-sysdep.h index 0a4c56a99..a66c80212 100644 --- a/ldso/ldso/i386/dl-sysdep.h +++ b/ldso/ldso/i386/dl-sysdep.h @@ -31,7 +31,9 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one of the main executable's symbols, as for a COPY reloc. */ #define elf_machine_type_class(type) \ - ((((type) == R_386_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + ((((type) == R_386_JMP_SLOT || (type) == R_386_TLS_DTPMOD32 \ + || (type) == R_386_TLS_DTPOFF32 || (type) == R_386_TLS_TPOFF32 \ + || (type) == R_386_TLS_TPOFF) * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY)) /* Return the link-time address of _DYNAMIC. Conveniently, this is the diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index 9a0885f8c..af0b397d0 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -162,6 +162,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, int reloc_type; int symtab_index; char *symname; + struct elf_resolve *tls_tpnt = 0; unsigned long *reloc_addr; unsigned long symbol_addr; #if defined (__SUPPORT_LD_DEBUG__) @@ -176,16 +177,21 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, if (symtab_index) { symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), NULL); + elf_machine_type_class(reloc_type), &tls_tpnt); /* * We want to allow undefined references to weak symbols - this * might have been intentional. We should not be linking local * symbols here, so all bases should be covered. */ - if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) + if (unlikely(!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) + && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) return 1; + } else { + symbol_addr = symtab[symtab_index].st_value; + tls_tpnt = tpnt; } + #if defined (__SUPPORT_LD_DEBUG__) old_val = *reloc_addr; @@ -222,6 +228,26 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, symtab[symtab_index].st_size); } break; +#if USE_TLS + case R_386_TLS_DTPMOD32: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + case R_386_TLS_DTPOFF32: + /* During relocation all TLS symbols are defined and used. + * Therefore the offset is already correct. */ + *reloc_addr = symbol_addr; + break; + case R_386_TLS_TPOFF32: + /* The offset is positive, backward from the thread pointer. */ + CHECK_STATIC_TLS((struct link_map*) tls_tpnt); + *reloc_addr += tls_tpnt->l_tls_offset - symbol_addr; + break; + case R_386_TLS_TPOFF: + /* The offset is negative, forward from the thread pointer. */ + CHECK_STATIC_TLS((struct link_map*) tls_tpnt); + *reloc_addr += symbol_addr - tls_tpnt->l_tls_offset; + break; +#endif default: return -1; } |
