public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb/binutils-2_40-branch] PR30697, ppc32 mix of local-dynamic and global-dynamic TLS
@ 2023-08-04  9:06 Alan Modra
  0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2023-08-04  9:06 UTC (permalink / raw)
  To: bfd-cvs

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

commit 391fd4d9ee5d2b78244cbcd57fc405738359b70b
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Aug 4 15:09:53 2023 +0930

    PR30697, ppc32 mix of local-dynamic and global-dynamic TLS
    
    This fixes miscounting of dynamic relocations on GOT entries when
    a) there are both local-dynamic and global-dynamic tls accesss for a
       given symbol, and
    b) the symbol is global with non-default visibility, and
    c) the __tls_get_addr calls aren't optimised away.
    
            PR 30697
    bfd/
            * elf32-ppc.c (allocate_dynrelocs): Correct local-dynamic
            reloc count.
    ld/
            * testsuite/ld-powerpc/tls32ldgd.d,
            * testsuite/ld-powerpc/tls32ldgd.s: New test.
            * testsuite/ld-powerpc/powerpc.exp: Run it.
    
    (cherry picked from commit ae33771224660dac25e64c3f70943a17bfab7681)

Diff:
---
 bfd/elf32-ppc.c                     | 16 +++++++---------
 ld/testsuite/ld-powerpc/powerpc.exp |  1 +
 ld/testsuite/ld-powerpc/tls32ldgd.d | 13 +++++++++++++
 ld/testsuite/ld-powerpc/tls32ldgd.s | 16 ++++++++++++++++
 4 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 833bc744563..34df50a3582 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -5130,13 +5130,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	  && eh->has_addr16_lo
 	  && htab->params->pic_fixup > 0))
     {
-      unsigned int need;
-
       /* Make sure this symbol is output as a dynamic symbol.  */
       if (!ensure_undef_dynamic (info, &eh->elf))
 	return false;
 
-      need = 0;
+      unsigned int need = got_entries_needed (eh->tls_mask);
+      unsigned int rel_need = need * sizeof (Elf32_External_Rela) / 4;
       if ((eh->tls_mask & (TLS_TLS | TLS_LD)) == (TLS_TLS | TLS_LD))
 	{
 	  if (SYMBOL_REFERENCES_LOCAL (info, &eh->elf))
@@ -5145,9 +5144,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	       a local dynamic reloc against a non-local symbol.  */
 	    htab->tlsld_got.refcount += 1;
 	  else
-	    need += 8;
+	    {
+	      need += 8;
+	      rel_need += sizeof (Elf32_External_Rela);
+	    }
 	}
-      need += got_entries_needed (eh->tls_mask);
       if (need == 0)
 	eh->elf.got.offset = (bfd_vma) -1;
       else
@@ -5165,13 +5166,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	    {
 	      asection *rsec;
 
-	      need *= sizeof (Elf32_External_Rela) / 4;
-	      if ((eh->tls_mask & (TLS_TLS | TLS_LD)) == (TLS_TLS | TLS_LD))
-		need -= sizeof (Elf32_External_Rela);
 	      rsec = htab->elf.srelgot;
 	      if (eh->elf.type == STT_GNU_IFUNC)
 		rsec = htab->elf.irelplt;
-	      rsec->size += need;
+	      rsec->size += rel_need;
 	    }
 	}
     }
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 16e25b09a14..6cb7bd2577e 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -522,5 +522,6 @@ run_dump_test "non-contiguous-powerpc"
 
 run_dump_test "tprel32"
 run_dump_test "tprelbad"
+run_dump_test tls32ldgd
 
 run_dump_test "undefweak"
diff --git a/ld/testsuite/ld-powerpc/tls32ldgd.d b/ld/testsuite/ld-powerpc/tls32ldgd.d
new file mode 100644
index 00000000000..88e26b9b2c0
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/tls32ldgd.d
@@ -0,0 +1,13 @@
+#as: -a32
+#ld: -shared -melf32ppc
+#readelf: -rW
+
+Relocation section '\.rela\.dyn' at offset .* contains 3 entries:
+ Offset +Info +Type +Sym\. Value +Symbol's Name \+ Addend
+.* +00000044 R_PPC_DTPMOD32 +0
+.* +0000004e R_PPC_DTPREL32 +0
+.* +00000044 R_PPC_DTPMOD32 +0
+
+Relocation section '\.rela\.plt' at offset .* contains 1 entry:
+ Offset +Info +Type +Sym\. Value +Symbol's Name \+ Addend
+.* +00000215 R_PPC_JMP_SLOT +00000000 +__tls_get_addr \+ 0
diff --git a/ld/testsuite/ld-powerpc/tls32ldgd.s b/ld/testsuite/ld-powerpc/tls32ldgd.s
new file mode 100644
index 00000000000..889eb444c6a
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/tls32ldgd.s
@@ -0,0 +1,16 @@
+#PR 30697
+	.section ".tbss","awT",@nobits
+	.global _start,x
+	.hidden x
+	.align 2
+x:	.space 4
+
+	.text
+_start:
+ addi 3,30,x@got@tlsgd
+ bl __tls_get_addr(x@tlsgd)@plt
+
+ addi 3,30,x@got@tlsld
+ bl __tls_get_addr(x@tlsld)@plt
+ addis 3,3,x@dtprel@ha
+ addi 3,3,x@dtprel@l

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-08-04  9:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-04  9:06 [binutils-gdb/binutils-2_40-branch] PR30697, ppc32 mix of local-dynamic and global-dynamic TLS Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).