]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PowerPC TLS miscounting PLT for __tls_get_addr
authorAlan Modra <amodra@gmail.com>
Mon, 7 Oct 2019 02:51:02 +0000 (13:21 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 8 Oct 2019 14:06:26 +0000 (00:36 +1030)
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)

bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf64-ppc.c

index 5e9d22b2a5c2abf2f54c1855bd24758e9123b4bf..cb126d3629878c65881b33384c90a756a5e55a2e 100644 (file)
@@ -1,6 +1,12 @@
 2019-10-09  Alan Modra  <amodra@gmail.com>
 
        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.
index 6fdc10558f9e82f2aea4dd4baa45b4fb4737247e..565a3344527b9dde4b9c604c20e2d5befa5f8f98 100644 (file)
@@ -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)
                    {
index da997c7ab5ed1cc0829168d7074ded4d8eeb309f..731f1ca657d894df02a61e35cc5e265676f0f30a 100644 (file)
@@ -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;