aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elf32-ppc.c16
-rw-r--r--ld/testsuite/ld-powerpc/powerpc.exp1
-rw-r--r--ld/testsuite/ld-powerpc/tls32ldgd.d13
-rw-r--r--ld/testsuite/ld-powerpc/tls32ldgd.s16
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