This is the mail archive of the binutils@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]

PATCH: Make STT_GNU_IFUNC symbol dynamic


Hi,

Even if a STT_GNU_IFUNC symbol is hidden, we have to make it dynamic.
Otherwise, it won't work correctly when it is called within the shared
library.


H.J.
---
2009-05-22  H.J. Lu  <hongjiu.lu@intel.com>

	* elflink.c (bfd_elf_link_record_dynamic_symbol): Make
	STT_GNU_IFUNC symbol dynamic.
	(_bfd_elf_fix_symbol_flags): Don't hide STT_GNU_IFUNC symbol.
	(elf_link_add_object_symbols): Likewise.
	(_bfd_elf_symbol_refs_local_p): Return FALSE on STT_GNU_IFUNC
	symbol.

Index: bfd/elflink.c
===================================================================
--- bfd/elflink.c	(revision 5928)
+++ bfd/elflink.c	(working copy)
@@ -417,7 +417,9 @@ bfd_elf_link_record_dynamic_symbol (stru
 	      && h->root.type != bfd_link_hash_undefweak)
 	    {
 	      h->forced_local = 1;
-	      if (!elf_hash_table (info)->is_relocatable_executable)
+	      /* STT_GNU_IFUNC symbol must go through PLT.  */
+	      if (ELF_ST_TYPE (h->type) != STT_GNU_IFUNC
+		  && !elf_hash_table (info)->is_relocatable_executable)
 		return TRUE;
 	    }
 
@@ -2507,10 +2509,11 @@ _bfd_elf_fix_symbol_flags (struct elf_li
      symbol was defined in a regular object, then it actually doesn't
      need a PLT entry.  Likewise, if the symbol has non-default
      visibility.  If the symbol has hidden or internal visibility, we
-     will force it local.  */
+     will force it local.  STT_GNU_IFUNC symbol must go through PLT.  */
   if (h->needs_plt
       && eif->info->shared
       && is_elf_hash_table (eif->info->hash)
+      && ELF_ST_TYPE (h->type) != STT_GNU_IFUNC
       && (SYMBOLIC_BIND (eif->info, h)
 	  || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
       && h->def_regular)
@@ -2845,6 +2848,10 @@ _bfd_elf_symbol_refs_local_p (struct elf
   if (h == NULL)
     return TRUE;
 
+  /* STT_GNU_IFUNC symbol must go through PLT.  */
+  if (h->type == STT_GNU_IFUNC)
+    return FALSE;
+
   /* STV_HIDDEN or STV_INTERNAL ones must be local.  */
   if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
       || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
@@ -4395,8 +4402,12 @@ elf_link_add_object_symbols (bfd *abfd, 
 	      {
 	      case STV_INTERNAL:
 	      case STV_HIDDEN:
-		(*bed->elf_backend_hide_symbol) (info, h, TRUE);
-		dynsym = FALSE;
+		/* STT_GNU_IFUNC symbol must go through PLT.  */
+		if (ELF_ST_TYPE (h->type) != STT_GNU_IFUNC)
+		  {
+		    (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+		    dynsym = FALSE;
+		  }
 		break;
 	      }
 


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