From 5c98a14e1e4ffe0e8754ca07e50c564e1a22d6c1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 29 Aug 2013 10:25:27 +0000 Subject: [PATCH] * elf64-x86-64.c (elf_x86_64_check_tls_transition): Allow 64-bit -mcmodel=large -fpic TLS GD and LD sequences. (elf_x86_64_relocate_section): Handle -mcmodel=large -fpic TLS GD and LD sequences in GD->LE, GD->IE and LD->LE transitions. ld/testsuite/ * ld-x86-64/x86-64.exp: Add tlsld3, tlsgd7 and tlsgd8 tests. * ld-x86-64/tlspic1.s: Add -mcmodel=large -fpic TLS GD and LD sequences. * ld-x86-64/tlspic.dd: Adjusted. * ld-x86-64/tlspic.rd: Adjusted. * ld-x86-64/tlspic-nacl.rd: Adjusted. * ld-x86-64/tlsld3.dd: New test. * ld-x86-64/tlsld3.s: New file. * ld-x86-64/tlsgd7.dd: New test. * ld-x86-64/tlsgd7.s: New file. * ld-x86-64/tlsgd8.dd: New test. * ld-x86-64/tlsgd8.s: New file. --- bfd/ChangeLog | 7 ++ bfd/elf64-x86-64.c | 124 ++++++++++++++++---- ld/testsuite/ChangeLog | 15 +++ ld/testsuite/ld-x86-64/tlsgd7.dd | 23 ++++ ld/testsuite/ld-x86-64/tlsgd7.s | 25 ++++ ld/testsuite/ld-x86-64/tlsgd8.dd | 23 ++++ ld/testsuite/ld-x86-64/tlsgd8.s | 18 +++ ld/testsuite/ld-x86-64/tlsld3.dd | 23 ++++ ld/testsuite/ld-x86-64/tlsld3.s | 27 +++++ ld/testsuite/ld-x86-64/tlspic-nacl.rd | 2 +- ld/testsuite/ld-x86-64/tlspic.dd | 161 +++++++++++++++++++++++++- ld/testsuite/ld-x86-64/tlspic.rd | 18 +-- ld/testsuite/ld-x86-64/tlspic1.s | 103 ++++++++++++++++ ld/testsuite/ld-x86-64/x86-64.exp | 9 ++ 14 files changed, 546 insertions(+), 32 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/tlsgd7.dd create mode 100644 ld/testsuite/ld-x86-64/tlsgd7.s create mode 100644 ld/testsuite/ld-x86-64/tlsgd8.dd create mode 100644 ld/testsuite/ld-x86-64/tlsgd8.s create mode 100644 ld/testsuite/ld-x86-64/tlsld3.dd create mode 100644 ld/testsuite/ld-x86-64/tlsld3.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a73dd953ac2..cfbd50da778 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2013-08-29 Jakub Jelinek + + * elf64-x86-64.c (elf_x86_64_check_tls_transition): Allow + 64-bit -mcmodel=large -fpic TLS GD and LD sequences. + (elf_x86_64_relocate_section): Handle -mcmodel=large -fpic + TLS GD and LD sequences in GD->LE, GD->IE and LD->LE transitions. + 2013-08-27 Alan Modra * elf-bfd.h (struct elf_backend_data): Remove as_needed_cleanup. diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 0da839ac940..a89485a157f 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1089,6 +1089,7 @@ elf_x86_64_check_tls_transition (bfd *abfd, { unsigned int val; unsigned long r_symndx; + bfd_boolean largepic = FALSE; struct elf_link_hash_entry *h; bfd_vma offset; struct elf_x86_64_link_hash_table *htab; @@ -1126,16 +1127,32 @@ elf_x86_64_check_tls_transition (bfd *abfd, can transit to different access model. For 32bit, only leaq foo@tlsgd(%rip), %rdi .word 0x6666; rex64; call __tls_get_addr - can transit to different access model. */ + can transit to different access model. For largepic + we also support: + leaq foo@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq $rbx, %rax + call *%rax. */ static const unsigned char call[] = { 0x66, 0x66, 0x48, 0xe8 }; static const unsigned char leaq[] = { 0x66, 0x48, 0x8d, 0x3d }; - if ((offset + 12) > sec->size - || memcmp (contents + offset + 4, call, 4) != 0) + if ((offset + 12) > sec->size) return FALSE; - if (ABI_64_P (abfd)) + if (memcmp (contents + offset + 4, call, 4) != 0) + { + if (!ABI_64_P (abfd) + || (offset + 19) > sec->size + || offset < 3 + || memcmp (contents + offset - 3, leaq + 1, 3) != 0 + || memcmp (contents + offset + 4, "\x48\xb8", 2) != 0 + || memcmp (contents + offset + 14, "\x48\x01\xd8\xff\xd0", 5) + != 0) + return FALSE; + largepic = TRUE; + } + else if (ABI_64_P (abfd)) { if (offset < 4 || memcmp (contents + offset - 4, leaq, 4) != 0) @@ -1153,16 +1170,31 @@ elf_x86_64_check_tls_transition (bfd *abfd, /* Check transition from LD access model. Only leaq foo@tlsld(%rip), %rdi; call __tls_get_addr - can transit to different access model. */ + can transit to different access model. For largepic + we also support: + leaq foo@tlsld(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq $rbx, %rax + call *%rax. */ static const unsigned char lea[] = { 0x48, 0x8d, 0x3d }; if (offset < 3 || (offset + 9) > sec->size) return FALSE; - if (memcmp (contents + offset - 3, lea, 3) != 0 - || 0xe8 != *(contents + offset + 4)) + if (memcmp (contents + offset - 3, lea, 3) != 0) return FALSE; + + if (0xe8 != *(contents + offset + 4)) + { + if (!ABI_64_P (abfd) + || (offset + 19) > sec->size + || memcmp (contents + offset + 4, "\x48\xb8", 2) != 0 + || memcmp (contents + offset + 14, "\x48\x01\xd8\xff\xd0", 5) + != 0) + return FALSE; + largepic = TRUE; + } } r_symndx = htab->r_sym (rel[1].r_info); @@ -1174,8 +1206,10 @@ elf_x86_64_check_tls_transition (bfd *abfd, may be versioned. */ return (h != NULL && h->root.root.string != NULL - && (ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PC32 - || ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PLT32) + && (largepic + ? ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PLTOFF64 + : (ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PC32 + || ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PLT32)) && (strncmp (h->root.root.string, "__tls_get_addr", 14) == 0)); @@ -3949,8 +3983,26 @@ direct: .word 0x6666; rex64; call __tls_get_addr into: movl %fs:0, %eax - leaq foo@tpoff(%rax), %rax */ - if (ABI_64_P (output_bfd)) + leaq foo@tpoff(%rax), %rax + For largepic, change: + leaq foo@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + into: + movq %fs:0, %rax + leaq foo@tpoff(%rax), %rax + nopw 0x0(%rax,%rax,1) */ + int largepic = 0; + if (ABI_64_P (output_bfd) + && contents[roff + 5] == (bfd_byte) '\xb8') + { + memcpy (contents + roff - 3, + "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80" + "\0\0\0\0\x66\x0f\x1f\x44\0", 22); + largepic = 1; + } + else if (ABI_64_P (output_bfd)) memcpy (contents + roff - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", 16); @@ -3960,8 +4012,8 @@ direct: 15); bfd_put_32 (output_bfd, elf_x86_64_tpoff (info, relocation), - contents + roff + 8); - /* Skip R_X86_64_PC32/R_X86_64_PLT32. */ + contents + roff + 8 + largepic); + /* Skip R_X86_64_PC32/R_X86_64_PLT32/R_X86_64_PLTOFF64. */ rel++; continue; } @@ -4196,8 +4248,26 @@ direct: .word 0x6666; rex64; call __tls_get_addr@plt into: movl %fs:0, %eax - addq foo@gottpoff(%rip), %rax */ - if (ABI_64_P (output_bfd)) + addq foo@gottpoff(%rip), %rax + For largepic, change: + leaq foo@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + into: + movq %fs:0, %rax + addq foo@gottpoff(%rax), %rax + nopw 0x0(%rax,%rax,1) */ + int largepic = 0; + if (ABI_64_P (output_bfd) + && contents[roff + 5] == (bfd_byte) '\xb8') + { + memcpy (contents + roff - 3, + "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05" + "\0\0\0\0\x66\x0f\x1f\x44\0", 22); + largepic = 1; + } + else if (ABI_64_P (output_bfd)) memcpy (contents + roff - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", 16); @@ -4209,12 +4279,13 @@ direct: relocation = (htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset + off - roff + - largepic - input_section->output_section->vma - input_section->output_offset - 12); bfd_put_32 (output_bfd, relocation, - contents + roff + 8); - /* Skip R_X86_64_PLT32. */ + contents + roff + 8 + largepic); + /* Skip R_X86_64_PLT32/R_X86_64_PLTOFF64. */ rel++; continue; } @@ -4276,16 +4347,29 @@ direct: For 64bit, we change it into: .word 0x6666; .byte 0x66; movq %fs:0, %rax. For 32bit, we change it into: - nopl 0x0(%rax); movl %fs:0, %eax. */ + nopl 0x0(%rax); movl %fs:0, %eax. + For largepic, change: + leaq foo@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + into: + data32 data32 data32 nopw %cs:0x0(%rax,%rax,1) + movq %fs:0, %eax */ BFD_ASSERT (r_type == R_X86_64_TPOFF32); - if (ABI_64_P (output_bfd)) + if (ABI_64_P (output_bfd) + && contents[rel->r_offset + 5] == (bfd_byte) '\xb8') + memcpy (contents + rel->r_offset - 3, + "\x66\x66\x66\x66\x2e\x0f\x1f\x84\0\0\0\0\0" + "\x64\x48\x8b\x04\x25\0\0\0", 22); + else if (ABI_64_P (output_bfd)) memcpy (contents + rel->r_offset - 3, "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12); else memcpy (contents + rel->r_offset - 3, "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12); - /* Skip R_X86_64_PC32/R_X86_64_PLT32. */ + /* Skip R_X86_64_PC32/R_X86_64_PLT32/R_X86_64_PLTOFF64. */ rel++; continue; } diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index f27092fb9b3..cd754cc7d8b 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2013-08-29 Jakub Jelinek + + * ld-x86-64/x86-64.exp: Add tlsld3, tlsgd7 and tlsgd8 tests. + * ld-x86-64/tlspic1.s: Add -mcmodel=large -fpic TLS GD and LD + sequences. + * ld-x86-64/tlspic.dd: Adjusted. + * ld-x86-64/tlspic.rd: Adjusted. + * ld-x86-64/tlspic-nacl.rd: Adjusted. + * ld-x86-64/tlsld3.dd: New test. + * ld-x86-64/tlsld3.s: New file. + * ld-x86-64/tlsgd7.dd: New test. + * ld-x86-64/tlsgd7.s: New file. + * ld-x86-64/tlsgd8.dd: New test. + * ld-x86-64/tlsgd8.s: New file. + 2013-08-26 Roland McGrath * ld-x86-64/x86-64.exp (Mixed x86_64 and i386 input test 1): diff --git a/ld/testsuite/ld-x86-64/tlsgd7.dd b/ld/testsuite/ld-x86-64/tlsgd7.dd new file mode 100644 index 00000000000..dfbe284f44f --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsgd7.dd @@ -0,0 +1,23 @@ +#source: tlsgd7.s +#as: --64 +#ld: -melf_x86_64 tmpdir/tlsgd7 +#objdump: -drw +#target: x86_64-*-linux* + +.*: +file format .* + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: 49 bb ([0-9a-f]{2} ){8} movabs \$0x[0-9a-f]+,%r11 +[ ]*[a-f0-9]+: 53 push %rbx +[ ]*[a-f0-9]+: 53 push %rbx +[ ]*[a-f0-9]+: 48 8d 1d ed ff ff ff lea -0x13\(%rip\),%rbx # [0-9a-f]+ <_start> +[ ]*[a-f0-9]+: 4c 01 db add %r11,%rbx +[ ]*[a-f0-9]+: 64 48 8b 04 25 00 00 00 00 mov %fs:0x0,%rax +[ ]*[a-f0-9]+: 48 8d 80 fc ff ff ff lea -0x4\(%rax\),%rax +[ ]*[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) +[ ]*[a-f0-9]+: 5b pop %rbx +[ ]*[a-f0-9]+: 5b pop %rbx +[ ]*[a-f0-9]+: c3 retq +#pass diff --git a/ld/testsuite/ld-x86-64/tlsgd7.s b/ld/testsuite/ld-x86-64/tlsgd7.s new file mode 100644 index 00000000000..cf4893029b7 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsgd7.s @@ -0,0 +1,25 @@ + .text + .globl _start +_start: +1: movabsq $_GLOBAL_OFFSET_TABLE_-1b, %r11 + pushq %rbx + pushq %rbx + leaq 1b(%rip), %rbx + addq %r11, %rbx + + /* GD, -mcmodel=large */ + leaq foo@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + + popq %rbx + popq %rbx + ret + .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/tlsgd8.dd b/ld/testsuite/ld-x86-64/tlsgd8.dd new file mode 100644 index 00000000000..10550528ca5 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsgd8.dd @@ -0,0 +1,23 @@ +#source: tlsgd8.s +#as: --64 +#ld: -melf_x86_64 tmpdir/tlsgd8 +#objdump: -drwj.text +#target: x86_64-*-linux* x86_64-*-nacl* + +.*: +file format .* + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: 49 bb ([0-9a-f]{2} ){8} movabs \$0x[0-9a-f]+,%r11 +[ ]*[a-f0-9]+: 53 push %rbx +[ ]*[a-f0-9]+: 53 push %rbx +[ ]*[a-f0-9]+: 48 8d 1d ed ff ff ff lea -0x13\(%rip\),%rbx # [0-9a-f]+ <_start> +[ ]*[a-f0-9]+: 4c 01 db add %r11,%rbx +[ ]*[a-f0-9]+: 64 48 8b 04 25 00 00 00 00 mov %fs:0x0,%rax +[ ]*[a-f0-9]+: 48 03 05 ([0-9a-f]{2} ){4} add 0x[0-9a-f]+\(%rip\),%rax # [0-9a-f]+ <_DYNAMIC\+0x140> +[ ]*[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) +[ ]*[a-f0-9]+: 5b pop %rbx +[ ]*[a-f0-9]+: 5b pop %rbx +[ ]*[a-f0-9]+: c3 retq +#pass diff --git a/ld/testsuite/ld-x86-64/tlsgd8.s b/ld/testsuite/ld-x86-64/tlsgd8.s new file mode 100644 index 00000000000..c913b29e2bc --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsgd8.s @@ -0,0 +1,18 @@ + .text + .globl _start +_start: +1: movabsq $_GLOBAL_OFFSET_TABLE_-1b, %r11 + pushq %rbx + pushq %rbx + leaq 1b(%rip), %rbx + addq %r11, %rbx + + /* GD, -mcmodel=large */ + leaq foo@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + + popq %rbx + popq %rbx + ret diff --git a/ld/testsuite/ld-x86-64/tlsld3.dd b/ld/testsuite/ld-x86-64/tlsld3.dd new file mode 100644 index 00000000000..0b639c694e9 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsld3.dd @@ -0,0 +1,23 @@ +#source: tlsld3.s +#as: --64 +#ld: -melf_x86_64 tmpdir/tlsld3 +#objdump: -drw +#target: x86_64-*-linux* + +.*: +file format .* + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: 49 bb ([0-9a-f]{2} ){8} movabs \$0x[0-9a-f]+,%r11 +[ ]*[a-f0-9]+: 53 push %rbx +[ ]*[a-f0-9]+: 53 push %rbx +[ ]*[a-f0-9]+: 48 8d 1d ed ff ff ff lea -0x13\(%rip\),%rbx # [0-9a-f]+ <_start> +[ ]*[a-f0-9]+: 4c 01 db add %r11,%rbx +[ ]*[a-f0-9]+: 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 data32 data32 data32 nopw %cs:0x0\(%rax,%rax,1\) +[ ]*[a-f0-9]+: 64 48 8b 04 25 00 00 00 00 mov %fs:0x0,%rax +[ ]*[a-f0-9]+: 8b 80 fc ff ff ff mov -0x4\(%rax\),%eax +[ ]*[a-f0-9]+: 5b pop %rbx +[ ]*[a-f0-9]+: 5b pop %rbx +[ ]*[a-f0-9]+: c3 retq +#pass diff --git a/ld/testsuite/ld-x86-64/tlsld3.s b/ld/testsuite/ld-x86-64/tlsld3.s new file mode 100644 index 00000000000..9bcdfbd5686 --- /dev/null +++ b/ld/testsuite/ld-x86-64/tlsld3.s @@ -0,0 +1,27 @@ + .text + .globl _start +_start: +1: movabsq $_GLOBAL_OFFSET_TABLE_-1b, %r11 + pushq %rbx + pushq %rbx + leaq 1b(%rip), %rbx + addq %r11, %rbx + + /* LD, -mcmodel=large */ + leaq foo@tlsld(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + + movl foo@dtpoff(%rax), %eax + + popq %rbx + popq %rbx + ret + .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/tlspic-nacl.rd b/ld/testsuite/ld-x86-64/tlspic-nacl.rd index 2ec483c1f16..d2cf7bad7da 100644 --- a/ld/testsuite/ld-x86-64/tlspic-nacl.rd +++ b/ld/testsuite/ld-x86-64/tlspic-nacl.rd @@ -11,7 +11,7 @@ Section Headers: +\[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al +\[[ 0-9]+\] +NULL +0+ 0+ 0+ 00 +0 +0 +0 +\[[ 0-9]+\] .plt +.* - +\[[ 0-9]+\] .text +PROGBITS +0+1000 [0-9a-f]+ 0+1aa 00 +AX +0 +0 4096 + +\[[ 0-9]+\] .text +PROGBITS +0+1000 [0-9a-f]+ 0+31a 00 +AX +0 +0 4096 +\[[ 0-9]+\] .hash +.* +\[[ 0-9]+\] .dynsym +.* +\[[ 0-9]+\] .dynstr +.* diff --git a/ld/testsuite/ld-x86-64/tlspic.dd b/ld/testsuite/ld-x86-64/tlspic.dd index 8b5b5fcd6e7..2f85586b22b 100644 --- a/ld/testsuite/ld-x86-64/tlspic.dd +++ b/ld/testsuite/ld-x86-64/tlspic.dd @@ -224,5 +224,162 @@ Disassembly of section .text: +11a5: 90[ ]+nop * +11a6: 90[ ]+nop * +11a7: 90[ ]+nop * - +11a8: c9[ ]+leaveq * - +11a9: c3[ ]+retq * + +11a8: 49 bb ([0-9a-f]{2} ){5}[ ]+movabs \$0x[0-9a-f]+,%r11 + +11af: ([0-9a-f]{2} ){3} + +11b2: 53[ ]+push %rbx + +11b3: 53[ ]+push %rbx + +11b4: 48 8d 1d ed ff ff ff[ ]+lea -0x13\(%rip\),%rbx +# [0-9a-f]+ + +11bb: 4c 01 db[ ]+add %r11,%rbx + +11be: 90[ ]+nop * + +11bf: 90[ ]+nop * + +11c0: 90[ ]+nop * + +11c1: 90[ ]+nop * +# -mcmodel=large sequences +# +# -mcmodel=large GD + +11c2: 48 8d 3d ([0-9a-f]{2} ){4}[ ]+lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x180> +# -> R_X86_64_DTPMOD64 sg1 + +11c9: 48 b8 ([0-9a-f]{2} ){5}[ ]+movabs \$0x[0-9a-f]+,%rax +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +11d0: ([0-9a-f]{2} ){3} + +11d3: 48 01 d8[ ]+add %rbx,%rax + +11d6: ff d0[ ]+callq \*%rax + +11d8: 90[ ]+nop * + +11d9: 90[ ]+nop * + +11da: 90[ ]+nop * + +11db: 90[ ]+nop * +# -mcmodel=large GD -> IE because variable is referenced through IE too +# -> R_X86_64_TPOFF64 sg2 + +11dc: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + +11e3: 00 00 + +11e5: 48 03 05 ([0-9a-f]{2} ){4}[ ]+add 0x[0-9a-f]+\(%rip\),%rax +# [0-9a-f]+ <_DYNAMIC\+0x1a0> +# -> R_X86_64_TPOFF64 sg2 + +11ec: 66 0f 1f 44 00 00[ ]+nopw 0x0\(%rax,%rax,1\) + +11f2: 90[ ]+nop * + +11f3: 90[ ]+nop * + +11f4: 90[ ]+nop * + +11f5: 90[ ]+nop * +# -mcmodel=large GD against local variable + +11f6: 48 8d 3d ([0-9a-f]{2} ){4}[ ]+lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x130> +# -> R_X86_64_DTPMOD64 [0 0x2000000000000000] + +11fd: 48 b8 ([0-9a-f]{2} ){5}[ ]+movabs \$0x[0-9a-f]+,%rax +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +1204: ([0-9a-f]{2} ){3} + +1207: 48 01 d8[ ]+add %rbx,%rax + +120a: ff d0[ ]+callq \*%rax + +120c: 90[ ]+nop * + +120d: 90[ ]+nop * + +120e: 90[ ]+nop * + +120f: 90[ ]+nop * +# -mcmodel=large GD -> IE against local variable referenced through IE too + +1210: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + +1217: 00 00 + +1219: 48 03 05 ([0-9a-f]{2} ){4}[ ]+add 0x[0-9a-f]+\(%rip\),%rax +# [0-9a-f]+ <_DYNAMIC\+0x140> +# -> R_X86_64_TPOFF64 *ABS*+0x24 + +1220: 66 0f 1f 44 00 00[ ]+nopw 0x0\(%rax,%rax,1\) + +1226: 90[ ]+nop * + +1227: 90[ ]+nop * + +1228: 90[ ]+nop * + +1229: 90[ ]+nop * +# -mcmodel=large GD against hidden and local variable + +122a: 48 8d 3d ([0-9a-f]{2} ){4}[ ]+lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x1a8> +# -> R_X86_64_DTPMOD64 [0 0x4000000000000000] + +1231: 48 b8 ([0-9a-f]{2} ){5}[ ]+movabs \$0x[0-9a-f]+,%rax +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +1238: ([0-9a-f]{2} ){3} + +123b: 48 01 d8[ ]+add %rbx,%rax + +123e: ff d0[ ]+callq \*%rax + +1240: 90[ ]+nop * + +1241: 90[ ]+nop * + +1242: 90[ ]+nop * + +1243: 90[ ]+nop * +# -mcmodel=large GD -> IE against hidden and local variable referenced through IE too + +1244: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + +124b: 00 00 + +124d: 48 03 05 ([0-9a-f]{2} ){4}[ ]+add 0x[0-9a-f]+\(%rip\),%rax +# [0-9a-f]+ <_DYNAMIC\+0x1b8> +# -> R_X86_64_TPOFF64 *ABS*+0x44 + +1254: 66 0f 1f 44 00 00[ ]+nopw 0x0\(%rax,%rax,1\) + +125a: 90[ ]+nop * + +125b: 90[ ]+nop * + +125c: 90[ ]+nop * + +125d: 90[ ]+nop * +# -mcmodel=large GD against hidden but not local variable + +125e: 48 8d 3d ([0-9a-f]{2} ){4}[ ]+lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x160> +# -> R_X86_64_DTPMOD64 [0 0x6000000000000000] + +1265: 48 b8 ([0-9a-f]{2} ){5}[ ]+movabs \$0x[0-9a-f]+,%rax +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +126c: ([0-9a-f]{2} ){3} + +126f: 48 01 d8[ ]+add %rbx,%rax + +1272: ff d0[ ]+callq \*%rax + +1274: 90[ ]+nop * + +1275: 90[ ]+nop * + +1276: 90[ ]+nop * + +1277: 90[ ]+nop * +# -mcmodel=large GD -> IE against hidden but not local variable referenced through IE too + +1278: 64 48 8b 04 25 00 00[ ]+mov %fs:0x0,%rax + +127f: 00 00 + +1281: 48 03 05 ([0-9a-f]{2} ){4}[ ]+add 0x[0-9a-f]+\(%rip\),%rax +# [0-9a-f]+ <_DYNAMIC\+0x170> +# -> R_X86_64_TPOFF64 *ABS*+0x64 + +1288: 66 0f 1f 44 00 00[ ]+nopw 0x0\(%rax,%rax,1\) + +128e: 90[ ]+nop * + +128f: 90[ ]+nop * + +1290: 90[ ]+nop * + +1291: 90[ ]+nop * +# -mcmodel=large LD + +1292: 48 8d 3d ([0-9a-f]{2} ){4}[ ]+lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x150> +# -> R_X86_64_DTPMOD64 [0 0x000000000000000] + +1299: 48 b8 ([0-9a-f]{2} ){5}[ ]+movabs \$0x[0-9a-f]+,%rax +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +12a0: ([0-9a-f]{2} ){3} + +12a3: 48 01 d8[ ]+add %rbx,%rax + +12a6: ff d0[ ]+callq \*%rax + +12a8: 90[ ]+nop * + +12a9: 90[ ]+nop * + +12aa: 48 8d 90 20 00 00 00[ ]+lea 0x20\(%rax\),%rdx + +12b1: 90[ ]+nop * + +12b2: 90[ ]+nop * + +12b3: 4c 8d 88 26 00 00 00[ ]+lea 0x26\(%rax\),%r9 + +12ba: 90[ ]+nop * + +12bb: 90[ ]+nop * + +12bc: 90[ ]+nop * + +12bd: 90[ ]+nop * +# -mcmodel=large LD against hidden and local variables + +12be: 48 8d 3d ([0-9a-f]{2} ){4}[ ]+lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x150> +# -> R_X86_64_DTPMOD64 [0 0x000000000000000] + +12c5: 48 b8 ([0-9a-f]{2} ){5}[ ]+movabs \$0x[0-9a-f]+,%rax +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +12cc: ([0-9a-f]{2} ){3} + +12cf: 48 01 d8[ ]+add %rbx,%rax + +12d2: ff d0[ ]+callq \*%rax + +12d4: 90[ ]+nop * + +12d5: 90[ ]+nop * + +12d6: 48 8d 90 40 00 00 00[ ]+lea 0x40\(%rax\),%rdx + +12dd: 90[ ]+nop * + +12de: 90[ ]+nop * + +12df: 48 8d 88 47 00 00 00[ ]+lea 0x47\(%rax\),%rcx + +12e6: 90[ ]+nop * + +12e7: 90[ ]+nop * + +12e8: 90[ ]+nop * + +12e9: 90[ ]+nop * +# -mcmodel=large LD against hidden but not local variables + +12ea: 48 8d 3d ([0-9a-f]{2} ){4}[ ]+lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x150> +# -> R_X86_64_DTPMOD64 [0 0x000000000000000] + +12f1: 48 b8 ([0-9a-f]{2} ){5}[ ]+movabs \$0x[0-9a-f]+,%rax +# -> R_X86_64_JUMP_SLOT __tls_get_addr + +12f8: ([0-9a-f]{2} ){3} + +12fb: 48 01 d8[ ]+add %rbx,%rax + +12fe: ff d0[ ]+callq \*%rax + +1300: 90[ ]+nop * + +1301: 90[ ]+nop * + +1302: 4c 8d a0 60 00 00 00[ ]+lea 0x60\(%rax\),%r12 + +1309: 90[ ]+nop * + +130a: 90[ ]+nop * + +130b: 48 8d 88 65 00 00 00[ ]+lea 0x65\(%rax\),%rcx + +1312: 90[ ]+nop * + +1313: 90[ ]+nop * + +1314: 90[ ]+nop * + +1315: 90[ ]+nop * + +1316: 5b[ ]+pop %rbx + +1317: 5b[ ]+pop %rbx + +1318: c9[ ]+leaveq + +1319: c3[ ]+retq diff --git a/ld/testsuite/ld-x86-64/tlspic.rd b/ld/testsuite/ld-x86-64/tlspic.rd index e54e20fe0ed..3caed27ce73 100644 --- a/ld/testsuite/ld-x86-64/tlspic.rd +++ b/ld/testsuite/ld-x86-64/tlspic.rd @@ -16,12 +16,12 @@ Section Headers: +\[[ 0-9]+\] .rela.dyn +.* +\[[ 0-9]+\] .rela.plt +.* +\[[ 0-9]+\] .plt +.* - +\[[ 0-9]+\] .text +PROGBITS +0+1000 0+1000 0+1aa 00 +AX +0 +0 4096 - +\[[ 0-9]+\] .tdata +PROGBITS +0+2011aa 0+11aa 0+60 00 WAT +0 +0 +1 - +\[[ 0-9]+\] .tbss +NOBITS +0+20120a 0+120a 0+20 00 WAT +0 +0 +1 - +\[[ 0-9]+\] .dynamic +DYNAMIC +0+201210 0+1210 0+130 10 +WA +3 +0 +8 - +\[[ 0-9]+\] .got +PROGBITS +0+201340 0+1340 0+90 08 +WA +0 +0 +8 - +\[[ 0-9]+\] .got.plt +PROGBITS +0+2013d0 0+13d0 0+20 08 +WA +0 +0 +8 + +\[[ 0-9]+\] .text +PROGBITS +0+1000 0+1000 0+31a 00 +AX +0 +0 4096 + +\[[ 0-9]+\] .tdata +PROGBITS +0+20131a 0+131a 0+60 00 WAT +0 +0 +1 + +\[[ 0-9]+\] .tbss +NOBITS +0+20137a 0+137a 0+20 00 WAT +0 +0 +1 + +\[[ 0-9]+\] .dynamic +DYNAMIC +0+201380 0+1380 0+130 10 +WA +3 +0 +8 + +\[[ 0-9]+\] .got +PROGBITS +0+2014b0 0+14b0 0+90 08 +WA +0 +0 +8 + +\[[ 0-9]+\] .got.plt +PROGBITS +0+201540 0+1540 0+20 08 +WA +0 +0 +8 +\[[ 0-9]+\] .shstrtab +.* +\[[ 0-9]+\] .symtab +.* +\[[ 0-9]+\] .strtab +.* @@ -37,9 +37,9 @@ There are [0-9]+ program headers, starting at offset [0-9]+ Program Headers: +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align +LOAD +0x0+ 0x0+ 0x0+ 0x[0-9a-f]+ 0x[0-9a-f]+ R E 0x200000 - +LOAD +0x0+11aa 0x0+2011aa 0x0+2011aa 0x0+246 0x0+246 RW +0x200000 - +DYNAMIC +0x0+1210 0x0+201210 0x0+201210 0x0+130 0x0+130 RW +0x8 - +TLS +0x0+11aa 0x0+2011aa 0x0+2011aa 0x0+60 0x0+80 R +0x1 + +LOAD +0x0+131a 0x0+20131a 0x0+20131a 0x0+246 0x0+246 RW +0x200000 + +DYNAMIC +0x0+1380 0x0+201380 0x0+201380 0x0+130 0x0+130 RW +0x8 + +TLS +0x0+131a 0x0+20131a 0x0+20131a 0x0+60 0x0+80 R +0x1 Section to Segment mapping: +Segment Sections... diff --git a/ld/testsuite/ld-x86-64/tlspic1.s b/ld/testsuite/ld-x86-64/tlspic1.s index 5e26f26cd92..aa18f36fad2 100644 --- a/ld/testsuite/ld-x86-64/tlspic1.s +++ b/ld/testsuite/ld-x86-64/tlspic1.s @@ -183,5 +183,108 @@ fn1: movq %fs:(%rcx), %rdx nop;nop;nop;nop +1: movabsq $_GLOBAL_OFFSET_TABLE_-1b, %r11 + pushq %rbx + pushq %rbx + leaq 1b(%rip), %rbx + addq %r11, %rbx + nop;nop;nop;nop + + /* -mcmodel=large sequences */ + + /* -mcmodel=large GD */ + leaq sg1@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop;nop;nop + + /* -mcmodel=large GD -> IE because variable is referenced through IE too */ + leaq sg2@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop;nop;nop + + /* -mcmodel=large GD against local variable */ + leaq sl1@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop;nop;nop + + /* -mcmodel=large GD -> IE against local variable referenced through IE too */ + leaq sl2@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop;nop;nop + + /* -mcmodel=large GD against hidden and local variable */ + leaq sh1@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop;nop;nop + + /* -mcmodel=large GD -> IE against hidden and local variable referenced through + IE too */ + leaq sh2@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop;nop;nop + + /* -mcmodel=large GD against hidden but not local variable */ + leaq sH1@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop;nop;nop + + /* -mcmodel=large GD -> IE against hidden but not local variable referenced through + IE too */ + leaq sH2@tlsgd(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop;nop;nop + + /* -mcmodel=large LD */ + leaq sl1@tlsld(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop + leaq sl1@dtpoff(%rax), %rdx + nop;nop + leaq 2+sl2@dtpoff(%rax), %r9 + nop;nop;nop;nop + + /* -mcmodel=large LD against hidden and local variables */ + leaq sh1@tlsld(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop + leaq sh1@dtpoff(%rax), %rdx + nop;nop + leaq sh2@dtpoff+3(%rax), %rcx + nop;nop;nop;nop + + /* -mcmodel=large LD against hidden but not local variables */ + leaq sH1@tlsld(%rip), %rdi + movabsq $__tls_get_addr@pltoff, %rax + addq %rbx, %rax + call *%rax + nop;nop + leaq sH1@dtpoff(%rax), %r12 + nop;nop + leaq sH2@dtpoff+1(%rax), %rcx + nop;nop;nop;nop + + popq %rbx + popq %rbx + leave ret diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 8ca2da757a6..3ddce846be6 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -124,6 +124,15 @@ set x86_64tests { {"TLS X32 LD->LE transition" "-melf32_x86_64" "" "--x32" {tlsld2.s} {{objdump -dwr tlsld2.dd}} "tlsld2"} + {"TLS -mcmodel=large GD->LE transition" "-melf_x86_64" "" + "--64" {tlsgd7.s} + {{objdump -dwr tlsgd7.dd}} "tlsgd7"} + {"TLS -mcmodel=large LD->LE transition" "-melf_x86_64" "" + "--64" {tlsld3.s} + {{objdump -dwr tlsld3.dd}} "tlsld3"} + {"TLS -mcmodel=large GD->IE transition" "-melf_x86_64 tmpdir/libtlsgd5.so" "" + "--64" {tlsgd8.s} + {{objdump -dwrj.text tlsgd8.dd}} "tlsgd8"} {"build 32-bit object with 33 locals" "-melf_x86_64 -e 0" "" "--32" {32bit.s} {{ ld incompatible.l }} "dummy" } {"build 64-bit object" "-melf_x86_64 -e 0 --defsym foo=1" "" "--64" {64bit.s} {} "dummy" } -- 2.30.2