aboutsummaryrefslogtreecommitdiff
path: root/gold/x86_64.cc
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2012-11-20 05:56:06 +0000
committerH.J. Lu <hjl.tools@gmail.com>2012-11-20 05:56:06 +0000
commitd2cf1c6cfceee86f869cf2a3e7fd32b47350a38c (patch)
treefb810585c152317ddd7d1fdc086df1d1a849dfca /gold/x86_64.cc
parentde9f1b683d9c03145db04e403be2410aea6d3186 (diff)
downloadfsf-binutils-gdb-d2cf1c6cfceee86f869cf2a3e7fd32b47350a38c.zip
fsf-binutils-gdb-d2cf1c6cfceee86f869cf2a3e7fd32b47350a38c.tar.gz
fsf-binutils-gdb-d2cf1c6cfceee86f869cf2a3e7fd32b47350a38c.tar.bz2
Fix TLS to LE optimization for x32
PR gold/14858 * x86_64.cc (Relocate::tls_ld_to_le): Support x32.
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r--gold/x86_64.cc9
1 files changed, 8 insertions, 1 deletions
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 6342196..8119983 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -3965,8 +3965,12 @@ Target_x86_64<size>::Relocate::tls_ld_to_le(
section_size_type view_size)
{
// leaq foo@tlsld(%rip),%rdi; call __tls_get_addr@plt;
+ // For SIZE == 64:
// ... leq foo@dtpoff(%rax),%reg
// ==> .word 0x6666; .byte 0x66; movq %fs:0,%rax ... leaq x@tpoff(%rax),%rdx
+ // For SIZE == 32:
+ // ... leq foo@dtpoff(%rax),%reg
+ // ==> nopl 0x0(%rax); movl %fs:0,%eax ... leaq x@tpoff(%rax),%rdx
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 9);
@@ -3976,7 +3980,10 @@ Target_x86_64<size>::Relocate::tls_ld_to_le(
tls::check_tls(relinfo, relnum, rela.get_r_offset(), view[4] == 0xe8);
- memcpy(view - 3, "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0\0", 12);
+ if (size == 64)
+ memcpy(view - 3, "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0\0", 12);
+ else
+ memcpy(view - 3, "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0\0", 12);
// The next reloc should be a PLT32 reloc against __tls_get_addr.
// We can skip it.