Skip to content

Commit

Permalink
PR30697, ppc32 mix of local-dynamic and global-dynamic TLS
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
amodra committed Aug 4, 2023
1 parent 99d0971 commit 391fd4d
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 9 deletions.
16 changes: 7 additions & 9 deletions bfd/elf32-ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
Expand All @@ -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;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions ld/testsuite/ld-powerpc/powerpc.exp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
13 changes: 13 additions & 0 deletions ld/testsuite/ld-powerpc/tls32ldgd.d
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions ld/testsuite/ld-powerpc/tls32ldgd.s
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 391fd4d

Please sign in to comment.