mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-30 12:44:10 +08:00
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.
This commit is contained in:
parent
49459ed32b
commit
ae33771224
@ -5126,13 +5126,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))
|
||||
@ -5141,9 +5140,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
|
||||
@ -5161,13 +5162,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
ld/testsuite/ld-powerpc/tls32ldgd.d
Normal file
13
ld/testsuite/ld-powerpc/tls32ldgd.d
Normal file
@ -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
ld/testsuite/ld-powerpc/tls32ldgd.s
Normal file
16
ld/testsuite/ld-powerpc/tls32ldgd.s
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user