From 4b336726739e2383c985545087ebd794168c3f2e Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 3 Mar 2011 22:11:30 +0000 Subject: [PATCH] Supprt TLS x32 IE->LE transition. bfd/ 2011-03-03 H.J. Lu * elf64-x86-64.c (elf_x86_64_check_tls_transition): Supprt TLS x32 IE->LE transition. (elf_x86_64_relocate_section): Likewise. ld/testsuite/ 2011-03-03 H.J. Lu * ld-x86-64/tlsie4.dd: New. * ld-x86-64/tlsie4.s: Likewise. * ld-x86-64/x86-64.exp (x86_64tests): Add tlsie4. --- bfd/ChangeLog | 6 ++++++ bfd/elf64-x86-64.c | 38 ++++++++++++++++++++++++++++++-------- ld/testsuite/ChangeLog | 7 +++++++ ld/testsuite/ld-x86-64/tlsie4.dd | 18 ++++++++++++++++++ ld/testsuite/ld-x86-64/tlsie4.s | 16 ++++++++++++++++ ld/testsuite/ld-x86-64/x86-64.exp | 3 +++ 6 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/tlsie4.dd create mode 100644 ld/testsuite/ld-x86-64/tlsie4.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 407738e05..36908e400 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2011-03-03 H.J. Lu + + * elf64-x86-64.c (elf_x86_64_check_tls_transition): Supprt TLS + x32 IE->LE transition. + (elf_x86_64_relocate_section): Likewise. + 2011-03-02 Bernd Schmidt * elflink.c (is_reloc_section): Remove function. diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 343abce64..56eb62e80 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -913,16 +913,29 @@ elf_x86_64_check_tls_transition (bfd *abfd, case R_X86_64_GOTTPOFF: /* Check transition from IE access model: - movq foo@gottpoff(%rip), %reg - addq foo@gottpoff(%rip), %reg + mov foo@gottpoff(%rip), %reg + add foo@gottpoff(%rip), %reg */ - if (offset < 3 || (offset + 4) > sec->size) - return FALSE; - - val = bfd_get_8 (abfd, contents + offset - 3); - if (val != 0x48 && val != 0x4c) - return FALSE; + /* Check REX prefix first. */ + if (offset >= 3 && (offset + 4) <= sec->size) + { + val = bfd_get_8 (abfd, contents + offset - 3); + if (val != 0x48 && val != 0x4c) + { + /* X32 may have 0x44 REX prefix or no REX prefix. */ + if (ABI_64_P (abfd)) + return FALSE; + } + } + else + { + /* X32 may not have any REX prefix. */ + if (ABI_64_P (abfd)) + return FALSE; + if (offset < 2 || (offset + 3) > sec->size) + return FALSE; + } val = bfd_get_8 (abfd, contents + offset - 2); if (val != 0x8b && val != 0x03) @@ -3505,6 +3518,9 @@ elf_x86_64_relocate_section (bfd *output_bfd, if (val == 0x4c) bfd_put_8 (output_bfd, 0x49, contents + roff - 3); + else if (!ABI_64_P (output_bfd) && val == 0x44) + bfd_put_8 (output_bfd, 0x41, + contents + roff - 3); bfd_put_8 (output_bfd, 0xc7, contents + roff - 2); bfd_put_8 (output_bfd, 0xc0 | reg, @@ -3517,6 +3533,9 @@ elf_x86_64_relocate_section (bfd *output_bfd, if (val == 0x4c) bfd_put_8 (output_bfd, 0x49, contents + roff - 3); + else if (!ABI_64_P (output_bfd) && val == 0x44) + bfd_put_8 (output_bfd, 0x41, + contents + roff - 3); bfd_put_8 (output_bfd, 0x81, contents + roff - 2); bfd_put_8 (output_bfd, 0xc0 | reg, @@ -3528,6 +3547,9 @@ elf_x86_64_relocate_section (bfd *output_bfd, if (val == 0x4c) bfd_put_8 (output_bfd, 0x4d, contents + roff - 3); + else if (!ABI_64_P (output_bfd) && val == 0x44) + bfd_put_8 (output_bfd, 0x45, + contents + roff - 3); bfd_put_8 (output_bfd, 0x8d, contents + roff - 2); bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3), diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 4ff663f89..c5bad1368 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-03-03 H.J. Lu + + * ld-x86-64/tlsie4.dd: New. + * ld-x86-64/tlsie4.s: Likewise. + + * ld-x86-64/x86-64.exp (x86_64tests): Add tlsie4. + 2011-02-25 H.J. Lu PR ld/12516 diff --git a/ld/testsuite/ld-x86-64/tlsie4.dd b/ld/testsuite/ld-x86-64/tlsie4.dd new file mode 100644 index 000000000..d52e337a7 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsie4.dd @@ -0,0 +1,18 @@ +#source: tlsie4.s +#as: --x32 +#ld: -melf32_x86_64 tmpdir/tlsie4 +#objdump: -drw +#target: x86_64-*-linux* + +.*: +file format .* + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: c7 c0 fc ff ff ff mov \$0xfffffffc,%eax +[ ]*[a-f0-9]+: 8d 80 fc ff ff ff lea -0x4\(%rax\),%eax +[ ]*[a-f0-9]+: 41 c7 c0 fc ff ff ff mov \$0xfffffffc,%r8d +[ ]*[a-f0-9]+: 45 8d 80 fc ff ff ff lea -0x4\(%r8\),%r8d +[ ]*[a-f0-9]+: 41 c7 c4 fc ff ff ff mov \$0xfffffffc,%r12d +[ ]*[a-f0-9]+: 41 81 c4 fc ff ff ff add \$0xfffffffc,%r12d +#pass diff --git a/ld/testsuite/ld-x86-64/tlsie4.s b/ld/testsuite/ld-x86-64/tlsie4.s new file mode 100644 index 000000000..ca6354646 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsie4.s @@ -0,0 +1,16 @@ + .text + .globl _start +_start: + mov foo@GOTTPOFF(%rip), %eax + add foo@GOTTPOFF(%rip), %eax + mov foo@GOTTPOFF(%rip), %r8d + add foo@GOTTPOFF(%rip), %r8d + mov foo@GOTTPOFF(%rip), %r12d + add foo@GOTTPOFF(%rip), %r12d + .globl foo + .section .tdata,"awT",@progbits + .align 4 + .type foo, @object + .size foo, 4 +foo: + .long 100 diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index a82a56fb3..43b9c393a 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -87,6 +87,9 @@ set x86_64tests { {"Split by file with 'l' flag on section." "-split-by-file -r" "--64" {split-by-file1.s split-by-file2.s} {{readelf -SW split-by-file.rd}} "split-by-file.o"} + {"TLS X32 IE->LE transition" "-melf32_x86_64" + "--x32" {tlsie4.s} + {{objdump -dwr tlsie4.dd}} "tlsie4"} } run_ld_link_tests $x86_64tests -- 2.11.4.GIT