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>
Mon, 7 Oct 2019 02:51:02 +0000 (13:21 +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.

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

index 9f3489920b68bccee621f2c4c5a44e4a5e2cc2ab..b691d585712c5e0bf3c26c5a1fe4ea7846f36677 100644 (file)
@@ -1,3 +1,10 @@
+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
index d5c3ae9d0b78d53dc5e3239f13bfca0838a0ed0c..cb6cd114af345de227eb42cf7932942a3a119656 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 31c86b40278cbc9219ed923e9679e176438c140a..842fc40f1447b768a2db98a9664d9d7fdf55e8f8 100644 (file)
@@ -7906,8 +7906,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)))
                        {
@@ -8092,7 +8095,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;