This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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]

Re: PATCH: Make STT_GNU_IFUNC symbol dynamic


On Fri, May 22, 2009 at 01:02:25PM -0700, H.J. Lu wrote:
> 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.
> 
> 


Here is the patch with a testcase. OK for trunk?

Thanks.


H.J.
---
bfd/

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.

ld/testsuite/

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

	* ld-ifunc/ifunc.exp: Run *.d.

	* ld-ifunc/ifunc-1-x86.d: New.
	* ld-ifunc/ifunc-1-x86.s: Likewise.

Index: ld/testsuite/ld-ifunc/ifunc.exp
===================================================================
--- ld/testsuite/ld-ifunc/ifunc.exp	(revision 5928)
+++ ld/testsuite/ld-ifunc/ifunc.exp	(working copy)
@@ -252,3 +252,10 @@ if { $verbose < 1 } {
     remote_file host delete "tmpdir/static_prog"
     remote_file host delete "tmpdir/static_nonifunc_prog"
 }
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+foreach t $test_list {
+    # We need to strip the ".d", but can leave the dirname.
+    verbose [file rootname $t]
+    run_dump_test [file rootname $t]
+}
Index: ld/testsuite/ld-ifunc/ifunc-1-x86.s
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-1-x86.s	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-1-x86.s	(revision 0)
@@ -0,0 +1,16 @@
+	.type foo, %gnu_indirect_function
+	.global __GI_foo
+	.hidden __GI_foo
+	.set __GI_foo, foo
+	.text
+.globl foo
+	.type	foo, @function
+foo:
+	ret
+	.size	foo, .-foo
+.globl bar
+	.type	bar, @function
+bar:
+	call	__GI_foo@PLT
+	ret
+	.size	bar, .-bar
Index: ld/testsuite/ld-ifunc/ifunc-1-x86.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-1-x86.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-1-x86.d	(revision 0)
@@ -0,0 +1,7 @@
+#ld: -shared
+#objdump: -dw
+#target: x86_64-*-* i?86-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+call[ \t0-9a-fq]+<__GI_foo@plt>
+#pass
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]