diff options
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r-- | gold/x86_64.cc | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 6c511e2..6aa489a 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -3505,6 +3505,7 @@ Target_x86_64<size>::Relocate::relocate( if (this->skip_call_tls_get_addr_) { if ((r_type != elfcpp::R_X86_64_PLT32 + && r_type != elfcpp::R_X86_64_GOTPCRELX && r_type != elfcpp::R_X86_64_PLT32_BND && r_type != elfcpp::R_X86_64_PC32_BND && r_type != elfcpp::R_X86_64_PC32) @@ -4169,16 +4170,23 @@ Target_x86_64<size>::Relocate::tls_gd_to_ie( { // For SIZE == 64: // .byte 0x66; leaq foo@tlsgd(%rip),%rdi; - // .word 0x6666; rex64; call __tls_get_addr + // .word 0x6666; rex64; call __tls_get_addr@PLT + // ==> movq %fs:0,%rax; addq x@gottpoff(%rip),%rax + // .byte 0x66; leaq foo@tlsgd(%rip),%rdi; + // .word 0x66; rex64; call *__tls_get_addr@GOTPCREL(%rip) // ==> movq %fs:0,%rax; addq x@gottpoff(%rip),%rax // For SIZE == 32: // leaq foo@tlsgd(%rip),%rdi; - // .word 0x6666; rex64; call __tls_get_addr + // .word 0x6666; rex64; call __tls_get_addr@PLT + // ==> movl %fs:0,%eax; addq x@gottpoff(%rip),%rax + // leaq foo@tlsgd(%rip),%rdi; + // .word 0x66; rex64; call *__tls_get_addr@GOTPCREL(%rip) // ==> movl %fs:0,%eax; addq x@gottpoff(%rip),%rax tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12); tls::check_tls(relinfo, relnum, rela.get_r_offset(), - (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0)); + (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0 + || memcmp(view + 4, "\x66\x48\xff", 3) == 0)); if (size == 64) { @@ -4225,16 +4233,23 @@ Target_x86_64<size>::Relocate::tls_gd_to_le( { // For SIZE == 64: // .byte 0x66; leaq foo@tlsgd(%rip),%rdi; - // .word 0x6666; rex64; call __tls_get_addr + // .word 0x6666; rex64; call __tls_get_addr@PLT + // ==> movq %fs:0,%rax; leaq x@tpoff(%rax),%rax + // .byte 0x66; leaq foo@tlsgd(%rip),%rdi; + // .word 0x66; rex64; call *__tls_get_addr@GOTPCREL(%rip) // ==> movq %fs:0,%rax; leaq x@tpoff(%rax),%rax // For SIZE == 32: // leaq foo@tlsgd(%rip),%rdi; - // .word 0x6666; rex64; call __tls_get_addr + // .word 0x6666; rex64; call __tls_get_addr@PLT + // ==> movl %fs:0,%eax; leaq x@tpoff(%rax),%rax + // leaq foo@tlsgd(%rip),%rdi; + // .word 0x66; rex64; call *__tls_get_addr@GOTPCREL(%rip) // ==> movl %fs:0,%eax; leaq x@tpoff(%rax),%rax tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12); tls::check_tls(relinfo, relnum, rela.get_r_offset(), - (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0)); + (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0 + || memcmp(view + 4, "\x66\x48\xff", 3) == 0)); if (size == 64) { @@ -4362,6 +4377,13 @@ Target_x86_64<size>::Relocate::tls_ld_to_le( // For SIZE == 32: // ... leq foo@dtpoff(%rax),%reg // ==> nopl 0x0(%rax); movl %fs:0,%eax ... leaq x@tpoff(%rax),%rdx + // leaq foo@tlsld(%rip),%rdi; call *__tls_get_addr@GOTPCREL(%rip) + // For SIZE == 64: + // ... leq foo@dtpoff(%rax),%reg + // ==> .word 0x6666; .byte 0x6666; movq %fs:0,%rax ... leaq x@tpoff(%rax),%rdx + // For SIZE == 32: + // ... leq foo@dtpoff(%rax),%reg + // ==> nopw 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); @@ -4369,12 +4391,25 @@ Target_x86_64<size>::Relocate::tls_ld_to_le( tls::check_tls(relinfo, relnum, rela.get_r_offset(), view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x3d); - tls::check_tls(relinfo, relnum, rela.get_r_offset(), view[4] == 0xe8); + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + view[4] == 0xe8 || view[4] == 0xff); - if (size == 64) - memcpy(view - 3, "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0\0", 12); + if (view[4] == 0xe8) + { + 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); + } else - memcpy(view - 3, "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0\0", 12); + { + if (size == 64) + memcpy(view - 3, "\x66\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0\0", + 13); + else + memcpy(view - 3, "\x66\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0\0", + 13); + } // The next reloc should be a PLT32 reloc against __tls_get_addr. // We can skip it. |