Browse Source
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.binutils-2_35-branch
23 changed files with 579 additions and 21 deletions
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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; |
|||
} |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
@ -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 |
|||
Loading…
Reference in new issue