]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
S/390: ifunc: Fix function pointers to hidden ifunc symbols.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 16 Oct 2015 19:49:43 +0000 (21:49 +0200)
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Thu, 22 Oct 2015 08:13:22 +0000 (10:13 +0200)
bfd/ChangeLog:
* elf32-s390.c (elf_s390_adjust_dynamic_symbol): Set the PLT
reference counters for local IFUNC calls.
* elf64-s390.c (elf_s390_adjust_dynamic_symbol): Likewise.

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

index 86a8ce818aad7442b73c43b9c5b974cff1822dda..b7f42cd6d3c22775a557d46f7f225acc287bafdc 100644 (file)
@@ -1,3 +1,9 @@
+2015-10-22  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       * elf32-s390.c (elf_s390_adjust_dynamic_symbol): Set the PLT
+       reference counters for local IFUNC calls.
+       * elf64-s390.c (elf_s390_adjust_dynamic_symbol): Likewise.
+
 2015-10-22  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * elf32-s390.c (elf_s390_check_relocs): Fallthrough to the PLT
index fcdade0461ecd14233c1bb4a48e0fe4150b75926..d154fb78aff1ed49cd77e85adf138ef2461a7d21 100644 (file)
@@ -1658,7 +1658,47 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   /* STT_GNU_IFUNC symbol must go through PLT. */
   if (s390_is_ifunc_symbol_p (h))
-    return TRUE;
+    {
+      /* All local STT_GNU_IFUNC references must be treated as local
+        calls via local PLT.  */
+      if (h->ref_regular && SYMBOL_CALLS_LOCAL (info, h))
+       {
+         bfd_size_type pc_count = 0, count = 0;
+         struct elf_dyn_relocs **pp;
+         struct elf_s390_link_hash_entry *eh;
+         struct elf_dyn_relocs *p;
+
+         eh = (struct elf_s390_link_hash_entry *) h;
+         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+           {
+             pc_count += p->pc_count;
+             p->count -= p->pc_count;
+             p->pc_count = 0;
+             count += p->count;
+             if (p->count == 0)
+               *pp = p->next;
+             else
+               pp = &p->next;
+           }
+
+         if (pc_count || count)
+           {
+             h->needs_plt = 1;
+             h->non_got_ref = 1;
+             if (h->plt.refcount <= 0)
+               h->plt.refcount = 1;
+             else
+               h->plt.refcount += 1;
+           }
+       }
+
+      if (h->plt.refcount <= 0)
+       {
+         h->plt.offset = (bfd_vma) -1;
+         h->needs_plt = 0;
+       }
+      return TRUE;
+    }
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later
index 588892fb8cf538dc3aeafd021ef0e840e3c780ea..2b6227148d276c92967eb5ee0138578808c1cf6b 100644 (file)
@@ -1592,7 +1592,47 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   /* STT_GNU_IFUNC symbol must go through PLT. */
   if (s390_is_ifunc_symbol_p (h))
-    return TRUE;
+    {
+      /* All local STT_GNU_IFUNC references must be treated as local
+        calls via local PLT.  */
+      if (h->ref_regular && SYMBOL_CALLS_LOCAL (info, h))
+       {
+         bfd_size_type pc_count = 0, count = 0;
+         struct elf_dyn_relocs **pp;
+         struct elf_s390_link_hash_entry *eh;
+         struct elf_dyn_relocs *p;
+
+         eh = (struct elf_s390_link_hash_entry *) h;
+         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+           {
+             pc_count += p->pc_count;
+             p->count -= p->pc_count;
+             p->pc_count = 0;
+             count += p->count;
+             if (p->count == 0)
+               *pp = p->next;
+             else
+               pp = &p->next;
+           }
+
+         if (pc_count || count)
+           {
+             h->needs_plt = 1;
+             h->non_got_ref = 1;
+             if (h->plt.refcount <= 0)
+               h->plt.refcount = 1;
+             else
+               h->plt.refcount += 1;
+           }
+       }
+
+      if (h->plt.refcount <= 0)
+       {
+         h->plt.offset = (bfd_vma) -1;
+         h->needs_plt = 0;
+       }
+      return TRUE;
+    }
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later