* 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.
This commit is contained in:
Jakub Jelinek 2013-08-29 10:25:27 +00:00
parent 5b791bb530
commit 5c98a14e1e
14 changed files with 546 additions and 32 deletions

View file

@ -1,3 +1,10 @@
2013-08-29 Jakub Jelinek <jakub@redhat.com>
* 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 <amodra@gmail.com>
* elf-bfd.h (struct elf_backend_data): Remove as_needed_cleanup.

View file

@ -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;
}

View file

@ -1,3 +1,18 @@
2013-08-29 Jakub Jelinek <jakub@redhat.com>
* 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 <mcgrathr@google.com>
* ld-x86-64/x86-64.exp (Mixed x86_64 and i386 input test 1):

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 +.*

View file

@ -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]+ <fn1\+0x[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

View file

@ -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...

View file

@ -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

View file

@ -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" }