From: H.J. Lu Date: Mon, 29 Aug 2016 15:12:59 +0000 (-0700) Subject: i386: Issue an error on non-PIC call to IFUNC in PIC object X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=74437ea28fb611d4c88077b486fd7c0a8b4c2a25;p=binutils-gdb.git i386: Issue an error on non-PIC call to IFUNC in PIC object 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ef771a932da..68a23d11d51 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2016-08-29 H.J. Lu + + 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 PR 20520 diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 417957214db..17f86e8eb8a 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -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 { diff --git a/ld/ChangeLog b/ld/ChangeLog index b38a7e36b0a..69e018c5dea 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,24 @@ +2016-08-29 H.J. Lu + + 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 * emultempl/armelf.em (params): New static variable. diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 2ba0f054d9c..aedec41dfe0 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -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 index 00000000000..f3f5fecfc4d --- /dev/null +++ b/ld/testsuite/ld-i386/pr20515.d @@ -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 index 00000000000..eb86cbc4a51 --- /dev/null +++ b/ld/testsuite/ld-i386/pr20515.s @@ -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 diff --git a/ld/testsuite/ld-ifunc/ifunc-14a.s b/ld/testsuite/ld-ifunc/ifunc-14a.s index 9f2060441cd..87bc0ef07ad 100644 --- a/ld/testsuite/ld-ifunc/ifunc-14a.s +++ b/ld/testsuite/ld-ifunc/ifunc-14a.s @@ -2,6 +2,6 @@ .globl bar .type bar, @function bar: - jmp foo + jmp foo@PLT .size bar, .-bar .hidden foo diff --git a/ld/testsuite/ld-ifunc/ifunc-14c.s b/ld/testsuite/ld-ifunc/ifunc-14c.s index 3cde56e89ae..1a714cb9ad5 100644 --- a/ld/testsuite/ld-ifunc/ifunc-14c.s +++ b/ld/testsuite/ld-ifunc/ifunc-14c.s @@ -2,6 +2,6 @@ .globl xxx .type xxx, @function xxx: - jmp foo + jmp foo@PLT .size xxx, .-xxx .hidden foo diff --git a/ld/testsuite/ld-ifunc/ifunc-2-i386.s b/ld/testsuite/ld-ifunc/ifunc-2-i386.s index 32d8812c800..e84d6b7b5cc 100644 --- a/ld/testsuite/ld-ifunc/ifunc-2-i386.s +++ b/ld/testsuite/ld-ifunc/ifunc-2-i386.s @@ -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 diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-i386.s b/ld/testsuite/ld-ifunc/ifunc-2-local-i386.s index 4e0b6aefe76..a69e060ddc0 100644 --- a/ld/testsuite/ld-ifunc/ifunc-2-local-i386.s +++ b/ld/testsuite/ld-ifunc/ifunc-2-local-i386.s @@ -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 diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp index c3c9379cc48..504007ae700 100644 --- a/ld/testsuite/ld-ifunc/ifunc.exp +++ b/ld/testsuite/ld-ifunc/ifunc.exp @@ -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 index c922cb97146..00000000000 --- a/ld/testsuite/ld-ifunc/pr19784a.c +++ /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 index 8ea7ce2c869..00000000000 --- a/ld/testsuite/ld-ifunc/pr19784b.c +++ /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 index 117dfec1202..00000000000 --- a/ld/testsuite/ld-ifunc/pr19784c.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -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 index 00000000000..c922cb97146 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19784a.c @@ -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 index 00000000000..8ea7ce2c869 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19784b.c @@ -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 index 00000000000..117dfec1202 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19784c.c @@ -0,0 +1,11 @@ +#include + +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/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 5fa4c9f2da9..01b6a491fab 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -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*"] \