aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-10-07 13:21:02 +1030
committerAlan Modra <amodra@gmail.com>2019-10-09 00:36:26 +1030
commit977424c60ef73b2a051ccb9c1c3dbfedc520b0d9 (patch)
treed7b2b6036dfe6897a35d007fcc08f03a1cb28d48
parentPowerPC section flag tidy (diff)
downloadbinutils-gdb-977424c60ef73b2a051ccb9c1c3dbfedc520b0d9.tar.gz
binutils-gdb-977424c60ef73b2a051ccb9c1c3dbfedc520b0d9.tar.bz2
binutils-gdb-977424c60ef73b2a051ccb9c1c3dbfedc520b0d9.zip
PowerPC TLS miscounting PLT for __tls_get_addr
ppc*_elf_tls_optimize decrements the PLT refcount for __tls_get_addr when a GD or LD sequence can be optimized. Without tls marker relocs this must be done when processing the argument setup relocations. With marker relocs it's better done when processing the marker reloc. But don't count them both ways. Seen as "unresolvable R_PPC_REL24 relocation against symbol `__tls_get_addr_opt'" (and other branch relocs). * elf32-ppc.c (ppc_elf_tls_optimize): Don't process R_PPC_TLSLD with non-local symbol. Don't double count __tls_get_addr calls with marker relocs. * elf64-ppc.c (ppc64_elf_tls_optimize): Likewise. (cherry picked from commit 7d04a20ae4af0f1f6e75ec642413c27de4c1e1b8)
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elf32-ppc.c12
-rw-r--r--bfd/elf64-ppc.c7
3 files changed, 18 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 5e9d22b2a5..cb126d3629 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -2,6 +2,12 @@
Apply from master
2019-10-07 Alan Modra <amodra@gmail.com>
+ * elf32-ppc.c (ppc_elf_tls_optimize): Don't process R_PPC_TLSLD
+ with non-local symbol. Don't double count __tls_get_addr calls
+ with marker relocs.
+ * elf64-ppc.c (ppc64_elf_tls_optimize): Likewise.
+
+ 2019-10-07 Alan Modra <amodra@gmail.com>
* elf32-ppc.c (nomark_tls_get_addr): Rename from has_tls_get_addr_call
throughout.
* elf64-ppc.c (nomark_tls_get_addr): Likewise.
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 6fdc10558f..565a334452 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -4530,8 +4530,11 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
else
continue;
- case R_PPC_TLSGD:
case R_PPC_TLSLD:
+ if (!is_local)
+ continue;
+ /* Fall through. */
+ case R_PPC_TLSGD:
if (rel + 1 < relend
&& is_plt_seq_reloc (ELF32_R_TYPE (rel[1].r_info)))
{
@@ -4633,7 +4636,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
!= (TLS_TLS | TLS_MARK)))
continue;
- if (expecting_tls_get_addr)
+ if (expecting_tls_get_addr == 1 + !sec->nomark_tls_get_addr)
{
struct plt_entry *ent;
bfd_vma addend = 0;
@@ -4646,10 +4649,9 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
got2, addend);
if (ent != NULL && ent->plt.refcount > 0)
ent->plt.refcount -= 1;
-
- if (expecting_tls_get_addr == 2)
- continue;
}
+ if (tls_clear == 0)
+ continue;
if (tls_set == 0)
{
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index da997c7ab5..731f1ca657 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -7880,8 +7880,11 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
}
continue;
- case R_PPC64_TLSGD:
case R_PPC64_TLSLD:
+ if (!is_local)
+ continue;
+ /* Fall through. */
+ case R_PPC64_TLSGD:
if (rel + 1 < relend
&& is_plt_seq_reloc (ELF64_R_TYPE (rel[1].r_info)))
{
@@ -8066,7 +8069,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
!= (TLS_TLS | TLS_MARK)))
continue;
- if (expecting_tls_get_addr)
+ if (expecting_tls_get_addr == 1 + !sec->nomark_tls_get_addr)
{
struct plt_entry *ent = NULL;