This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] S/390: ifunc: Fix function pointers to hidden ifunc symbols.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d8ee9e44cc9a986b063a6ea6c91d39217cce65a1

commit d8ee9e44cc9a986b063a6ea6c91d39217cce65a1
Author: Andreas Krebbel <krebbel@linux.vnet.ibm.com>
Date:   Fri Oct 16 21:49:43 2015 +0200

    S/390: ifunc: Fix function pointers to hidden ifunc symbols.
    
    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.

Diff:
---
 bfd/ChangeLog    |  6 ++++++
 bfd/elf32-s390.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 bfd/elf64-s390.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 86a8ce8..b7f42cd 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,11 @@
 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
 	slot allocating code for GOTOFF relocs on ifunc symbols.
 	(elf_s390_gc_sweep_hook): Decrement plt refcount for GOTOFF relocs
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index fcdade0..d154fb7 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -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
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index 588892f..2b62271 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]