Handle local IFUNC symbols in shared object
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 8 Mar 2016 17:42:01 +0000 (09:42 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 8 Mar 2016 17:42:16 +0000 (09:42 -0800)
Increment PLT reference count for locally defined local IFUNC symbols
in shared object since STT_GNU_IFUNC symbol must go through PLT even
if it is locally defined and undefined symbol may turn out to be a
STT_GNU_IFUNC symbol later.

bfd/

PR ld/19784
* elf32-i386.c (elf_i386_check_relocs): Increment PLT reference
count for locally defined local IFUNC symbols in shared object.
* elf64-x86-64.c (elf_x86_64_check_relocs): Likewise.

ld/

PR ld/19784
* testsuite/ld-i386/i386.exp: Remove pr19636-2e-nacl test.
* testsuite/ld-i386/pr19636-2e-nacl.d: Moved to ...
* testsuite/ld-i386/pr19636-2e.d: Here.  Remove notarget.
* testsuite/ld-ifunc/ifunc.exp: Run PR ld/19784 tests.
* testsuite/ld-ifunc/pass.out: New file.
* testsuite/ld-ifunc/pr19784a.c: Likewise.
* testsuite/ld-ifunc/pr19784b.c: Likewise.
* testsuite/ld-ifunc/pr19784c.c: Likewise.

12 files changed:
bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
ld/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pr19636-2e-nacl.d [deleted file]
ld/testsuite/ld-i386/pr19636-2e.d
ld/testsuite/ld-ifunc/ifunc.exp
ld/testsuite/ld-ifunc/pass.out [new file with mode: 0644]
ld/testsuite/ld-ifunc/pr19784a.c [new file with mode: 0644]
ld/testsuite/ld-ifunc/pr19784b.c [new file with mode: 0644]
ld/testsuite/ld-ifunc/pr19784c.c [new file with mode: 0644]

index c3b91320504a46d25223bef578a0f6538bf69ebb..e2193a59f1a0753a238aa22c6bb116aa97091609 100644 (file)
@@ -1,3 +1,10 @@
+2016-03-08  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/19784
+       * elf32-i386.c (elf_i386_check_relocs): Increment PLT reference
+       count for locally defined local IFUNC symbols in shared object.
+       * elf64-x86-64.c (elf_x86_64_check_relocs): Likewise.
+
 2016-03-08  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/19579
index ab3945de00b280275cfdc9b6e0bab0fa72db7f3c..ac3c2f467c60e6cc334f17dfa2c668a137c47e0a 100644 (file)
@@ -1808,7 +1808,15 @@ elf_i386_check_relocs (bfd *abfd,
          if (eh != NULL && (sec->flags & SEC_CODE) != 0)
            eh->has_non_got_reloc = 1;
 do_relocation:
-         if (h != NULL && bfd_link_executable (info))
+         /* STT_GNU_IFUNC symbol must go through PLT even if it is
+            locally defined and undefined symbol may turn out to be
+            a STT_GNU_IFUNC symbol later.  */
+         if (h != NULL
+             && (bfd_link_executable (info)
+                 || ((h->type == STT_GNU_IFUNC
+                      || h->root.type == bfd_link_hash_undefweak
+                      || h->root.type == bfd_link_hash_undefined)
+                     && SYMBOLIC_BIND (info, h))))
            {
              /* If this reloc is in a read-only section, we might
                 need a copy reloc.  We can't check reliably at this
index c6968501cad2d9341de185094667a7f20e0e3f6c..380376d93c16d464f2ab4bc481ff3cff40074f17 100644 (file)
@@ -1999,7 +1999,15 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 pointer:
          if (eh != NULL && (sec->flags & SEC_CODE) != 0)
            eh->has_non_got_reloc = 1;
-         if (h != NULL && bfd_link_executable (info))
+         /* STT_GNU_IFUNC symbol must go through PLT even if it is
+            locally defined and undefined symbol may turn out to be
+            a STT_GNU_IFUNC symbol later.  */
+         if (h != NULL
+             && (bfd_link_executable (info)
+                 || ((h->type == STT_GNU_IFUNC
+                      || h->root.type == bfd_link_hash_undefweak
+                      || h->root.type == bfd_link_hash_undefined)
+                     && SYMBOLIC_BIND (info, h))))
            {
              /* If this reloc is in a read-only section, we might
                 need a copy reloc.  We can't check reliably at this
index 960190ff84e7f47da9cb19ae332d72e94e3f914c..73f67b0ca3cacb0b2bfb8b65afefadfad4d23f8b 100644 (file)
@@ -1,3 +1,15 @@
+2016-03-08  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/19784
+       * testsuite/ld-i386/i386.exp: Remove pr19636-2e-nacl test.
+       * testsuite/ld-i386/pr19636-2e-nacl.d: Moved to ...
+       * testsuite/ld-i386/pr19636-2e.d: Here.  Remove notarget.
+       * testsuite/ld-ifunc/ifunc.exp: Run PR ld/19784 tests.
+       * testsuite/ld-ifunc/pass.out: New file.
+       * testsuite/ld-ifunc/pr19784a.c: Likewise.
+       * testsuite/ld-ifunc/pr19784b.c: Likewise.
+       * testsuite/ld-ifunc/pr19784c.c: Likewise.
+
 2016-03-08  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/19774
index 5b9d790cbd1eb202b155caa4097efc8a256ce3d5..a032ca734e307a42481759c9e445573e8fecb223 100644 (file)
@@ -337,7 +337,6 @@ run_dump_test "pr19636-2c-nacl"
 run_dump_test "pr19636-2d"
 run_dump_test "pr19636-2d-nacl"
 run_dump_test "pr19636-2e"
-run_dump_test "pr19636-2e-nacl"
 run_dump_test "pr19636-3a"
 run_dump_test "pr19636-3b"
 run_dump_test "pr19636-3c"
diff --git a/ld/testsuite/ld-i386/pr19636-2e-nacl.d b/ld/testsuite/ld-i386/pr19636-2e-nacl.d
deleted file mode 100644 (file)
index f791128..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#source: pr19636-2.s
-#as: --32 -mrelax-relocations=no
-#ld: -shared -Bsymbolic -m elf_i386
-#readelf : -r --wide --dyn-syms
-#target: i?86-*-nacl* x86_64-*-nacl*
-
-Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 3 entries:
- +Offset +Info +Type +Sym. Value +Symbol's Name
-[0-9a-f]+ +[0-9a-f]+ +R_386_32 +0+ +func
-[0-9a-f]+ +[0-9a-f]+ +R_386_PC32 +0+ +func
-[0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func
-
-Relocation section '\.rel\.plt' at offset [0x0-9a-f]+ contains 1 entries:
- +Offset +Info +Type +Sym. Value +Symbol's Name
-[0-9a-f]+ +[0-9a-f]+ +R_386_JUMP_SLOT +0+ +func
-
-Symbol table '\.dynsym' contains [0-9]+ entries:
- +Num: +Value +Size Type +Bind +Vis +Ndx Name
-#...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +WEAK +DEFAULT +UND +func
-#pass
index 148e3060a7f62de94a211f20dd5cbd49fedbbaef..c985242718b4ee52a9c245b2f5920fcd12c7dc2d 100644 (file)
@@ -2,7 +2,6 @@
 #as: --32 -mrelax-relocations=no
 #ld: -shared -Bsymbolic -m elf_i386
 #readelf : -r --wide --dyn-syms
-#notarget: i?86-*-nacl* x86_64-*-nacl*
 
 Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 3 entries:
  +Offset +Info +Type +Sym. Value +Symbol's Name
@@ -10,6 +9,10 @@ Relocation section '\.rel\.dyn' at offset [0x0-9a-f]+ contains 3 entries:
 [0-9a-f]+ +[0-9a-f]+ +R_386_PC32 +0+ +func
 [0-9a-f]+ +[0-9a-f]+ +R_386_GLOB_DAT +0+ +func
 
+Relocation section '\.rel\.plt' at offset [0x0-9a-f]+ contains 1 entries:
+ +Offset +Info +Type +Sym. Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_JUMP_SLOT +0+ +func
+
 Symbol table '\.dynsym' contains [0-9]+ entries:
  +Num: +Value +Size Type +Bind +Vis +Ndx Name
 #...
index 96627e7edb608aab7bf0b242683b00f20cc2c119..e860f36d87c831f2be2c9b9d5661cc4c340fc19f 100644 (file)
@@ -505,6 +505,30 @@ run_cc_link_tests [list \
        {} \
        "libpr18841c.so" \
     ] \
+    [list \
+       "Build libpr19784a.so" \
+       "-shared -Wl,-Bsymbolic-functions" \
+       "-fPIC -O2 -g" \
+       { pr19784b.c pr19784c.c } \
+       {} \
+       "libpr19784a.so" \
+    ] \
+    [list \
+       "Build libpr19784b.so" \
+       "-shared -Wl,-Bsymbolic-functions" \
+       "-fPIC -O2 -g" \
+       { pr19784c.c pr19784b.c } \
+       {} \
+       "libpr19784b.so" \
+    ] \
+    [list \
+       "Build pr19784a.o" \
+       "" \
+       "" \
+       { pr19784a.c } \
+       "" \
+       "" \
+    ] \
 ]
 
 run_ld_link_exec_tests [] [list \
@@ -532,4 +556,20 @@ run_ld_link_exec_tests [] [list \
        "pr18841c" \
        "pr18841.out" \
     ] \
+    [list \
+       "Run pr19784a" \
+       "tmpdir/pr19784a.o tmpdir/libpr19784a.so" \
+       "" \
+       { dummy.c } \
+       "pr19784a" \
+       "pass.out" \
+    ] \
+    [list \
+       "Run pr19784b" \
+       "--as-needed tmpdir/pr19784a.o tmpdir/libpr19784b.so" \
+       "" \
+       { dummy.c } \
+       "pr19784b" \
+       "pass.out" \
+    ] \
 ]
diff --git a/ld/testsuite/ld-ifunc/pass.out b/ld/testsuite/ld-ifunc/pass.out
new file mode 100644 (file)
index 0000000..7ef22e9
--- /dev/null
@@ -0,0 +1 @@
+PASS
diff --git a/ld/testsuite/ld-ifunc/pr19784a.c b/ld/testsuite/ld-ifunc/pr19784a.c
new file mode 100644 (file)
index 0000000..c922cb9
--- /dev/null
@@ -0,0 +1,6 @@
+void bar(void);
+int main(void)
+{
+  bar();
+  return 0;
+}
diff --git a/ld/testsuite/ld-ifunc/pr19784b.c b/ld/testsuite/ld-ifunc/pr19784b.c
new file mode 100644 (file)
index 0000000..8ea7ce2
--- /dev/null
@@ -0,0 +1,11 @@
+int foo (int x) __attribute__ ((ifunc ("resolve_foo")));
+
+static int foo_impl(int x)
+{
+  return x;
+}
+
+void *resolve_foo (void)
+{
+  return (void *) foo_impl;
+}
diff --git a/ld/testsuite/ld-ifunc/pr19784c.c b/ld/testsuite/ld-ifunc/pr19784c.c
new file mode 100644 (file)
index 0000000..117dfec
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+extern void abort (void);
+extern int foo (int) __attribute__ ((visibility("hidden")));
+
+int bar()
+{
+  if (foo (5) != 5)
+    abort ();
+  printf("PASS\n");
+}