From 0b7acfa800444525498442032b47bfd7d066c72b Mon Sep 17 00:00:00 2001 From: Roman I Khimov Date: Tue, 4 May 2010 14:00:47 +0400 Subject: ldso: fix x86_64 R_X86_64_TPOFF64 and R_X86_64_DTPOFF64 relocations R_X86_64_TPOFF64 revealed by trivial testcase: =================================================================== #include #include int main() { void *a = &errno; printf("errno addr: %llx\n", a); __asm__("movq errno@gottpoff(%%rip), %0;\n" "add %%fs:0x0,%0;" : "=r"(a) ); printf("got errno addr: %llx\n", a); return 0; } =================================================================== The addresses application got with R_X86_64_TPOFF64 was different than the once libc internal __errno_location returned. R_X86_64_DTPOFF64 testcase is even simpler than that: =================================================================== #include #include #include #undef h_errno extern __thread int h_errno; int main() { printf("h_errno addr: %llx\n", &h_errno); printf("__h_errno_location addr: %llx\n", __h_errno_location()); return 0; } =================================================================== but needs to be linked with "-lpthread". This way we've got h_errno relocation via R_X86_64_TPOFF64 in application and h_errno relocation via R_X86_64_DTPOFF64 in libpthread which has its own __h_errno_location() (probably we can kill it later?). And addresses were different again. The problem is that both relocations resolve symbols in external modules and thus should use symbol_addr instead of sym->st_value. Signed-off-by: Roman I Khimov Signed-off-by: Austin Foxley --- ldso/ldso/x86_64/elfinterp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ldso/ldso/x86_64') diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c index 54528d382..baf024d11 100644 --- a/ldso/ldso/x86_64/elfinterp.c +++ b/ldso/ldso/x86_64/elfinterp.c @@ -226,7 +226,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, case R_X86_64_DTPOFF64: /* During relocation all TLS symbols are defined and used. * Therefore the offset is already correct. */ - *reloc_addr = sym->st_value + rpnt->r_addend; + *reloc_addr = symbol_addr + rpnt->r_addend; break; case R_X86_64_TPOFF64: /* The offset is negative, forward from the thread pointer. @@ -234,7 +234,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, * It is a negative value which will be added to the * thread pointer. */ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt); - *reloc_addr = sym->st_value - tls_tpnt->l_tls_offset + rpnt->r_addend; + *reloc_addr = symbol_addr - tls_tpnt->l_tls_offset + rpnt->r_addend; break; case R_X86_64_32: *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend; -- cgit v1.2.3