Correct PowerPC64 local-dynamic TLS linker optimization
The linker hardcoded r3 into a local-dynamic to local-exec TLS optimization sequence. This is normally the case since r3 is required as a parameter to (the optimized out) __tls_get_addr call. However, it is possible for a compiler, LLVM in this case, to set up the parameter value in another register then copy it to r3 before the call. When fixing this problem, I noticed that ppc32 had another bug when optimizing away one of the TLS insns to a nop. The patch also tidies a mask used by global-dynamic to initial-exec TLS optimization, to just select the fields needed. Leaving the offset in the instruction wasn't a bug since it will be overwritten anyway. bfd/ * elf64-ppc.c (ppc64_elf_relocate_section): Correct GOT_TLSLD optimization. Tidy mask for GOT_TLSGD optimization. * elf32-ppc.c (ppc_elf_relocate_section): Likewise. Correct location of nop zapping high insn too. ld/testsuite/ * ld-powerpc/tlsld.d, * ld-powerpc/tlsld.s: New test. * ld-powerpc/tlsld32.d, * ld-powerpc/tlsld32.s: New test. * ld-powerpc/powerpc.exp: Run them. Move tocvar and tocnovar.
This commit is contained in:
parent
912ae7dd0f
commit
b86ac8e3a5
9 changed files with 215 additions and 11 deletions
|
@ -1,3 +1,10 @@
|
|||
2015-01-29 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf64-ppc.c (ppc64_elf_relocate_section): Correct GOT_TLSLD
|
||||
optimization. Tidy mask for GOT_TLSGD optimization.
|
||||
* elf32-ppc.c (ppc_elf_relocate_section): Likewise. Correct
|
||||
location of nop zapping high insn too.
|
||||
|
||||
2015-01-28 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf64-ppc.h (struct ppc64_elf_params): Add "object_in_toc".
|
||||
|
|
|
@ -7760,8 +7760,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
+ R_PPC_GOT_TPREL16);
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
|
||||
rel->r_offset -= d_offset;
|
||||
bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
|
||||
r_type = R_PPC_NONE;
|
||||
}
|
||||
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
||||
|
@ -7794,12 +7794,16 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
&& branch_reloc_hash_match (input_bfd, rel + 1,
|
||||
htab->tls_get_addr))
|
||||
offset = rel[1].r_offset;
|
||||
/* We read the low GOT_TLS insn because we need to keep
|
||||
the destination reg. It may be something other than
|
||||
the usual r3, and moved to r3 before the call by
|
||||
intervening code. */
|
||||
insn1 = bfd_get_32 (output_bfd,
|
||||
contents + rel->r_offset - d_offset);
|
||||
if ((tls_mask & tls_gd) != 0)
|
||||
{
|
||||
/* IE */
|
||||
insn1 = bfd_get_32 (output_bfd,
|
||||
contents + rel->r_offset - d_offset);
|
||||
insn1 &= (1 << 26) - 1;
|
||||
insn1 &= (0x1f << 21) | (0x1f << 16);
|
||||
insn1 |= 32 << 26; /* lwz */
|
||||
if (offset != (bfd_vma) -1)
|
||||
{
|
||||
|
@ -7814,7 +7818,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
else
|
||||
{
|
||||
/* LE */
|
||||
insn1 = 0x3c620000; /* addis 3,2,0 */
|
||||
insn1 &= 0x1f << 21;
|
||||
insn1 |= 0x3c020000; /* addis r,2,0 */
|
||||
if (tls_gd == 0)
|
||||
{
|
||||
/* Was an LD reloc. */
|
||||
|
|
|
@ -13417,12 +13417,16 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
htab->tls_get_addr,
|
||||
htab->tls_get_addr_fd))
|
||||
offset = rel[1].r_offset;
|
||||
/* We read the low GOT_TLS (or TOC16) insn because we
|
||||
need to keep the destination reg. It may be
|
||||
something other than the usual r3, and moved to r3
|
||||
before the call by intervening code. */
|
||||
insn1 = bfd_get_32 (output_bfd,
|
||||
contents + rel->r_offset - d_offset);
|
||||
if ((tls_mask & tls_gd) != 0)
|
||||
{
|
||||
/* IE */
|
||||
insn1 = bfd_get_32 (output_bfd,
|
||||
contents + rel->r_offset - d_offset);
|
||||
insn1 &= (1 << 26) - (1 << 2);
|
||||
insn1 &= (0x1f << 21) | (0x1f << 16);
|
||||
insn1 |= 58 << 26; /* ld */
|
||||
insn2 = 0x7c636a14; /* add 3,3,13 */
|
||||
if (offset != (bfd_vma) -1)
|
||||
|
@ -13437,7 +13441,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
else
|
||||
{
|
||||
/* LE */
|
||||
insn1 = 0x3c6d0000; /* addis 3,13,0 */
|
||||
insn1 &= 0x1f << 21;
|
||||
insn1 |= 0x3c0d0000; /* addis r,13,0 */
|
||||
insn2 = 0x38630000; /* addi 3,3,0 */
|
||||
if (tls_gd == 0)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2015-01-29 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ld-powerpc/tlsld.d, * ld-powerpc/tlsld.s: New test.
|
||||
* ld-powerpc/tlsld32.d, * ld-powerpc/tlsld32.s: New test.
|
||||
* ld-powerpc/powerpc.exp: Run them. Move tocvar and tocnovar.
|
||||
|
||||
2015-01-28 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/17878
|
||||
|
|
|
@ -282,8 +282,13 @@ if [ supports_ppc64 ] then {
|
|||
run_dump_test "ambiguousv2"
|
||||
run_dump_test "ambiguousv2b"
|
||||
run_dump_test "defsym"
|
||||
run_dump_test "tocvar"
|
||||
run_dump_test "tocnovar"
|
||||
run_dump_test "tlsld"
|
||||
}
|
||||
|
||||
run_dump_test "tlsld32"
|
||||
|
||||
if { [istarget "powerpc*-eabi*"] } {
|
||||
run_ld_link_tests $ppceabitests
|
||||
}
|
||||
|
@ -320,5 +325,3 @@ run_dump_test "attr-gnu-12-11"
|
|||
run_dump_test "attr-gnu-12-21"
|
||||
|
||||
run_dump_test "vle-multiseg-6"
|
||||
run_dump_test "tocvar"
|
||||
run_dump_test "tocnovar"
|
||||
|
|
43
ld/testsuite/ld-powerpc/tlsld.d
Normal file
43
ld/testsuite/ld-powerpc/tlsld.d
Normal file
|
@ -0,0 +1,43 @@
|
|||
#source: tlsld.s
|
||||
#as: -a64
|
||||
#ld: -melf64ppc
|
||||
#objdump: -dr
|
||||
#target: powerpc64*-*-*
|
||||
|
||||
.*: file format .*
|
||||
|
||||
Disassembly of section \.text:
|
||||
|
||||
.*:
|
||||
.* nop
|
||||
.* addis r29,r13,0
|
||||
.* mr r3,r29
|
||||
.* nop
|
||||
.* addi r3,r3,4096
|
||||
.* addis r3,r3,0
|
||||
.* ld r3,-32768\(r3\)
|
||||
.* nop
|
||||
.* addis r29,r13,0
|
||||
.* mr r3,r29
|
||||
.* nop
|
||||
.* addi r3,r3,4096
|
||||
.* ld r3,-32768\(r3\)
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
||||
.* addis r29,r13,0
|
||||
.* mr r3,r29
|
||||
.* nop
|
||||
.* addi r3,r3,-28672
|
||||
.* ld r3,0\(r3\)
|
||||
.* nop
|
||||
.* nop
|
||||
.* addis r29,r13,0
|
||||
.* mr r3,r29
|
||||
.* nop
|
||||
.* addi r3,r3,-28672
|
||||
.* ld r3,0\(r3\)
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
48
ld/testsuite/ld-powerpc/tlsld.s
Normal file
48
ld/testsuite/ld-powerpc/tlsld.s
Normal file
|
@ -0,0 +1,48 @@
|
|||
.section ".opd","aw",@progbits
|
||||
.p2align 3
|
||||
.globl _start
|
||||
_start:
|
||||
.quad .L_start,.TOC.@tocbase,0
|
||||
|
||||
.text
|
||||
.L_start:
|
||||
addis 3,2,PrettyStackTraceHead@got@tlsld@ha
|
||||
addi 29,3,PrettyStackTraceHead@got@tlsld@l
|
||||
mr 3,29
|
||||
bl __tls_get_addr(PrettyStackTraceHead@tlsld)
|
||||
nop
|
||||
addis 3,3,PrettyStackTraceHead@dtprel@ha
|
||||
ld 3,PrettyStackTraceHead@dtprel@l(3)
|
||||
nop
|
||||
|
||||
addi 29,2,PrettyStackTraceHead@got@tlsld
|
||||
mr 3,29
|
||||
bl __tls_get_addr(PrettyStackTraceHead@tlsld)
|
||||
nop
|
||||
ld 3,PrettyStackTraceHead@dtprel(3)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
addis 3,2,PrettyStackTraceHead@got@tlsgd@ha
|
||||
addi 29,3,PrettyStackTraceHead@got@tlsgd@l
|
||||
mr 3,29
|
||||
bl __tls_get_addr(PrettyStackTraceHead@tlsgd)
|
||||
nop
|
||||
ld 3,0(3)
|
||||
nop
|
||||
nop
|
||||
|
||||
addi 29,2,PrettyStackTraceHead@got@tlsgd
|
||||
mr 3,29
|
||||
bl __tls_get_addr(PrettyStackTraceHead@tlsgd)
|
||||
nop
|
||||
ld 3,0(3)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.section ".tbss","awT",@nobits
|
||||
.align 3
|
||||
PrettyStackTraceHead:
|
||||
.space 8
|
44
ld/testsuite/ld-powerpc/tlsld32.d
Normal file
44
ld/testsuite/ld-powerpc/tlsld32.d
Normal file
|
@ -0,0 +1,44 @@
|
|||
#source: tlsld32.s
|
||||
#as: -a32
|
||||
#ld: -melf32ppc
|
||||
#objdump: -dr
|
||||
#target: powerpc*-*-*
|
||||
|
||||
.*: file format .*
|
||||
|
||||
Disassembly of section \.text:
|
||||
|
||||
.*:
|
||||
.* nop
|
||||
.* addis r29,r2,0
|
||||
.* mr r3,r29
|
||||
.* addi r3,r3,4096
|
||||
.* addis r3,r3,0
|
||||
.* lwz r3,-32768\(r3\)
|
||||
.* nop
|
||||
.* nop
|
||||
.* addis r29,r2,0
|
||||
.* mr r3,r29
|
||||
.* addi r3,r3,4096
|
||||
.* lwz r3,-32768\(r3\)
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
||||
.* addis r29,r2,0
|
||||
.* mr r3,r29
|
||||
.* addi r3,r3,-28672
|
||||
.* lwz r3,0\(r3\)
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
||||
.* addis r29,r2,0
|
||||
.* mr r3,r29
|
||||
.* addi r3,r3,-28672
|
||||
.* lwz r3,0\(r3\)
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
||||
.* nop
|
||||
#pass
|
43
ld/testsuite/ld-powerpc/tlsld32.s
Normal file
43
ld/testsuite/ld-powerpc/tlsld32.s
Normal file
|
@ -0,0 +1,43 @@
|
|||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
addis 3,31,PrettyStackTraceHead@got@tlsld@ha
|
||||
addi 29,3,PrettyStackTraceHead@got@tlsld@l
|
||||
mr 3,29
|
||||
bl __tls_get_addr(PrettyStackTraceHead@tlsld)
|
||||
addis 3,3,PrettyStackTraceHead@dtprel@ha
|
||||
lwz 3,PrettyStackTraceHead@dtprel@l(3)
|
||||
nop
|
||||
nop
|
||||
|
||||
addi 29,31,PrettyStackTraceHead@got@tlsld
|
||||
mr 3,29
|
||||
bl __tls_get_addr(PrettyStackTraceHead@tlsld)
|
||||
lwz 3,PrettyStackTraceHead@dtprel(3)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
addis 3,31,PrettyStackTraceHead@got@tlsgd@ha
|
||||
addi 29,3,PrettyStackTraceHead@got@tlsgd@l
|
||||
mr 3,29
|
||||
bl __tls_get_addr(PrettyStackTraceHead@tlsgd)
|
||||
lwz 3,0(3)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
addi 29,31,PrettyStackTraceHead@got@tlsgd
|
||||
mr 3,29
|
||||
bl __tls_get_addr(PrettyStackTraceHead@tlsgd)
|
||||
lwz 3,0(3)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.section ".tbss","awT",@nobits
|
||||
.align 2
|
||||
PrettyStackTraceHead:
|
||||
.space 4
|
Loading…
Reference in a new issue