From 97dc35c88dd470465a99edeb0b491012a368f2bf Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 11 Aug 2015 12:58:52 -0700 Subject: [PATCH] Skip IFUNC relocations in debug sections Skip IFUNC relocations in debug sections ignored by ld.so. bfd/ PR ld/18808 * elf32-i386.c (elf_i386_relocate_section): Skip IFUNC relocations in debug sections. * elf64-x86-64.c (elf_x86_64_relocate_section): Likewise. ld/testsuite/ PR ld/18808 * ld-ifunc/ifunc.exp: Add a test for PR ld/18808. * ld-ifunc/pr18808.out: New file. * ld-ifunc/pr18808a.c: Likewise. * ld-ifunc/pr18808b.c: Likewise. --- bfd/ChangeLog | 7 +++++ bfd/elf32-i386.c | 12 +++++++-- bfd/elf64-x86-64.c | 12 +++++++-- ld/testsuite/ChangeLog | 8 ++++++ ld/testsuite/ld-ifunc/ifunc.exp | 27 +++++++++++++++++++ ld/testsuite/ld-ifunc/pr18808.out | 1 + ld/testsuite/ld-ifunc/pr18808a.c | 9 +++++++ ld/testsuite/ld-ifunc/pr18808b.c | 24 +++++++++++++++++ ld/testsuite/lib/ld-lib.exp | 45 +++++++++++++++++++++++++++++++ 9 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 ld/testsuite/ld-ifunc/pr18808.out create mode 100644 ld/testsuite/ld-ifunc/pr18808a.c create mode 100644 ld/testsuite/ld-ifunc/pr18808b.c diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f152cdcb120..7912368cb7d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2015-08-11 H.J. Lu + + PR ld/18808 + * elf32-i386.c (elf_i386_relocate_section): Skip IFUNC + relocations in debug sections. + * elf64-x86-64.c (elf_x86_64_relocate_section): Likewise. + 2015-08-11 Peter Zotov PR ld/18759 diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 92e7f72ad59..fb874215aec 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -3503,8 +3503,16 @@ elf_i386_relocate_section (bfd *output_bfd, bfd_vma plt_index; const char *name; - if ((input_section->flags & SEC_ALLOC) == 0 - || h->plt.offset == (bfd_vma) -1) + if ((input_section->flags & SEC_ALLOC) == 0) + { + /* Dynamic relocs are not propagated for SEC_DEBUGGING + sections because such sections are not SEC_ALLOC and + thus ld.so will not process them. */ + if ((input_section->flags & SEC_DEBUGGING) != 0) + break; + abort (); + } + else if (h->plt.offset == (bfd_vma) -1) abort (); /* STT_GNU_IFUNC symbol must go through PLT. */ diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index a4dfdc830cc..4b8303292ab 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -3786,8 +3786,16 @@ elf_x86_64_relocate_section (bfd *output_bfd, bfd_vma plt_index; const char *name; - if ((input_section->flags & SEC_ALLOC) == 0 - || h->plt.offset == (bfd_vma) -1) + if ((input_section->flags & SEC_ALLOC) == 0) + { + /* Dynamic relocs are not propagated for SEC_DEBUGGING + sections because such sections are not SEC_ALLOC and + thus ld.so will not process them. */ + if ((input_section->flags & SEC_DEBUGGING) != 0) + break; + abort (); + } + else if (h->plt.offset == (bfd_vma) -1) abort (); /* STT_GNU_IFUNC symbol must go through PLT. */ diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index ea873d99ce3..f719db730c1 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-08-11 H.J. Lu + + PR ld/18808 + * ld-ifunc/ifunc.exp: Add a test for PR ld/18808. + * ld-ifunc/pr18808.out: New file. + * ld-ifunc/pr18808a.c: Likewise. + * ld-ifunc/pr18808b.c: Likewise. +--- 2015-08-07 H.J. Lu PR ld/18720 diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp index e08261b76f5..498cb2d2d89 100644 --- a/ld/testsuite/ld-ifunc/ifunc.exp +++ b/ld/testsuite/ld-ifunc/ifunc.exp @@ -457,3 +457,30 @@ run_ld_link_exec_tests [] [list \ "-fpic" \ ] \ ] + +# Run-time tests which require working ifunc attribute support. +if { ![check_ifunc_attribute_available] } { + return +} + +run_cc_link_tests [list \ + [list \ + "Build libpr18808.so" \ + "-shared" \ + "-fPIC -O2 -g" \ + { pr18808b.c } \ + {} \ + "libpr18808.so" \ + ] \ +] + +run_ld_link_exec_tests [] [list \ + [list \ + "Run pr18808" \ + "tmpdir/libpr18808.so" \ + "" \ + { pr18808a.c } \ + "pr18808" \ + "pr18808.out" \ + ] \ +] diff --git a/ld/testsuite/ld-ifunc/pr18808.out b/ld/testsuite/ld-ifunc/pr18808.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/ld/testsuite/ld-ifunc/pr18808.out @@ -0,0 +1 @@ +OK diff --git a/ld/testsuite/ld-ifunc/pr18808a.c b/ld/testsuite/ld-ifunc/pr18808a.c new file mode 100644 index 00000000000..35228aef068 --- /dev/null +++ b/ld/testsuite/ld-ifunc/pr18808a.c @@ -0,0 +1,9 @@ +#include + +void bar(void); +int main(void) +{ + bar(); + printf("OK\n"); + return 0; +} diff --git a/ld/testsuite/ld-ifunc/pr18808b.c b/ld/testsuite/ld-ifunc/pr18808b.c new file mode 100644 index 00000000000..6f0db5a6614 --- /dev/null +++ b/ld/testsuite/ld-ifunc/pr18808b.c @@ -0,0 +1,24 @@ +int foo (int x) __attribute__ ((ifunc ("resolve_foo"))); +extern void abort (void); + +static int foo_impl(int x) +{ + return x; +} + +int bar() +{ + int (*f)(int) = foo; + + if (foo (5) != 5) + abort (); + + if (f(42) != 42) + abort (); +} + + +void *resolve_foo (void) +{ + return (void *) foo_impl; +} diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp index 6904499a10d..364c6facba8 100644 --- a/ld/testsuite/lib/ld-lib.exp +++ b/ld/testsuite/lib/ld-lib.exp @@ -1960,6 +1960,51 @@ proc check_ifunc_available { } { return $ifunc_available_saved } +# Returns true if ifunc attribute works. + +proc check_ifunc_attribute_available { } { + global ifunc_attribute_available_saved + global CC + + if {![info exists ifunc_attribute_available_saved]} { + if { [which $CC] == 0 } { + set ifunc_attribute_available_saved 0 + return 0 + } + # Check if gcc supports -flto -fuse-linker-plugin + set flags "" + if [board_info [target_info name] exists cflags] { + append flags " [board_info [target_info name] cflags]" + } + if [board_info [target_info name] exists ldflags] { + append flags " [board_info [target_info name] ldflags]" + } + + set basename "tmpdir/ifunc[pid]" + set src ${basename}.c + set output ${basename}.out + set f [open $src "w"] + puts $f "extern int library_func2 (void) __attribute__ ((ifunc (\"foo\")));" + puts $f "int main (void)" + puts $f "{" + puts $f " if (library_func2 () != 2) __builtin_abort ();" + puts $f " return 0; " + puts $f "}" + puts $f "static int library_func1 (void) {return 2; }" + puts $f "void *foo (void) { return library_func1; }" + close $f + remote_download host $src + set ifunc_attribute_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"] + if { $ifunc_attribute_available_saved == 1 } { + set ifunc_attribute_available_saved [run_host_cmd_yesno "$output" ""] + } + remote_file host delete $src + remote_file host delete $output + file delete $src + } + return $ifunc_attribute_available_saved +} + # Provide virtual target "cfi" for targets supporting CFI. rename "istarget" "istarget_ld" -- 2.30.2