Skip to content

Commit ae33771

Browse files
committed
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.
1 parent 49459ed commit ae33771

File tree

4 files changed

+37
-9
lines changed

4 files changed

+37
-9
lines changed

bfd/elf32-ppc.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -5126,13 +5126,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
51265126
&& eh->has_addr16_lo
51275127
&& htab->params->pic_fixup > 0))
51285128
{
5129-
unsigned int need;
5130-
51315129
/* Make sure this symbol is output as a dynamic symbol. */
51325130
if (!ensure_undef_dynamic (info, &eh->elf))
51335131
return false;
51345132

5135-
need = 0;
5133+
unsigned int need = got_entries_needed (eh->tls_mask);
5134+
unsigned int rel_need = need * sizeof (Elf32_External_Rela) / 4;
51365135
if ((eh->tls_mask & (TLS_TLS | TLS_LD)) == (TLS_TLS | TLS_LD))
51375136
{
51385137
if (SYMBOL_REFERENCES_LOCAL (info, &eh->elf))
@@ -5141,9 +5140,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
51415140
a local dynamic reloc against a non-local symbol. */
51425141
htab->tlsld_got.refcount += 1;
51435142
else
5144-
need += 8;
5143+
{
5144+
need += 8;
5145+
rel_need += sizeof (Elf32_External_Rela);
5146+
}
51455147
}
5146-
need += got_entries_needed (eh->tls_mask);
51475148
if (need == 0)
51485149
eh->elf.got.offset = (bfd_vma) -1;
51495150
else
@@ -5161,13 +5162,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
51615162
{
51625163
asection *rsec;
51635164

5164-
need *= sizeof (Elf32_External_Rela) / 4;
5165-
if ((eh->tls_mask & (TLS_TLS | TLS_LD)) == (TLS_TLS | TLS_LD))
5166-
need -= sizeof (Elf32_External_Rela);
51675165
rsec = htab->elf.srelgot;
51685166
if (eh->elf.type == STT_GNU_IFUNC)
51695167
rsec = htab->elf.irelplt;
5170-
rsec->size += need;
5168+
rsec->size += rel_need;
51715169
}
51725170
}
51735171
}

ld/testsuite/ld-powerpc/powerpc.exp

+1
Original file line numberDiff line numberDiff line change
@@ -522,5 +522,6 @@ run_dump_test "non-contiguous-powerpc"
522522

523523
run_dump_test "tprel32"
524524
run_dump_test "tprelbad"
525+
run_dump_test tls32ldgd
525526

526527
run_dump_test "undefweak"

ld/testsuite/ld-powerpc/tls32ldgd.d

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#as: -a32
2+
#ld: -shared -melf32ppc
3+
#readelf: -rW
4+
5+
Relocation section '\.rela\.dyn' at offset .* contains 3 entries:
6+
Offset +Info +Type +Sym\. Value +Symbol's Name \+ Addend
7+
.* +00000044 R_PPC_DTPMOD32 +0
8+
.* +0000004e R_PPC_DTPREL32 +0
9+
.* +00000044 R_PPC_DTPMOD32 +0
10+
11+
Relocation section '\.rela\.plt' at offset .* contains 1 entry:
12+
Offset +Info +Type +Sym\. Value +Symbol's Name \+ Addend
13+
.* +00000215 R_PPC_JMP_SLOT +00000000 +__tls_get_addr \+ 0

ld/testsuite/ld-powerpc/tls32ldgd.s

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#PR 30697
2+
.section ".tbss","awT",@nobits
3+
.global _start,x
4+
.hidden x
5+
.align 2
6+
x: .space 4
7+
8+
.text
9+
_start:
10+
addi 3,30,x@got@tlsgd
11+
bl __tls_get_addr(x@tlsgd)@plt
12+
13+
addi 3,30,x@got@tlsld
14+
bl __tls_get_addr(x@tlsld)@plt
15+
addis 3,3,x@dtprel@ha
16+
addi 3,3,x@dtprel@l

0 commit comments

Comments
 (0)