[git commit master] ldso: fix x86_64 R_X86_64_TPOFF64 and R_X86_64_DTPOFF64 relocations
Austin Foxley
austinf at cetoncorp.com
Wed May 5 15:43:22 UTC 2010
commit: http://git.uclibc.org/uClibc/commit/?id=0b7acfa800444525498442032b47bfd7d066c72b
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/master
R_X86_64_TPOFF64 revealed by trivial testcase:
===================================================================
#include <stdio.h>
#include <errno.h>
int main() {
void *a = &errno;
printf("errno addr: %llx\n", a);
__asm__("movq errno at 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 <stdio.h>
#include <errno.h>
#include <netdb.h>
#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 <khimov at altell.ru>
Signed-off-by: Austin Foxley <austinf at cetoncorp.com>
---
ldso/ldso/x86_64/elfinterp.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c
index 54528d3..baf024d 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;
--
1.6.3.3
More information about the uClibc-cvs
mailing list