From: H.J. Lu Date: Mon, 20 Jan 2020 14:58:51 +0000 (-0800) Subject: x86-64: Fix TLSDESC relaxation for x32 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=14470f0755dbc942aa684ed647df978ddfc7cff2;p=binutils-gdb.git x86-64: Fix TLSDESC relaxation for x32 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4f74a20544a..ed4054084ec 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2020-01-20 H.J. Lu + + 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 * elf64-ppc.c (LD_R11_0R3, CMPDI_R11_0, STD_R11_0R1, LD_R11_0R1), diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 79e68ff4767..014bea14754 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -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 diff --git a/gas/ChangeLog b/gas/ChangeLog index 426e484854e..02209481075 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2020-01-20 H.J. Lu + + 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 * configure: Regenerate. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 8728725b82d..87ab43bbce0 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -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 diff --git a/gas/testsuite/gas/i386/ilp32/x32-tls.d b/gas/testsuite/gas/i386/ilp32/x32-tls.d index 1255829f8b7..ab4da5c730b 100644 --- a/gas/testsuite/gas/i386/ilp32/x32-tls.d +++ b/gas/testsuite/gas/i386/ilp32/x32-tls.d @@ -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 diff --git a/gas/testsuite/gas/i386/ilp32/x32-tls.s b/gas/testsuite/gas/i386/ilp32/x32-tls.s index f9626cdfdd3..e1599be73c1 100644 --- a/gas/testsuite/gas/i386/ilp32/x32-tls.s +++ b/gas/testsuite/gas/i386/ilp32/x32-tls.s @@ -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 diff --git a/ld/ChangeLog b/ld/ChangeLog index 18d5073895a..f95a25cf305 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,24 @@ +2020-01-20 H.J. Lu + + 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 * 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 index 00000000000..66636c12981 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-1.s @@ -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 index 00000000000..02818b0526e --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-1a.d @@ -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 index 00000000000..d1bb6892cbe --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-1b.d @@ -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 index 00000000000..b6dbb6d93ad --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-2.s @@ -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 index 00000000000..d1b257652a6 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-2a.d @@ -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 index 00000000000..e78283fd666 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-2b.d @@ -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 index 00000000000..9c1da134847 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-3.d @@ -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 index 00000000000..949b1239ed2 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-3.s @@ -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 index 00000000000..8d91fbc0a66 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-4.d @@ -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 index 00000000000..5120af466c7 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-4.s @@ -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 index 00000000000..9d820a1911d --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-5a.c @@ -0,0 +1,33 @@ +#include +#include + +__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 index 00000000000..8edd248c4fe --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-5b.s @@ -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 index 00000000000..f42a8a0e6b3 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-5c.s @@ -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 index 00000000000..8d36733d9bf --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-5d.s @@ -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 index 00000000000..fe0c0e8b111 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr25416-5e.s @@ -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 diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 88f75e0e431..c78b0fd7576 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -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 \