Supprt TLS x32 IE->LE transition.
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 3 Mar 2011 22:11:33 +0000 (22:11 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 3 Mar 2011 22:11:33 +0000 (22:11 +0000)
bfd/

2011-03-03  H.J. Lu  <hongjiu.lu@intel.com>

* 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  <hongjiu.lu@intel.com>

* ld-x86-64/tlsie4.dd: New.
* ld-x86-64/tlsie4.s: Likewise.

* ld-x86-64/x86-64.exp (x86_64tests): Add tlsie4.

bfd/ChangeLog
bfd/elf64-x86-64.c
ld/testsuite/ChangeLog
ld/testsuite/ld-x86-64/tlsie4.dd [new file with mode: 0644]
ld/testsuite/ld-x86-64/tlsie4.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 407738e..36908e4 100644 (file)
@@ -1,3 +1,9 @@
+2011-03-03  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * 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  <bernds@codesourcery.com>
 
         * elflink.c (is_reloc_section): Remove function.
 2011-03-02  Bernd Schmidt  <bernds@codesourcery.com>
 
         * elflink.c (is_reloc_section): Remove function.
index 343abce..56eb62e 100644 (file)
@@ -913,16 +913,29 @@ elf_x86_64_check_tls_transition (bfd *abfd,
 
     case R_X86_64_GOTTPOFF:
       /* Check transition from IE access model:
 
     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)
 
       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);
                      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,
                      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);
                      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,
                      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);
                      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),
                      bfd_put_8 (output_bfd, 0x8d,
                                 contents + roff - 2);
                      bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3),
index 4ff663f..c5bad13 100644 (file)
@@ -1,3 +1,10 @@
+2011-03-03  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * 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  <hongjiu.lu@intel.com>
 
        PR ld/12516
 2011-02-25  H.J. Lu  <hongjiu.lu@intel.com>
 
        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 (file)
index 0000000..d52e337
--- /dev/null
@@ -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 (file)
index 0000000..ca63546
--- /dev/null
@@ -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
index a82a56f..43b9c39 100644 (file)
@@ -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"}
     {"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
 }
 
 run_ld_link_tests $x86_64tests