aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2023-08-04 15:09:53 +0930
committerAlan Modra <amodra@gmail.com>2023-08-04 17:59:01 +0930
commitae33771224660dac25e64c3f70943a17bfab7681 (patch)
treed48602b894890c97fb00c756b3962aaf8f480ab0 /bfd
parent49459ed32b71aefd0443d82c939f05933505080e (diff)
downloadgdb-ae33771224660dac25e64c3f70943a17bfab7681.zip
gdb-ae33771224660dac25e64c3f70943a17bfab7681.tar.gz
gdb-ae33771224660dac25e64c3f70943a17bfab7681.tar.bz2
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/elf32-ppc.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 2c544b1..37bfbcf 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -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;
}
}
}