bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 21 Jul 2009 21:37:26 +0000 (21:37 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 21 Jul 2009 21:37:26 +0000 (21:37 +0000)
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.

ld/testsuite/

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.

bfd/ChangeLog
bfd/elflink.c
ld/testsuite/ChangeLog
ld/testsuite/ld-ifunc/ifunc.exp
ld/testsuite/ld-ifunc/test-1.c [new file with mode: 0644]
ld/testsuite/ld-ifunc/test-2.c [new file with mode: 0644]

index c8f1d85..926e5d9 100644 (file)
@@ -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 4d54add..f9b577c 100644 (file)
@@ -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
index 2ef2e2a..e1333f2 100644 (file)
@@ -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 6824d04..786b32b 100644 (file)
@@ -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 (file)
index 0000000..6930e56
--- /dev/null
@@ -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 (file)
index 0000000..8343d0c
--- /dev/null
@@ -0,0 +1,3 @@
+extern int library_func2 (void);
+int foo (void) { library_func2 (); return 0; }
+__asm__(".type library_func2, %gnu_indirect_function");