i386: Issue an error on non-PIC call to IFUNC in PIC object
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 29 Aug 2016 15:12:59 +0000 (08:12 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 29 Aug 2016 15:14:45 +0000 (08:14 -0700)
On i386, IFUNC function must be called via PLT.  Since PLT in PIC
object uses EBX register, R_386_PLT32 relocation must be used to
call IFUNC function even when IFUNC function is defined locally.
Linker should issue an error when R_386_PC32 relocation is used
to call IFUNC function.

Since PR ld/19784 tests doesn't use PLT relocation to local IFUNC
function, they are moved to the x86-64 test directory.

bfd/

PR ld/14961
PR ld/20515
* elf32-i386.c (elf_i386_check_relocs): Issue an error when
R_386_PC32 relocation is used to call IFUNC function in PIC
object.

ld/

PR ld/14961
PR ld/20515
* testsuite/ld-i386/i386.exp: Run pr20515.
* testsuite/ld-i386/pr20515.d: New file.
* testsuite/ld-i386/pr20515.s: Likewise.
* testsuite/ld-ifunc/ifunc-14a.s: Use R_386_PLT32 to call IFUNC
function.
* testsuite/ld-ifunc/ifunc-14c.s: Likewise.
* testsuite/ld-ifunc/ifunc-2-i386.s: Likewise.
* testsuite/ld-ifunc/ifunc-2-local-i386.s: Likewise.
* testsuite/ld-ifunc/ifunc.exp: Move PR ld/19784 tests to ...
* testsuite/ld-x86-64/x86-64.exp: Here.
* testsuite/ld-ifunc/pr19784a.c: Moved to ...
* testsuite/ld-x86-64/pr19784a.c: Here.
* testsuite/ld-ifunc/pr19784b.c: Moved to ...
* testsuite/ld-x86-64/pr19784b.c: Here.
* testsuite/ld-ifunc/pr19784c.c: Moved to ...
* testsuite/ld-x86-64/pr19784c.c: Here.

18 files changed:
bfd/ChangeLog
bfd/elf32-i386.c
ld/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pr20515.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr20515.s [new file with mode: 0644]
ld/testsuite/ld-ifunc/ifunc-14a.s
ld/testsuite/ld-ifunc/ifunc-14c.s
ld/testsuite/ld-ifunc/ifunc-2-i386.s
ld/testsuite/ld-ifunc/ifunc-2-local-i386.s
ld/testsuite/ld-ifunc/ifunc.exp
ld/testsuite/ld-ifunc/pr19784a.c [deleted file]
ld/testsuite/ld-ifunc/pr19784b.c [deleted file]
ld/testsuite/ld-ifunc/pr19784c.c [deleted file]
ld/testsuite/ld-x86-64/pr19784a.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19784b.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19784c.c [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index ef771a932daa587d1c56d3d2c121789ff4da0ccd..68a23d11d51fc93c5647a558cefb370f9ae37bcf 100644 (file)
@@ -1,3 +1,11 @@
+2016-08-29  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/14961
+       PR ld/20515
+       * elf32-i386.c (elf_i386_check_relocs): Issue an error when
+       R_386_PC32 relocation is used to call IFUNC function in PIC
+       object.
+
 2016-08-27  Alan Modra  <amodra@gmail.com>
 
        PR 20520
index 417957214dbb6257e97fe1510ebd431807a1a256..17f86e8eb8af9ac63d1514eaba4eb4c9111ced89 100644 (file)
@@ -2178,6 +2178,20 @@ do_relocation:
                     a function defined in a shared library.  */
                  if ((sec->flags & SEC_CODE) == 0)
                    h->pointer_equality_needed = 1;
+                 else if (h->type == STT_GNU_IFUNC
+                          && bfd_link_pic (info))
+                   {
+                   if (isym == NULL)
+                     name = h->root.root.string;
+                   else
+                     name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
+                                              NULL);
+                   (*_bfd_error_handler)
+                     (_("%B: unsupported non-PIC call to IFUNC `%s'"),
+                      abfd, name);
+                     bfd_set_error (bfd_error_bad_value);
+                     goto error_return;
+                   }
                }
              else
                {
index b38a7e36b0a2b7b70c000cfa58cfd9918060bc15..69e018c5dea14c7161c3685429353fea7dc4c2af 100644 (file)
@@ -1,3 +1,24 @@
+2016-08-29  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/14961
+       PR ld/20515
+       * testsuite/ld-i386/i386.exp: Run pr20515.
+       * testsuite/ld-i386/pr20515.d: New file.
+       * testsuite/ld-i386/pr20515.s: Likewise.
+       * testsuite/ld-ifunc/ifunc-14a.s: Use R_386_PLT32 to call IFUNC
+       function.
+       * testsuite/ld-ifunc/ifunc-14c.s: Likewise.
+       * testsuite/ld-ifunc/ifunc-2-i386.s: Likewise.
+       * testsuite/ld-ifunc/ifunc-2-local-i386.s: Likewise.
+       * testsuite/ld-ifunc/ifunc.exp: Move PR ld/19784 tests to ...
+       * testsuite/ld-x86-64/x86-64.exp: Here.
+       * testsuite/ld-ifunc/pr19784a.c: Moved to ...
+       * testsuite/ld-x86-64/pr19784a.c: Here.
+       * testsuite/ld-ifunc/pr19784b.c: Moved to ...
+       * testsuite/ld-x86-64/pr19784b.c: Here.
+       * testsuite/ld-ifunc/pr19784c.c: Moved to ...
+       * testsuite/ld-x86-64/pr19784c.c: Here.
+
 2016-08-26  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * emultempl/armelf.em (params): New static variable.
index 2ba0f054d9cdf16d2071ebdd5401ac33be1a2035..aedec41dfe032ec427fee69b1e9cbb52aa9e5a66 100644 (file)
@@ -413,6 +413,7 @@ run_dump_test "pr20253-4a"
 run_dump_test "pr20253-4b"
 run_dump_test "pr20253-4c"
 run_dump_test "pr20253-5"
+run_dump_test "pr20515"
 
 if { !([istarget "i?86-*-linux*"]
        || [istarget "i?86-*-gnu*"]
diff --git a/ld/testsuite/ld-i386/pr20515.d b/ld/testsuite/ld-i386/pr20515.d
new file mode 100644 (file)
index 0000000..f3f5fec
--- /dev/null
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -m elf_i386 -shared
+#error: unsupported non-PIC call to IFUNC `foo'
diff --git a/ld/testsuite/ld-i386/pr20515.s b/ld/testsuite/ld-i386/pr20515.s
new file mode 100644 (file)
index 0000000..eb86cbc
--- /dev/null
@@ -0,0 +1,12 @@
+       .text
+       .globl bar
+       .type   bar, @function
+bar:
+       jmp     foo
+       .size   bar, .-bar
+       .hidden foo
+       .type foo, %gnu_indirect_function
+       .globl foo
+foo:
+       ret
+       .size   foo, .-foo
index 9f2060441cd905413059a7f1c2d1f469dbec8619..87bc0ef07adbdef3ba12de668f1c2bc8aaad1f14 100644 (file)
@@ -2,6 +2,6 @@
        .globl bar
        .type   bar, @function
 bar:
-       jmp     foo
+       jmp     foo@PLT
        .size   bar, .-bar
        .hidden foo
index 3cde56e89ae5f8aa7e5bb29b5fbfe44d721d6a49..1a714cb9ad52bbf1a702c3b047691dc8cca96069 100644 (file)
@@ -2,6 +2,6 @@
        .globl xxx
        .type   xxx, @function
 xxx:
-       jmp     foo
+       jmp     foo@PLT
        .size   xxx, .-xxx
        .hidden foo
index 32d8812c80080845669c2293a123743e2e28722f..e84d6b7b5cc05a74d953d24e925f285c2af9f468 100644 (file)
@@ -15,7 +15,7 @@ bar:
 .L6:
        popl    %ebx
        addl    $_GLOBAL_OFFSET_TABLE_+[.-.L6], %ebx
-       call    __GI_foo
+       call    __GI_foo@PLT
        leal    __GI_foo@GOTOFF(%ebx), %eax
        ret
        .size   bar, .-bar
index 4e0b6aefe769708af46a7fbbfc9fdf1c9352d559..a69e060ddc0bad362e2cd15a65851ccba4918697 100644 (file)
@@ -12,7 +12,7 @@ bar:
 .L6:
        popl    %ebx
        addl    $_GLOBAL_OFFSET_TABLE_+[.-.L6], %ebx
-       call    __GI_foo
+       call    __GI_foo@PLT
        leal    __GI_foo@GOTOFF(%ebx), %eax
        ret
        .size   bar, .-bar
index c3c9379cc4854aee2243298ee70f981399a17fdd..504007ae700485f7420a5eb50e50a38064399014 100644 (file)
@@ -505,30 +505,6 @@ 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 \
@@ -556,20 +532,4 @@ 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/pr19784a.c b/ld/testsuite/ld-ifunc/pr19784a.c
deleted file mode 100644 (file)
index c922cb9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-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
deleted file mode 100644 (file)
index 8ea7ce2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-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
deleted file mode 100644 (file)
index 117dfec..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <stdio.h>
-
-extern void abort (void);
-extern int foo (int) __attribute__ ((visibility("hidden")));
-
-int bar()
-{
-  if (foo (5) != 5)
-    abort ();
-  printf("PASS\n");
-}
diff --git a/ld/testsuite/ld-x86-64/pr19784a.c b/ld/testsuite/ld-x86-64/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-x86-64/pr19784b.c b/ld/testsuite/ld-x86-64/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-x86-64/pr19784c.c b/ld/testsuite/ld-x86-64/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");
+}
index 5fa4c9f2da9b1d8389ae5ba181567163e823bd82..01b6a491fab59306513c38b140eeacaf50dcc93b 100644 (file)
@@ -822,6 +822,28 @@ if { [isnative] && [which $CC] != 0 } {
            {{objdump {-dw} pr19319.dd}} \
            "pr19319" \
        ] \
+       [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 \
@@ -892,6 +914,22 @@ if { [isnative] && [which $CC] != 0 } {
            "gotpcrel1" \
            "gotpcrel1.out" \
        ] \
+       [list \
+           "Run pr19784a" \
+           "tmpdir/pr19784a.o tmpdir/libpr19784a.so" \
+           "" \
+           { dummy.s } \
+           "pr19784a" \
+           "pass.out" \
+       ] \
+       [list \
+           "Run pr19784b" \
+           "--as-needed tmpdir/pr19784a.o tmpdir/libpr19784b.so" \
+           "" \
+           { dummy.s } \
+           "pr19784b" \
+           "pass.out" \
+       ] \
     ]
 
     if { [istarget "x86_64-*-linux*"] \