This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: PR ld/10426: ld incorrectly creates STT_GNU_IFUNC SHN_UNDEF symbols
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: binutils at sources dot redhat dot com
- Date: Tue, 21 Jul 2009 14:36:00 -0700
- Subject: PATCH: PR ld/10426: ld incorrectly creates STT_GNU_IFUNC SHN_UNDEF symbols
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
Hi,
For static linker, a STT_GNU_IFUNC symbol in a DSO is the same as a normal
FUNC symbol. Also, there should be no undefined STT_GNU_IFUNC symbol in
output. I am checking in this patch as an obvious fix.
Thanks.
H.J.
---
Index: ld/testsuite/ChangeLog
===================================================================
--- ld/testsuite/ChangeLog (revision 6446)
+++ ld/testsuite/ChangeLog (working copy)
@@ -1,3 +1,11 @@
+2009-07-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/10426
+ * ld-ifunc/ifunc.exp: Check test-1 and libtest-2.so. Updated.
+
+ * ld-ifunc/test-1.c: New.
+ * ld-ifunc/test-2.c: Likewise.
+
2009-07-17 Chao-ying Fu <fu@mips.com>
* ld-mips-elf/pic-and-nonpic-3b.dd: Updated to use new PLT
Index: ld/testsuite/ld-ifunc/ifunc.exp
===================================================================
--- ld/testsuite/ld-ifunc/ifunc.exp (revision 6446)
+++ ld/testsuite/ld-ifunc/ifunc.exp (working copy)
@@ -181,6 +181,14 @@ if ![ld_assemble $as "$srcdir/ld-elf/emp
fail "Could not create an empty object file"
set fails [expr $fails + 1]
}
+if ![ld_compile "$CC -c" "$srcdir/$subdir/test-1.c" "tmpdir/test-1.o"] {
+ fail "Could not create test-1.o"
+ set fails [expr $fails + 1]
+}
+if ![ld_compile "$CC -fPIC -c" "$srcdir/$subdir/test-2.c" "tmpdir/test-2.o"] {
+ fail "Could not create test-2.o"
+ set fails [expr $fails + 1]
+}
if { $fails != 0 } {
return
@@ -215,6 +223,14 @@ if ![ld_simple_link $ld "tmpdir/static_n
fail "Could not link a non-ifunc using static executable"
set fails [expr $fails + 1]
}
+if ![default_ld_link $ld "tmpdir/test-1" "tmpdir/test-1.o tmpdir/libshared_ifunc.so"] {
+ fail "Could not link test-1"
+ set fails [expr $fails + 1]
+}
+if ![ld_simple_link $ld "tmpdir/libtest-2.so" "-shared tmpdir/test-2.o"] {
+ fail "Could not link libtest-2.so"
+ set fails [expr $fails + 1]
+}
if { $fails == 0 } {
pass "Building ifunc binaries"
@@ -266,14 +282,22 @@ if {[contains_ifunc_symbol tmpdir/static
fail "Static ifunc-using executable does not contain an IFUNC symbol"
set fails [expr $fails + 1]
}
-if {[contains_ifunc_symbol tmpdir/dynamic_prog] != 1} {
- fail "Dynamic ifunc-using executable does not contain an IFUNC symbol"
+if {[contains_ifunc_symbol tmpdir/dynamic_prog] != 0} {
+ fail "Dynamic ifunc-using executable contains an IFUNC symbol"
set fails [expr $fails + 1]
}
if {[contains_ifunc_symbol tmpdir/static_nonifunc_prog] != 0} {
fail "Static non-ifunc-using executable contains an IFUNC symbol"
set fails [expr $fails + 1]
}
+if {[contains_ifunc_symbol tmpdir/test-1] != 0} {
+ fail "test-1 contains IFUNC symbols"
+ set fails [expr $fails + 1]
+}
+if {[contains_ifunc_symbol tmpdir/libtest-2.so] != 0} {
+ fail "libtest-2.so contains IFUNC symbols"
+ set fails [expr $fails + 1]
+}
# The linked ifunc using executables and shared libraries should contain
# a dynamic reloc referencing the IFUNC symbol. (Even the static
@@ -292,8 +316,8 @@ if {[contains_irelative_reloc tmpdir/sta
fail "Static ifunc-using executable does not contain R_*_IRELATIVE relocation"
set fails [expr $fails + 1]
}
-if {[contains_ifunc_reloc tmpdir/dynamic_prog] != 1} {
- fail "Dynamic ifunc-using executable does not contain a reloc against an IFUNC symbol"
+if {[contains_ifunc_reloc tmpdir/dynamic_prog] != 0} {
+ fail "Dynamic ifunc-using executable contains a reloc against an IFUNC symbol"
set fails [expr $fails + 1]
}
if {[contains_ifunc_reloc tmpdir/static_nonifunc_prog] == 1} {
Index: ld/testsuite/ld-ifunc/test-1.c
===================================================================
--- ld/testsuite/ld-ifunc/test-1.c (revision 0)
+++ ld/testsuite/ld-ifunc/test-1.c (revision 0)
@@ -0,0 +1,3 @@
+extern int library_func2 (void);
+int (*fn) (void) = library_func2;
+int main (void) { fn (); return 0; }
Index: ld/testsuite/ld-ifunc/test-2.c
===================================================================
--- ld/testsuite/ld-ifunc/test-2.c (revision 0)
+++ ld/testsuite/ld-ifunc/test-2.c (revision 0)
@@ -0,0 +1,3 @@
+extern int library_func2 (void);
+int foo (void) { library_func2 (); return 0; }
+__asm__(".type library_func2, %gnu_indirect_function");
Index: bfd/ChangeLog
===================================================================
--- bfd/ChangeLog (revision 6446)
+++ bfd/ChangeLog (working copy)
@@ -1,3 +1,11 @@
+2009-07-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/10426
+ * elflink.c (elf_link_add_object_symbols): Turn an IFUNC symbol
+ from a DSO into a normal FUNC symbol.
+ (elf_link_output_extsym): Turn an undefined IFUNC symbol into
+ a normal FUNC symbol.
+
2009-07-17 Chao-ying Fu <fu@mips.com>
* elfxx-mips.c (LOAD_INTERLOCKS_P): New define.
Index: bfd/elflink.c
===================================================================
--- bfd/elflink.c (revision 6446)
+++ bfd/elflink.c (working copy)
@@ -4279,15 +4279,24 @@ error_free_dyn:
if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
&& (definition || h->type == STT_NOTYPE))
{
- if (h->type != STT_NOTYPE
- && h->type != ELF_ST_TYPE (isym->st_info)
- && ! type_change_ok)
- (*_bfd_error_handler)
- (_("Warning: type of symbol `%s' changed"
- " from %d to %d in %B"),
- abfd, name, h->type, ELF_ST_TYPE (isym->st_info));
+ unsigned int type = ELF_ST_TYPE (isym->st_info);
+
+ /* Turn an IFUNC symbol from a DSO into a normal FUNC
+ symbol. */
+ if (type == STT_GNU_IFUNC
+ && (abfd->flags & DYNAMIC) != 0)
+ type = STT_FUNC;
- h->type = ELF_ST_TYPE (isym->st_info);
+ if (h->type != type)
+ {
+ if (h->type != STT_NOTYPE && ! type_change_ok)
+ (*_bfd_error_handler)
+ (_("Warning: type of symbol `%s' changed"
+ " from %d to %d in %B"),
+ abfd, name, h->type, type);
+
+ h->type = type;
+ }
}
/* Merge st_other field. */
@@ -8683,12 +8692,17 @@ elf_link_output_extsym (struct elf_link_
|| ELF_ST_BIND (sym.st_info) == STB_WEAK))
{
int bindtype;
+ unsigned int type = ELF_ST_TYPE (sym.st_info);
+
+ /* Turn an undefined IFUNC symbol into a normal FUNC symbol. */
+ if (type == STT_GNU_IFUNC)
+ type = STT_FUNC;
if (h->ref_regular_nonweak)
bindtype = STB_GLOBAL;
else
bindtype = STB_WEAK;
- sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
+ sym.st_info = ELF_ST_INFO (bindtype, type);
}
/* If this is a symbol defined in a dynamic library, don't use the