x86-64: Fix TLSDESC relaxation for x32
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 20 Jan 2020 14:58:51 +0000 (06:58 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 20 Jan 2020 15:01:07 +0000 (07:01 -0800)
For x32, we must encode "lea x@TLSDESC(%rip), %reg" with a REX prefix
even if it isn't required.  Otherwise linker can’t safely perform
GDesc -> IE/LE optimization.  X32 TLSDESC sequences can be:

40 8d 05 00 00 00 00 rex lea x@TLSDESC(%rip), %reg
...
67 ff 10 call *x@TLSCALL(%eax)

or the same sequence as LP64:

48 8d 05 00 00 00 00 lea foo@TLSDESC(%rip), %reg
...
ff 10 call *foo@TLSCALL(%rax)

We need to support both sequences for x32.  For both GDesc -> IE/LE
transitions,

67 ff 10 call *x@TLSCALL(%eax)

should relaxed to

0f 1f 00 nopl (%rax)

For GDesc -> LE transition,

40 8d 05 00 00 00 00 rex lea x@TLSDESC(%rip), %reg

should relaxed to

40 c7 c0 fc ff ff ff rex movl $x@tpoff, %reg

For GDesc -> IE transition,

40 8d 05 00 00 00 00 rex lea x@TLSDESC(%rip), %reg

should relaxed to

40 8b 05 00 00 00 00 rex movl x@gottpoff(%rip), %eax

bfd/

PR ld/25416
* elf64-x86-64.c (elf_x86_64_check_tls_transition): Support
"rex leal x@tlsdesc(%rip), %reg" and "call *x@tlsdesc(%eax)" in
X32 mode.
(elf_x86_64_relocate_section): In x32 mode, for GDesc -> LE
transition, relax "rex leal x@tlsdesc(%rip), %reg" to
"rex movl $x@tpoff, %reg", for GDesc -> IE transition, relax
"rex leal x@tlsdesc(%rip), %reg" to
"rex movl x@gottpoff(%rip), %eax".  For both transitions, relax
"call *(%eax)" to "nopl (%rax)".

gas/

PR ld/25416
* config/tc-i386.c (output_insn): Add a dummy REX_OPCODE prefix
for lea with R_X86_64_GOTPC32_TLSDESC relocation when generating
x32 object.
* testsuite/gas/i386/ilp32/x32-tls.d: Updated.
* testsuite/gas/i386/ilp32/x32-tls.s: Add tests for lea with
R_X86_64_GOTPC32_TLSDESC relocation.

ld/

PR ld/25416
* testsuite/ld-x86-64/pr25416-1.s: New file
* testsuite/ld-x86-64/pr25416-1a.d: Likewise.
* testsuite/ld-x86-64/pr25416-1b.d: Likewise.
* testsuite/ld-x86-64/pr25416-1.s: Likewise.
* testsuite/ld-x86-64/pr25416-2.s: Likewise.
* testsuite/ld-x86-64/pr25416-2a.d: Likewise.
* testsuite/ld-x86-64/pr25416-2b.d: Likewise.
* testsuite/ld-x86-64/pr25416-3.d: Likewise.
* testsuite/ld-x86-64/pr25416-3.s: Likewise.
* testsuite/ld-x86-64/pr25416-4.d: Likewise.
* testsuite/ld-x86-64/pr25416-4.s: Likewise.
* testsuite/ld-x86-64/pr25416-5a.c: Likewise.
* testsuite/ld-x86-64/pr25416-5b.s: Likewise.
* testsuite/ld-x86-64/pr25416-5c.s: Likewise.
* testsuite/ld-x86-64/pr25416-5d.s: Likewise.
* testsuite/ld-x86-64/pr25416-5e.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run PR ld/25416 tests.

23 files changed:
bfd/ChangeLog
bfd/elf64-x86-64.c
gas/ChangeLog
gas/config/tc-i386.c
gas/testsuite/gas/i386/ilp32/x32-tls.d
gas/testsuite/gas/i386/ilp32/x32-tls.s
ld/ChangeLog
ld/testsuite/ld-x86-64/pr25416-1.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-1a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-1b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-2.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-2a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-2b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-3.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-3.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-4.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-4.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-5a.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-5b.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-5c.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-5d.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr25416-5e.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 4f74a20544ac056f4afb3b52dd49d71dd17eb82d..ed4054084ec046af909619506210f5e351d73067 100644 (file)
@@ -1,3 +1,16 @@
+2020-01-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/25416
+       * elf64-x86-64.c (elf_x86_64_check_tls_transition): Support
+       "rex leal x@tlsdesc(%rip), %reg" and "call *x@tlsdesc(%eax)" in
+       X32 mode.
+       (elf_x86_64_relocate_section): In x32 mode, for GDesc -> LE
+       transition, relax "rex leal x@tlsdesc(%rip), %reg" to
+       "rex movl $x@tpoff, %reg", for GDesc -> IE transition, relax
+       "rex leal x@tlsdesc(%rip), %reg" to
+       "rex movl x@gottpoff(%rip), %eax".  For both transitions, relax
+       "call *(%eax)" to "nopl (%rax)".
+
 2020-01-20  Alan Modra  <amodra@gmail.com>
 
        * elf64-ppc.c (LD_R11_0R3, CMPDI_R11_0, STD_R11_0R1, LD_R11_0R1),
index 79e68ff47674220a1d8e9a6840b5a671e1f0cb40..014bea147541caf686d203f519f3adf616146411 100644 (file)
@@ -1223,7 +1223,8 @@ elf_x86_64_check_tls_transition (bfd *abfd,
 
     case R_X86_64_GOTPC32_TLSDESC:
       /* Check transition from GDesc access model:
-               leaq x@tlsdesc(%rip), %rax
+               leaq x@tlsdesc(%rip), %rax <--- LP64 mode.
+               rex leal x@tlsdesc(%rip), %eax <--- X32 mode.
 
         Make sure it's a leaq adding rip to a 32-bit offset
         into any register, although it's probably almost always
@@ -1233,7 +1234,8 @@ elf_x86_64_check_tls_transition (bfd *abfd,
        return FALSE;
 
       val = bfd_get_8 (abfd, contents + offset - 3);
-      if ((val & 0xfb) != 0x48)
+      val &= 0xfb;
+      if (val != 0x48 && (ABI_64_P (abfd) || val != 0x40))
        return FALSE;
 
       if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
@@ -1244,13 +1246,26 @@ elf_x86_64_check_tls_transition (bfd *abfd,
 
     case R_X86_64_TLSDESC_CALL:
       /* Check transition from GDesc access model:
-               call *x@tlsdesc(%rax)
+               call *x@tlsdesc(%rax) <--- LP64 mode.
+               call *x@tlsdesc(%eax) <--- X32 mode.
        */
       if (offset + 2 <= sec->size)
        {
-         /* Make sure that it's a call *x@tlsdesc(%rax).  */
+         unsigned int prefix;
          call = contents + offset;
-         return call[0] == 0xff && call[1] == 0x10;
+         prefix = 0;
+         if (!ABI_64_P (abfd))
+           {
+             /* Check for call *x@tlsdesc(%eax).  */
+             if (call[0] == 0x67)
+               {
+                 prefix = 1;
+                 if (offset + 3 > sec->size)
+                   return FALSE;
+               }
+           }
+         /* Make sure that it's a call *x@tlsdesc(%rax).  */
+         return call[prefix] == 0xff && call[1 + prefix] == 0x10;
        }
 
       return FALSE;
@@ -3401,10 +3416,13 @@ corrupt_input:
                {
                  /* GDesc -> LE transition.
                     It's originally something like:
-                    leaq x@tlsdesc(%rip), %rax
+                    leaq x@tlsdesc(%rip), %rax <--- LP64 mode.
+                    rex leal x@tlsdesc(%rip), %eax <--- X32 mode.
 
                     Change it to:
-                    movl $x@tpoff, %rax.  */
+                    movq $x@tpoff, %rax <--- LP64 mode.
+                    rex movl $x@tpoff, %eax <--- X32 mode.
+                  */
 
                  unsigned int val, type;
 
@@ -3412,7 +3430,8 @@ corrupt_input:
                    goto corrupt_input;
                  type = bfd_get_8 (input_bfd, contents + roff - 3);
                  val = bfd_get_8 (input_bfd, contents + roff - 1);
-                 bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1),
+                 bfd_put_8 (output_bfd,
+                            (type & 0x48) | ((type >> 2) & 1),
                             contents + roff - 3);
                  bfd_put_8 (output_bfd, 0xc7, contents + roff - 2);
                  bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
@@ -3426,11 +3445,30 @@ corrupt_input:
                {
                  /* GDesc -> LE transition.
                     It's originally:
-                    call *(%rax)
+                    call *(%rax) <--- LP64 mode.
+                    call *(%eax) <--- X32 mode.
                     Turn it into:
-                    xchg %ax,%ax.  */
-                 bfd_put_8 (output_bfd, 0x66, contents + roff);
-                 bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+                    xchg %ax,%ax <-- LP64 mode.
+                    nopl (%rax)  <-- X32 mode.
+                  */
+                 unsigned int prefix = 0;
+                 if (!ABI_64_P (input_bfd))
+                   {
+                     /* Check for call *x@tlsdesc(%eax).  */
+                     if (contents[roff] == 0x67)
+                       prefix = 1;
+                   }
+                 if (prefix)
+                   {
+                     bfd_put_8 (output_bfd, 0x0f, contents + roff);
+                     bfd_put_8 (output_bfd, 0x1f, contents + roff + 1);
+                     bfd_put_8 (output_bfd, 0x00, contents + roff + 2);
+                   }
+                 else
+                   {
+                     bfd_put_8 (output_bfd, 0x66, contents + roff);
+                     bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+                   }
                  continue;
                }
              else if (r_type == R_X86_64_GOTTPOFF)
@@ -3741,13 +3779,18 @@ corrupt_input:
                {
                  /* GDesc -> IE transition.
                     It's originally something like:
-                    leaq x@tlsdesc(%rip), %rax
+                    leaq x@tlsdesc(%rip), %rax <--- LP64 mode.
+                    rex leal x@tlsdesc(%rip), %eax <--- X32 mode.
 
                     Change it to:
-                    movq x@gottpoff(%rip), %rax # before xchg %ax,%ax.  */
+                    # before xchg %ax,%ax in LP64 mode.
+                    movq x@gottpoff(%rip), %rax
+                    # before nopl (%rax) in X32 mode.
+                    rex movl x@gottpoff(%rip), %eax
+                 */
 
                  /* Now modify the instruction as appropriate. To
-                    turn a leaq into a movq in the form we use it, it
+                    turn a lea into a mov in the form we use it, it
                     suffices to change the second byte from 0x8d to
                     0x8b.  */
                  if (roff < 2)
@@ -3768,13 +3811,32 @@ corrupt_input:
                {
                  /* GDesc -> IE transition.
                     It's originally:
-                    call *(%rax)
+                    call *(%rax) <--- LP64 mode.
+                    call *(%eax) <--- X32 mode.
 
                     Change it to:
-                    xchg %ax, %ax.  */
+                    xchg %ax, %ax <-- LP64 mode.
+                    nopl (%rax)  <-- X32 mode.
+                  */
 
-                 bfd_put_8 (output_bfd, 0x66, contents + roff);
-                 bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+                 unsigned int prefix = 0;
+                 if (!ABI_64_P (input_bfd))
+                   {
+                     /* Check for call *x@tlsdesc(%eax).  */
+                     if (contents[roff] == 0x67)
+                       prefix = 1;
+                   }
+                 if (prefix)
+                   {
+                     bfd_put_8 (output_bfd, 0x0f, contents + roff);
+                     bfd_put_8 (output_bfd, 0x1f, contents + roff + 1);
+                     bfd_put_8 (output_bfd, 0x00, contents + roff + 2);
+                   }
+                 else
+                   {
+                     bfd_put_8 (output_bfd, 0x66, contents + roff);
+                     bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+                   }
                  continue;
                }
              else
index 426e484854ec3d919f2097ab8e892bb63fcb4a20..02209481075d0859103833d3ec4777d2b3140455 100644 (file)
@@ -1,3 +1,13 @@
+2020-01-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/25416
+       * config/tc-i386.c (output_insn): Add a dummy REX_OPCODE prefix
+       for lea with R_X86_64_GOTPC32_TLSDESC relocation when generating
+       x32 object.
+       * testsuite/gas/i386/ilp32/x32-tls.d: Updated.
+       * testsuite/gas/i386/ilp32/x32-tls.s: Add tests for lea with
+       R_X86_64_GOTPC32_TLSDESC relocation.
+
 2020-01-18  Nick Clifton  <nickc@redhat.com>
 
        * configure: Regenerate.
index 8728725b82d49bb64d169269167a58fa103827bc..87ab43bbce017ed338a388b3e6e8ca7331d0dfa4 100644 (file)
@@ -8713,10 +8713,13 @@ output_insn (void)
 #if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF)
          /* For x32, add a dummy REX_OPCODE prefix for mov/add with
             R_X86_64_GOTTPOFF relocation so that linker can safely
-            perform IE->LE optimization.  */
+            perform IE->LE optimization.  A dummy REX_OPCODE prefix
+            is also needed for lea with R_X86_64_GOTPC32_TLSDESC
+            relocation for GDesc -> IE/LE optimization.  */
          if (x86_elf_abi == X86_64_X32_ABI
              && i.operands == 2
-             && i.reloc[0] == BFD_RELOC_X86_64_GOTTPOFF
+             && (i.reloc[0] == BFD_RELOC_X86_64_GOTTPOFF
+                 || i.reloc[0] == BFD_RELOC_X86_64_GOTPC32_TLSDESC)
              && i.prefix[REX_PREFIX] == 0)
            add_prefix (REX_OPCODE);
 #endif
index 1255829f8b7730e27598a8c58db56b52ccd0ed43..ab4da5c730b094fa642d18b516e0ae8e8fa69ba9 100644 (file)
@@ -10,4 +10,6 @@ Disassembly of section .text:
 [      ]*[a-f0-9]+:    4c 8b 25 00 00 00 00    mov    0x0\(%rip\),%r12        # e <_start\+0xe>
 [      ]*[a-f0-9]+:    40 03 05 00 00 00 00    rex add 0x0\(%rip\),%eax        # 15 <_start\+0x15>
 [      ]*[a-f0-9]+:    44 03 25 00 00 00 00    add    0x0\(%rip\),%r12d        # 1c <_start\+0x1c>
+[      ]*[a-f0-9]+:    40 8d 05 00 00 00 00    rex lea 0x0\(%rip\),%eax        # 23 <_start\+0x23>
+[      ]*[a-f0-9]+:    44 8d 25 00 00 00 00    lea    0x0\(%rip\),%r12d        # 2a <_start\+0x2a>
 #pass
index f9626cdfdd30e75834b9d46d477c56d00e50e7b6..e1599be73c1fd999ee9f1f18017e432c15189b5e 100644 (file)
@@ -4,6 +4,8 @@ _start:
        mov     foo@gottpoff(%rip), %r12
        add     foo@gottpoff(%rip), %eax
        add     foo@gottpoff(%rip), %r12d
+       lea     foo@tlsdesc(%rip), %eax
+       lea     foo@tlsdesc(%rip), %r12d
        .globl  foo
        .section        .tdata,"awT",@progbits
        .align 4
index 18d5073895a4c8e46330b2124fa6348c2fdcad02..f95a25cf30568ba45e6aa9fdc5d8036d9074abe4 100644 (file)
@@ -1,3 +1,24 @@
+2020-01-20  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/25416
+       * testsuite/ld-x86-64/pr25416-1.s: New file
+       * testsuite/ld-x86-64/pr25416-1a.d: Likewise.
+       * testsuite/ld-x86-64/pr25416-1b.d: Likewise.
+       * testsuite/ld-x86-64/pr25416-1.s: Likewise.
+       * testsuite/ld-x86-64/pr25416-2.s: Likewise.
+       * testsuite/ld-x86-64/pr25416-2a.d: Likewise.
+       * testsuite/ld-x86-64/pr25416-2b.d: Likewise.
+       * testsuite/ld-x86-64/pr25416-3.d: Likewise.
+       * testsuite/ld-x86-64/pr25416-3.s: Likewise.
+       * testsuite/ld-x86-64/pr25416-4.d: Likewise.
+       * testsuite/ld-x86-64/pr25416-4.s: Likewise.
+       * testsuite/ld-x86-64/pr25416-5a.c: Likewise.
+       * testsuite/ld-x86-64/pr25416-5b.s: Likewise.
+       * testsuite/ld-x86-64/pr25416-5c.s: Likewise.
+       * testsuite/ld-x86-64/pr25416-5d.s: Likewise.
+       * testsuite/ld-x86-64/pr25416-5e.s: Likewise.
+       * testsuite/ld-x86-64/x86-64.exp: Run PR ld/25416 tests.
+
 2020-01-20  Alan Modra  <amodra@gmail.com>
 
        * testsuite/ld-powerpc/tlsexe.d: Match new __tls_get_addr stub.
diff --git a/ld/testsuite/ld-x86-64/pr25416-1.s b/ld/testsuite/ld-x86-64/pr25416-1.s
new file mode 100644 (file)
index 0000000..66636c1
--- /dev/null
@@ -0,0 +1,13 @@
+       .text
+       .globl  _start
+       .type   _start, @function
+_start:
+       lea     foo@TLSDESC(%rip), %eax
+       call    *foo@TLSCALL(%eax)
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   30
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr25416-1a.d b/ld/testsuite/ld-x86-64/pr25416-1a.d
new file mode 100644 (file)
index 0000000..02818b0
--- /dev/null
@@ -0,0 +1,16 @@
+#name: X32 GDesc 1
+#source: pr25416-1.s
+#as: --x32
+#ld: -melf32_x86_64 -shared
+#objdump: -dw
+
+.*: +file format .*
+
+
+#...
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:   40 8d 05 ([0-9a-f]{2} ){4}[ \t]+rex lea 0x[a-f0-9]+\(%rip\),%eax[ \t]+# [a-f0-9]+ <_GLOBAL_OFFSET_TABLE_\+0x[a-f0-9]+>
+ +[a-f0-9]+:   67 ff 10                callq  \*\(%eax\)
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr25416-1b.d b/ld/testsuite/ld-x86-64/pr25416-1b.d
new file mode 100644 (file)
index 0000000..d1bb689
--- /dev/null
@@ -0,0 +1,15 @@
+#name: X32 GDesc -> LE 1
+#source: pr25416-1.s
+#as: --x32
+#ld: -melf32_x86_64
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:   40 c7 c0 ([0-9a-f]{2} ){4}[ \t]+rex mov \$0x[a-f0-9]+,%eax
+ +[a-f0-9]+:   0f 1f 00                nopl   \(%rax\)
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr25416-2.s b/ld/testsuite/ld-x86-64/pr25416-2.s
new file mode 100644 (file)
index 0000000..b6dbb6d
--- /dev/null
@@ -0,0 +1,13 @@
+       .text
+       .globl  _start
+       .type   _start, @function
+_start:
+       lea     foo@TLSDESC(%rip), %rax
+       call    *foo@TLSCALL(%rax)
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   30
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr25416-2a.d b/ld/testsuite/ld-x86-64/pr25416-2a.d
new file mode 100644 (file)
index 0000000..d1b2576
--- /dev/null
@@ -0,0 +1,16 @@
+#name: X32 GDesc 2
+#source: pr25416-2.s
+#as: --x32
+#ld: -melf32_x86_64 -shared
+#objdump: -dw
+
+.*: +file format .*
+
+
+#...
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:   48 8d 05 ([0-9a-f]{2} ){4}[ \t]+lea    0x[a-f0-9]+\(%rip\),%rax[ \t]+# [a-f0-9]+ <_GLOBAL_OFFSET_TABLE_\+0x[a-f0-9]+>
+ +[a-f0-9]+:   ff 10                   callq  \*\(%rax\)
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr25416-2b.d b/ld/testsuite/ld-x86-64/pr25416-2b.d
new file mode 100644 (file)
index 0000000..e78283f
--- /dev/null
@@ -0,0 +1,15 @@
+#name: X32 GDesc -> LE 2
+#source: pr25416-2.s
+#as: --x32
+#ld: -melf32_x86_64
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:   48 c7 c0 ([0-9a-f]{2} ){4}[ \t]+mov    \$0x[a-f0-9]+,%rax
+ +[a-f0-9]+:   66 90                   xchg   %ax,%ax
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr25416-3.d b/ld/testsuite/ld-x86-64/pr25416-3.d
new file mode 100644 (file)
index 0000000..9c1da13
--- /dev/null
@@ -0,0 +1,16 @@
+#name: X32 GDesc -> IE 1
+#as: --x32
+#ld: -melf32_x86_64 -shared
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:   40 8b 05 ([0-9a-f]{2} ){4}[ \t]+rex mov 0x[a-f0-9]+\(%rip\),%eax[ \t]+# [a-f0-9]+ <.got>
+ +[a-f0-9]+:   0f 1f 00                nopl   \(%rax\)
+ +[a-f0-9]+:   64 8b 0c 25 00 00 00 00         mov    %fs:0x0,%ecx
+ +[a-f0-9]+:   40 03 0d ([0-9a-f]{2} ){4}[ \t]+rex add 0x[a-f0-9]+\(%rip\),%ecx[ \t]+# [a-f0-9]+ <.got>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr25416-3.s b/ld/testsuite/ld-x86-64/pr25416-3.s
new file mode 100644 (file)
index 0000000..949b123
--- /dev/null
@@ -0,0 +1,15 @@
+       .text
+       .globl  _start
+       .type   _start, @function
+_start:
+       lea     foo@TLSDESC(%rip), %eax
+       call    *foo@TLSCALL(%eax)
+       movl    %fs:0, %ecx
+       addl    foo@gottpoff(%rip), %ecx
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   30
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr25416-4.d b/ld/testsuite/ld-x86-64/pr25416-4.d
new file mode 100644 (file)
index 0000000..8d91fbc
--- /dev/null
@@ -0,0 +1,16 @@
+#name: X32 GDesc -> IE 2
+#as: --x32
+#ld: -melf32_x86_64 -shared
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+ +[a-f0-9]+:   48 8b 05 ([0-9a-f]{2} ){4}[ \t]+mov    0x[a-f0-9]+\(%rip\),%rax[ \t]+# [a-f0-9]+ <.got>
+ +[a-f0-9]+:   66 90                   xchg   %ax,%ax
+ +[a-f0-9]+:   64 8b 0c 25 00 00 00 00         mov    %fs:0x0,%ecx
+ +[a-f0-9]+:   40 03 0d ([0-9a-f]{2} ){4}[ \t]+rex add 0x[a-f0-9]+\(%rip\),%ecx[ \t]+# [a-f0-9]+ <.got>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr25416-4.s b/ld/testsuite/ld-x86-64/pr25416-4.s
new file mode 100644 (file)
index 0000000..5120af4
--- /dev/null
@@ -0,0 +1,15 @@
+       .text
+       .globl  _start
+       .type   _start, @function
+_start:
+       lea     foo@TLSDESC(%rip), %rax
+       call    *foo@TLSCALL(%rax)
+       movl    %fs:0, %ecx
+       addl    foo@gottpoff(%rip), %ecx
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   30
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr25416-5a.c b/ld/testsuite/ld-x86-64/pr25416-5a.c
new file mode 100644 (file)
index 0000000..9d820a1
--- /dev/null
@@ -0,0 +1,33 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+__thread int bar = 301;
+
+extern int *test1 (int);
+extern int *test2 (int);
+extern int *test3 (int);
+
+int
+main ()
+{
+  int *p;
+  p = test1 (30);
+  if (*p != 30)
+    abort ();
+  *p = 40;
+  test1 (40);
+  p = test2 (301);
+  if (*p != 301)
+    abort ();
+  if (p != &bar)
+    abort ();
+  *p = 40;
+  test2 (40);
+  p = test3 (40);
+  if (*p != 40)
+    abort ();
+  *p = 50;
+  test3 (50);
+  puts ("PASS");
+  return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/pr25416-5b.s b/ld/testsuite/ld-x86-64/pr25416-5b.s
new file mode 100644 (file)
index 0000000..8edd248
--- /dev/null
@@ -0,0 +1,52 @@
+       .text
+       .p2align 4
+       .globl  test1
+       .type   test1, @function
+test1:
+       .cfi_startproc
+       subl    $8, %esp
+       .cfi_def_cfa_offset 16
+       lea     foo@TLSDESC(%rip), %eax
+       call    *foo@TLSCALL(%eax)
+       addl    %fs:0, %eax
+       cmpl    %edi, (%eax)
+       jne     .L5
+       addl    $8, %esp
+       .cfi_remember_state
+       .cfi_def_cfa_offset 8
+       ret
+.L5:
+       .cfi_restore_state
+       call    abort@PLT
+       .cfi_endproc
+       .size   test1, .-test1
+       .p2align 4
+       .globl  test2
+       .type   test2, @function
+test2:
+       .cfi_startproc
+       subl    $8, %esp
+       .cfi_def_cfa_offset 16
+       lea     bar@TLSDESC(%rip), %eax
+       call    *bar@TLSCALL(%eax)
+       addl    %fs:0, %eax
+       cmpl    %edi, (%eax)
+       jne     .L9
+       addl    $8, %esp
+       .cfi_remember_state
+       .cfi_def_cfa_offset 8
+       ret
+.L9:
+       .cfi_restore_state
+       call    abort@PLT
+       .cfi_endproc
+       .size   test2, .-test2
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .hidden foo
+       .globl foo
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   30
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr25416-5c.s b/ld/testsuite/ld-x86-64/pr25416-5c.s
new file mode 100644 (file)
index 0000000..f42a8a0
--- /dev/null
@@ -0,0 +1,56 @@
+       .text
+       .p2align 4
+       .globl  test1
+       .type   test1, @function
+test1:
+       .cfi_startproc
+       subq    $8, %rsp
+       .cfi_def_cfa_offset 16
+       lea     foo@TLSDESC(%rip), %rax
+       call    *foo@TLSCALL(%rax)
+       addl    %fs:0, %eax
+       cmpl    %edi, (%eax)
+       jne     .L5
+       movl    %eax, %r8d
+       addq    $8, %rsp
+       .cfi_remember_state
+       .cfi_def_cfa_offset 8
+       movq    %r8, %rax
+       ret
+.L5:
+       .cfi_restore_state
+       call    abort@PLT
+       .cfi_endproc
+       .size   test1, .-test1
+       .p2align 4
+       .globl  test2
+       .type   test2, @function
+test2:
+       .cfi_startproc
+       subq    $8, %rsp
+       .cfi_def_cfa_offset 16
+       lea     bar@TLSDESC(%rip), %rax
+       call    *bar@TLSCALL(%rax)
+       addl    %fs:0, %eax
+       cmpl    %edi, (%eax)
+       jne     .L9
+       movl    %eax, %r8d
+       addq    $8, %rsp
+       .cfi_remember_state
+       .cfi_def_cfa_offset 8
+       movq    %r8, %rax
+       ret
+.L9:
+       .cfi_restore_state
+       call    abort@PLT
+       .cfi_endproc
+       .size   test2, .-test2
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .hidden foo
+       .globl foo
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   30
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr25416-5d.s b/ld/testsuite/ld-x86-64/pr25416-5d.s
new file mode 100644 (file)
index 0000000..8d36733
--- /dev/null
@@ -0,0 +1,19 @@
+       .text
+       .p2align 4
+       .globl  test3
+       .type   test3, @function
+test3:
+       .cfi_startproc
+       movl    %fs:0, %eax
+       addq    foo@gottpoff(%rip), %rax
+       cmpl    %edi, (%eax)
+       jne     .L7
+       movl    %eax, %eax
+       ret
+.L7:
+       pushq   %rax
+       .cfi_def_cfa_offset 16
+       call    abort@PLT
+       .cfi_endproc
+       .size   test3, .-test3
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr25416-5e.s b/ld/testsuite/ld-x86-64/pr25416-5e.s
new file mode 100644 (file)
index 0000000..fe0c0e8
--- /dev/null
@@ -0,0 +1,23 @@
+       .text
+       .p2align 4
+       .globl  test3
+       .type   test3, @function
+test3:
+       .cfi_startproc
+       subl    $8, %esp
+       .cfi_def_cfa_offset 16
+       lea     foo@TLSDESC(%rip), %eax
+       call    *foo@TLSCALL(%eax)
+       addl    %fs:0, %eax
+       cmpl    %edi, (%eax)
+       jne     .L5
+       addl    $8, %esp
+       .cfi_remember_state
+       .cfi_def_cfa_offset 8
+       ret
+.L5:
+       .cfi_restore_state
+       call    abort@PLT
+       .cfi_endproc
+       .size   test3, .-test3
+       .section        .note.GNU-stack,"",@progbits
index 88f75e0e4319a0d5b8b6b97e1f12ba5f4aa89d2b..c78b0fd75760f09a5614e4d06c10d9ba99605e19 100644 (file)
@@ -461,6 +461,12 @@ run_dump_test "pr24721-x32"
 run_dump_test "pr24905"
 run_dump_test "pr24905-x32"
 run_dump_test "align-branch-1"
+run_dump_test "pr25416-1a"
+run_dump_test "pr25416-2b"
+run_dump_test "pr25416-2a"
+run_dump_test "pr25416-2b"
+run_dump_test "pr25416-3"
+run_dump_test "pr25416-4"
 
 if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} {
     return
@@ -1302,6 +1308,51 @@ if { [isnative] && [check_compiler_available] } {
     ]
 
     if  {[istarget "x86_64-*-linux*-gnux32"]} {
+       run_cc_link_tests [list \
+           [list \
+               "Build pr25416-5b.o (GDesc -maddress-mode=short)" \
+               "" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5b.s } \
+           ] \
+           [list \
+               "Build pr25416-5b.so (GDesc -> IE -maddress-mode=short)" \
+               "-shared" \
+               "-fPIC -Wa,-mx86-used-note=yes" \
+               { pr25416-5b.s pr25416-5d.s } \
+               {} \
+               "pr25416-5b.so" \
+           ] \
+           [list \
+               "Build pr25416-5c.o (GDesc -maddress-mode=long)" \
+               "" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5c.s } \
+           ] \
+           [list \
+               "Build pr25416-5c.so (GDesc -> IE -maddress-mode=long)" \
+               "-shared" \
+               "-fPIC -Wa,-mx86-used-note=yes" \
+               { pr25416-5c.s pr25416-5d.s } \
+               {} \
+               "pr25416-5c.so" \
+           ] \
+           [list \
+               "Build pr25416-5d.so (GDesc -maddress-mode=short)" \
+               "-shared" \
+               "-fPIC -Wa,-mx86-used-note=yes" \
+               { pr25416-5b.s pr25416-5e.s } \
+               {} \
+               "pr25416-5d.so" \
+           ] \
+           [list \
+               "Build pr25416-5d.o (IE -maddress-mode=short)" \
+               "" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5d.s } \
+           ] \
+       ]
+
        run_ld_link_exec_tests [list \
            [list \
                "Run pr22001-1b" \
@@ -1321,6 +1372,67 @@ if { [isnative] && [check_compiler_available] } {
                "pass.out" \
                "$NOPIE_CFLAGS" \
            ] \
+           [list \
+               "Run pr25416-5a (GDesc -> IE -maddress-mode=short)" \
+               "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr25416-5b.so" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5a.c } \
+               "pr25416-5a" \
+               "pass.out" \
+               "$NOPIE_CFLAGS" \
+           ] \
+           [list \
+               "Run pr25416-5b (GDesc -> LE -maddress-mode=short" \
+               "$NOPIE_LDFLAGS tmpdir/pr25416-5b.o tmpdir/pr25416-5d.o" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5a.c } \
+               "pr25416-5b" \
+               "pass.out" \
+               "$NOPIE_CFLAGS" \
+           ] \
+           [list \
+               "Run pr25416-5c (GDesc -> IE -maddress-mode=long)" \
+               "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr25416-5c.so" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5a.c } \
+               "pr25416-5c" \
+               "pass.out" \
+               "$NOPIE_CFLAGS" \
+           ] \
+           [list \
+               "Run pr25416-5d (GDesc -> LE -maddress-mode=long)" \
+               "$NOPIE_LDFLAGS tmpdir/pr25416-5c.o tmpdir/pr25416-5d.o" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5a.c } \
+               "pr25416-5d" \
+               "pass.out" \
+               "$NOPIE_CFLAGS" \
+           ] \
+           [list \
+               "Run pr25416-5e (GDesc -maddress-mode=short)" \
+               "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr25416-5d.so" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5a.c } \
+               "pr25416-5e" \
+               "pass.out" \
+               "$NOPIE_CFLAGS" \
+           ] \
+           [list \
+               "Run pr25416-5f (PIE GDesc -> LE -maddress-mode=short)" \
+               "-pie tmpdir/pr25416-5b.o tmpdir/pr25416-5d.o" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5a.c } \
+               "pr25416-5f" \
+               "pass.out" \
+           ] \
+           [list \
+               "Run pr25416-5g (PIE GDesc -> LE -maddress-mode=long)" \
+               "-pie tmpdir/pr25416-5c.o tmpdir/pr25416-5d.o" \
+               "-Wa,-mx86-used-note=yes" \
+               { pr25416-5a.c } \
+               "pr25416-5g" \
+               "pass.out" \
+           ] \
        ]
     } else {
        run_cc_link_tests [list \