From d2dee3b25cafc19da767092a02deb52335e47591 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 12 Jul 2006 15:45:33 +0000 Subject: [PATCH] bfd/ 2006-07-12 H.J. Lu PR ld/2884 * elflink.c (_bfd_elf_merge_symbol): Copy the symbol info from the old versioned dynamic definition to the new one with non-default visibility. Hide the symbol if it is hidden or internal. ld/testsuite/ 2006-07-12 H.J. Lu PR ld/2884 * ld-elf/begin.c: New file. * ld-elf/end.c: Likewise. * ld-elf/endhidden.c: Likewise. * ld-elf/endprotected.c: Likewise. * ld-elf/foo.c: Likewise. * ld-elf/foo.map: Likewise. * ld-elf/hidden.out: Likewise. * ld-elf/main.c: Likewise. * ld-elf/normal.out: Likewise. * ld-elf/shared.exp: Likewise. * lib/ld-lib.exp (run_cc_link_tests): New. --- bfd/ChangeLog | 8 +++ bfd/elflink.c | 36 ++++++++++- ld/testsuite/ChangeLog | 16 +++++ ld/testsuite/ld-elf/begin.c | 5 ++ ld/testsuite/ld-elf/end.c | 7 +++ ld/testsuite/ld-elf/endhidden.c | 8 +++ ld/testsuite/ld-elf/endprotected.c | 8 +++ ld/testsuite/ld-elf/foo.c | 11 ++++ ld/testsuite/ld-elf/foo.map | 4 ++ ld/testsuite/ld-elf/hidden.out | 3 + ld/testsuite/ld-elf/main.c | 8 +++ ld/testsuite/ld-elf/normal.out | 3 + ld/testsuite/ld-elf/shared.exp | 112 ++++++++++++++++++++++++++++++++++ ld/testsuite/lib/ld-lib.exp | 120 +++++++++++++++++++++++++++++++++++++ 14 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 ld/testsuite/ld-elf/begin.c create mode 100644 ld/testsuite/ld-elf/end.c create mode 100644 ld/testsuite/ld-elf/endhidden.c create mode 100644 ld/testsuite/ld-elf/endprotected.c create mode 100644 ld/testsuite/ld-elf/foo.c create mode 100644 ld/testsuite/ld-elf/foo.map create mode 100644 ld/testsuite/ld-elf/hidden.out create mode 100644 ld/testsuite/ld-elf/main.c create mode 100644 ld/testsuite/ld-elf/normal.out create mode 100644 ld/testsuite/ld-elf/shared.exp diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e9a5dba..411f704 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2006-07-12 H.J. Lu + + PR ld/2884 + * elflink.c (_bfd_elf_merge_symbol): Copy the symbol info from + the old versioned dynamic definition to the new one with + non-default visibility. Hide the symbol if it is hidden or + internal. + 2006-07-12 Matthew R. Dempsky * cpu-m68k.c (bfd_m68k_compatible): Handle CPU32. diff --git a/bfd/elflink.c b/bfd/elflink.c index 9d65b5f..84d9d1f 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1025,7 +1025,41 @@ _bfd_elf_merge_symbol (bfd *abfd, relocatable file and the old definition comes from a dynamic object, we remove the old definition. */ if ((*sym_hash)->root.type == bfd_link_hash_indirect) - h = *sym_hash; + { + /* Handle the case where the old dynamic definition is + default versioned. We need to copy the symbol info from + the symbol with default version to the normal one if it + was referenced before. */ + if (h->ref_regular) + { + const struct elf_backend_data *bed + = get_elf_backend_data (abfd); + struct elf_link_hash_entry *vh = *sym_hash; + vh->root.type = h->root.type; + h->root.type = bfd_link_hash_indirect; + (*bed->elf_backend_copy_indirect_symbol) (info, vh, h); + /* Protected symbols will override the dynamic definition + with default version. */ + if (ELF_ST_VISIBILITY (sym->st_other) == STV_PROTECTED) + { + h->root.u.i.link = (struct bfd_link_hash_entry *) vh; + vh->dynamic_def = 1; + vh->ref_dynamic = 1; + } + else + { + h->root.type = vh->root.type; + vh->ref_dynamic = 0; + /* We have to hide it here since it was made dynamic + global with extra bits when the symbol info was + copied from the old dynamic definition. */ + (*bed->elf_backend_hide_symbol) (info, vh, TRUE); + } + h = vh; + } + else + h = *sym_hash; + } if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root) && bfd_is_und_section (sec)) diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 575da33..eb5535e 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2006-07-12 H.J. Lu + + PR ld/2884 + * ld-elf/begin.c: New file. + * ld-elf/end.c: Likewise. + * ld-elf/endhidden.c: Likewise. + * ld-elf/endprotected.c: Likewise. + * ld-elf/foo.c: Likewise. + * ld-elf/foo.map: Likewise. + * ld-elf/hidden.out: Likewise. + * ld-elf/main.c: Likewise. + * ld-elf/normal.out: Likewise. + * ld-elf/shared.exp: Likewise. + + * lib/ld-lib.exp (run_cc_link_tests): New. + 2006-07-12 Richard Sandiford * ld-m68k/merge-ok-1c.d: New test. diff --git a/ld/testsuite/ld-elf/begin.c b/ld/testsuite/ld-elf/begin.c new file mode 100644 index 0000000..ccc47d4 --- /dev/null +++ b/ld/testsuite/ld-elf/begin.c @@ -0,0 +1,5 @@ +extern void foo (void); + +static void (*const init_array []) (void) + __attribute__ ((used, section (".init_array"), aligned (sizeof (void *)))) + = { foo }; diff --git a/ld/testsuite/ld-elf/end.c b/ld/testsuite/ld-elf/end.c new file mode 100644 index 0000000..f7b681a --- /dev/null +++ b/ld/testsuite/ld-elf/end.c @@ -0,0 +1,7 @@ +#include + +void +foo () +{ + printf ("TEST1\n"); +} diff --git a/ld/testsuite/ld-elf/endhidden.c b/ld/testsuite/ld-elf/endhidden.c new file mode 100644 index 0000000..2cab97a --- /dev/null +++ b/ld/testsuite/ld-elf/endhidden.c @@ -0,0 +1,8 @@ +#include + +__attribute__ ((visibility ("hidden"))) +void +foo () +{ + printf ("TEST1\n"); +} diff --git a/ld/testsuite/ld-elf/endprotected.c b/ld/testsuite/ld-elf/endprotected.c new file mode 100644 index 0000000..b6b39ea --- /dev/null +++ b/ld/testsuite/ld-elf/endprotected.c @@ -0,0 +1,8 @@ +#include + +__attribute__ ((visibility ("protected"))) +void +foo () +{ + printf ("TEST1\n"); +} diff --git a/ld/testsuite/ld-elf/foo.c b/ld/testsuite/ld-elf/foo.c new file mode 100644 index 0000000..c84baee --- /dev/null +++ b/ld/testsuite/ld-elf/foo.c @@ -0,0 +1,11 @@ +#include + +void +foo (void) +{ + printf ("TEST2\n"); +} + +static void (*const init_array []) (void) + __attribute__ ((used, section (".init_array"), aligned (sizeof (void *)))) + = { foo }; diff --git a/ld/testsuite/ld-elf/foo.map b/ld/testsuite/ld-elf/foo.map new file mode 100644 index 0000000..6b993de --- /dev/null +++ b/ld/testsuite/ld-elf/foo.map @@ -0,0 +1,4 @@ +FOO { + global: foo; + local: *; +}; diff --git a/ld/testsuite/ld-elf/hidden.out b/ld/testsuite/ld-elf/hidden.out new file mode 100644 index 0000000..7ad7cbe --- /dev/null +++ b/ld/testsuite/ld-elf/hidden.out @@ -0,0 +1,3 @@ +TEST2 +TEST1 +MAIN diff --git a/ld/testsuite/ld-elf/main.c b/ld/testsuite/ld-elf/main.c new file mode 100644 index 0000000..24f9dcc --- /dev/null +++ b/ld/testsuite/ld-elf/main.c @@ -0,0 +1,8 @@ +#include + +int +main (void) +{ + printf ("MAIN\n"); + return 0; +} diff --git a/ld/testsuite/ld-elf/normal.out b/ld/testsuite/ld-elf/normal.out new file mode 100644 index 0000000..3b721f0 --- /dev/null +++ b/ld/testsuite/ld-elf/normal.out @@ -0,0 +1,3 @@ +TEST1 +TEST1 +MAIN diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp new file mode 100644 index 0000000..9222358 --- /dev/null +++ b/ld/testsuite/ld-elf/shared.exp @@ -0,0 +1,112 @@ +# Expect script for various ELF tests. +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. +# + +# Exclude non-ELF targets. + +if ![is_elf_format] { + return +} + +# The following tests require running the executable generated by ld. +if ![isnative] { + return +} + +# Check if compiler works +if { [which $CC] == 0 } { + return +} + +set build_tests { + {"Build libfoo.so" + "-shared" "-fPIC" + {foo.c} {} "libfoo.so"} + {"Build versioned libfoo.so" + "-shared -Wl,--version-script=foo.map" "-fPIC" + {foo.c} {} "libfoov.so" "-fPIC"} + {"Build libbar.so" + "-shared" "-fPIC" + {begin.c end.c} {} "libbar.so"} + {"Build hidden libbar.so" + "-shared" "-fPIC" + {begin.c endhidden.c} {} "libbarh.so"} + {"Build protected libbar.so" + "-shared" "-fPIC" + {begin.c endprotected.c} {} "libbarp.so"} + {"Build libbar.so with libfoo.so" + "-shared tmpdir/begin.o tmpdir/libfoo.so" "-fPIC" + {end.c} {} "libbarfoo.so"} + {"Build libar.so with versioned libfoo.so" + "-shared tmpdir/begin.o tmpdir/libfoov.so" "-fPIC" + {end.c} {} "libbarfoov.so"} + {"Build hidden libbar.so with libfoo.so" + "-shared tmpdir/begin.o tmpdir/libfoo.so" "-fPIC" + {endhidden.c} {} "libbarhfoo.so"} + {"Build hidden libar.so with versioned libfoo.so" + "-shared tmpdir/begin.o tmpdir/libfoov.so" "-fPIC" + {endhidden.c} {} "libbarhfoov.so"} + {"Build protected libbar.so with libfoo.so" + "-shared tmpdir/begin.o tmpdir/libfoo.so" "-fPIC" + {endprotected.c} {} "libbarpfoo.so"} + {"Build protected libbar.so with versioned libfoo.so" + "-shared tmpdir/begin.o tmpdir/libfoov.so" "-fPIC" + {endprotected.c} {} "libbarpfoov.so"} +} + +set run_tests { + {"Run normal with libfoo.so" + "tmpdir/begin.o tmpdir/libfoo.so tmpdir/end.o" "" + {main.c} "normal" "normal.out"} + {"Run protected with libfoo.so" + "tmpdir/begin.o tmpdir/libfoo.so tmpdir/endprotected.o" "" + {main.c} "protected" "normal.out"} + {"Run hidden with libfoo.so" + "tmpdir/begin.o tmpdir/libfoo.so tmpdir/endhidden.o" "" + {main.c} "hidden" "hidden.out"} + {"Run normal with versioned libfoo.so" + "tmpdir/begin.o tmpdir/libfoov.so tmpdir/end.o" "" + {main.c} "normalv" "normal.out"} + {"Run protected with versioned libfoo.so" + "tmpdir/begin.o tmpdir/libfoov.so tmpdir/endprotected.o" "" + {main.c} "protected" "normal.out"} + {"Run hidden with versioned libfoo.so" + "tmpdir/begin.o tmpdir/libfoov.so tmpdir/endhidden.o" "" + {main.c} "hiddenv" "hidden.out"} + {"Run normal libbar.so with libfoo.so" + "tmpdir/libbarfoo.so tmpdir/libfoo.so" "" + {main.c} "normal" "normal.out"} + {"Run protected libbar.so with libfoo.so" + "tmpdir/libbarpfoo.so tmpdir/libfoo.so" "" + {main.c} "protected" "normal.out"} + {"Run hidden libbar.so with libfoo.so" + "tmpdir/libbarhfoo.so tmpdir/libfoo.so" "" + {main.c} "hidden" "hidden.out"} + {"Run normal libbar.so with versioned libfoo.so" + "tmpdir/libbarfoov.so tmpdir/libfoov.so" "" + {main.c} "normal" "normal.out"} + {"Run protected libbar.so with versioned libfoo.so" + "tmpdir/libbarpfoov.so tmpdir/libfoov.so" "" + {main.c} "protected" "normal.out"} + {"Run hidden libbar.so with versioned libfoo.so" + "tmpdir/libbarhfoov.so tmpdir/libfoov.so" "" + {main.c} "hidden" "hidden.out"} +} + +run_cc_link_tests $build_tests +# NetBSD ELF systems do not currently support the .*_array sections. +run_ld_link_exec_tests [list "*-*-netbsdelf*"] $run_tests diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp index a0e734e..4b69428 100644 --- a/ld/testsuite/lib/ld-lib.exp +++ b/ld/testsuite/lib/ld-lib.exp @@ -1341,3 +1341,123 @@ proc run_ld_link_exec_tests { targets_to_xfail ldtests } { } } } + +# List contains test-items with 3 items followed by 2 lists, one item and +# one optional item: +# 0:name 1:link options 2:compile options +# 3:filenames of assembler files 4: action and options. 5: name of output file +# +# Actions: +# objdump: Apply objdump options on result. Compare with regex (last arg). +# nm: Apply nm options on result. Compare with regex (last arg). +# readelf: Apply readelf options on result. Compare with regex (last arg). +# +proc run_cc_link_tests { ldtests } { + global nm + global objdump + global READELF + global srcdir + global subdir + global env + global CC + global CFLAGS + + foreach testitem $ldtests { + set testname [lindex $testitem 0] + set ldflags [lindex $testitem 1] + set cflags [lindex $testitem 2] + set src_files [lindex $testitem 3] + set actions [lindex $testitem 4] + set binfile tmpdir/[lindex $testitem 5] + set objfiles {} + set is_unresolved 0 + set failed 0 + + # Compile each file in the test. + foreach src_file $src_files { + set objfile "tmpdir/[file rootname $src_file].o" + lappend objfiles $objfile + + # We ignore warnings since some compilers may generate + # incorrect section attributes and the assembler will warn + # them. + ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile + } + + # Clear error and warning counts. + reset_vars + + if ![ld_simple_link $CC $binfile "-L$srcdir/$subdir $ldflags $objfiles"] { + fail $testname + } else { + set failed 0 + foreach actionlist $actions { + set action [lindex $actionlist 0] + set progopts [lindex $actionlist 1] + + # There are actions where we run regexp_diff on the + # output, and there are other actions (presumably). + # Handling of the former look the same. + set dump_prog "" + switch -- $action { + objdump + { set dump_prog $objdump } + nm + { set dump_prog $nm } + readelf + { set dump_prog $READELF } + default + { + perror "Unrecognized action $action" + set is_unresolved 1 + break + } + } + + if { $dump_prog != "" } { + set dumpfile [lindex $actionlist 2] + set binary $dump_prog + + # Ensure consistent sorting of symbols + if {[info exists env(LC_ALL)]} { + set old_lc_all $env(LC_ALL) + } + set env(LC_ALL) "C" + set cmd "$binary $progopts $binfile > dump.out" + send_log "$cmd\n" + catch "exec $cmd" comp_output + if {[info exists old_lc_all]} { + set env(LC_ALL) $old_lc_all + } else { + unset env(LC_ALL) + } + set comp_output [prune_warnings $comp_output] + + if ![string match "" $comp_output] then { + send_log "$comp_output\n" + set failed 1 + break + } + + if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then { + verbose "output is [file_contents "dump.out"]" 2 + set failed 1 + break + } + } + } + + if { $failed != 0 } { + fail $testname + } else { if { $is_unresolved == 0 } { + pass $testname + } } + } + + # Catch action errors. + if { $is_unresolved != 0 } { + unresolved $testname + continue + } + } +} -- 2.7.4