This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb/binutils-2_25-branch] Correct PowerPC64 local-dynamic TLS linker optimization


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=44d57bfed170b3ba18162e6715e1450dc33a0ab7

commit 44d57bfed170b3ba18162e6715e1450dc33a0ab7
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Jan 29 11:09:55 2015 +1030

    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.

Diff:
---
 bfd/ChangeLog                       |  6 +++++
 bfd/elf32-ppc.c                     | 15 ++++++++----
 bfd/elf64-ppc.c                     | 13 ++++++----
 ld/testsuite/ChangeLog              |  5 ++++
 ld/testsuite/ld-powerpc/powerpc.exp |  3 +++
 ld/testsuite/ld-powerpc/tlsld.d     | 43 +++++++++++++++++++++++++++++++++
 ld/testsuite/ld-powerpc/tlsld.s     | 48 +++++++++++++++++++++++++++++++++++++
 ld/testsuite/ld-powerpc/tlsld32.d   | 44 ++++++++++++++++++++++++++++++++++
 ld/testsuite/ld-powerpc/tlsld32.s   | 43 +++++++++++++++++++++++++++++++++
 9 files changed, 211 insertions(+), 9 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index cba389e..45f9c69 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,6 +1,12 @@
 2015-02-11  Alan Modra  <amodra@gmail.com>
 
 	Apply from master.
+	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-20  Alan Modra  <amodra@gmail.com>
 	PR ld/17615
 	* elf64-ppc.c (ppc64_elf_gc_mark_dynamic_ref): Don't drop
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 1ebb2c7..57d6349 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -7754,8 +7754,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);
@@ -7788,12 +7788,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)
 		    {
@@ -7808,7 +7812,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.  */
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 318f41a..2cff63e 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -13406,12 +13406,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)
@@ -13426,7 +13430,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)
 		    {
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 3bf2758..44a2b0a 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,6 +1,11 @@
 2015-02-11  Alan Modra  <amodra@gmail.com>
 
 	Apply from master.
+	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.
+
 	2015-01-20  Andrew Burgess  <andrew.burgess@embecosm.com>
 	* ld-scripts/provide-4-map.d: Update expected output.
 	* ld-scripts/provide-5-map.d: Likewise.
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 645236d..8fc261e 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -282,8 +282,11 @@ if [ supports_ppc64 ] then {
     run_dump_test "ambiguousv2"
     run_dump_test "ambiguousv2b"
     run_dump_test "defsym"
+    run_dump_test "tlsld"
 }
 
+run_dump_test "tlsld32"
+
 if { [istarget "powerpc*-eabi*"] } {
     run_ld_link_tests $ppceabitests
 }
diff --git a/ld/testsuite/ld-powerpc/tlsld.d b/ld/testsuite/ld-powerpc/tlsld.d
new file mode 100644
index 0000000..d66d1db
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/tlsld.d
@@ -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
diff --git a/ld/testsuite/ld-powerpc/tlsld.s b/ld/testsuite/ld-powerpc/tlsld.s
new file mode 100644
index 0000000..925d8bf
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/tlsld.s
@@ -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
diff --git a/ld/testsuite/ld-powerpc/tlsld32.d b/ld/testsuite/ld-powerpc/tlsld32.d
new file mode 100644
index 0000000..b0fd657
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/tlsld32.d
@@ -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
diff --git a/ld/testsuite/ld-powerpc/tlsld32.s b/ld/testsuite/ld-powerpc/tlsld32.s
new file mode 100644
index 0000000..f5561d4
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/tlsld32.s
@@ -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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]