From 2955ec4c12dbffa517fe1d821e7c5d1f7dde5f8a Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 21 Jul 2009 21:37:26 +0000 Subject: [PATCH] bfd/ 2009-07-21 H.J. Lu 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. ld/testsuite/ 2009-07-21 H.J. Lu 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. --- bfd/ChangeLog | 8 ++++++++ bfd/elflink.c | 32 +++++++++++++++++++++++--------- ld/testsuite/ChangeLog | 8 ++++++++ ld/testsuite/ld-ifunc/ifunc.exp | 32 ++++++++++++++++++++++++++++---- ld/testsuite/ld-ifunc/test-1.c | 3 +++ ld/testsuite/ld-ifunc/test-2.c | 3 +++ 6 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 ld/testsuite/ld-ifunc/test-1.c create mode 100644 ld/testsuite/ld-ifunc/test-2.c diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c8f1d85a75c..926e5d99baa 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2009-07-21 H.J. Lu + + 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 * elfxx-mips.c (LOAD_INTERLOCKS_P): New define. diff --git a/bfd/elflink.c b/bfd/elflink.c index 4d54adddb48..f9b577c7738 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -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_hash_entry *h, void *data) || 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 diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 2ef2e2aebb1..e1333f2690a 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2009-07-21 H.J. Lu + + 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 * ld-mips-elf/pic-and-nonpic-3b.dd: Updated to use new PLT diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp index 6824d04a5b1..786b32b2a45 100644 --- a/ld/testsuite/ld-ifunc/ifunc.exp +++ b/ld/testsuite/ld-ifunc/ifunc.exp @@ -181,6 +181,14 @@ if ![ld_assemble $as "$srcdir/ld-elf/empty.s" "tmpdir/empty.o"] { 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_nonifunc_prog" "-static tmpdir/empty.o"] 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_prog] != 1} { 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/static_prog] != 1} { 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} { diff --git a/ld/testsuite/ld-ifunc/test-1.c b/ld/testsuite/ld-ifunc/test-1.c new file mode 100644 index 00000000000..6930e56d27a --- /dev/null +++ b/ld/testsuite/ld-ifunc/test-1.c @@ -0,0 +1,3 @@ +extern int library_func2 (void); +int (*fn) (void) = library_func2; +int main (void) { fn (); return 0; } diff --git a/ld/testsuite/ld-ifunc/test-2.c b/ld/testsuite/ld-ifunc/test-2.c new file mode 100644 index 00000000000..8343d0c139f --- /dev/null +++ b/ld/testsuite/ld-ifunc/test-2.c @@ -0,0 +1,3 @@ +extern int library_func2 (void); +int foo (void) { library_func2 (); return 0; } +__asm__(".type library_func2, %gnu_indirect_function"); -- 2.30.2