+2006-07-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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 <mrd@alkemio.org>
* cpu-m68k.c (bfd_m68k_compatible): Handle CPU32.
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))
+2006-07-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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 <richard@codesourcery.com>
* ld-m68k/merge-ok-1c.d: New test.
--- /dev/null
+extern void foo (void);
+
+static void (*const init_array []) (void)
+ __attribute__ ((used, section (".init_array"), aligned (sizeof (void *))))
+ = { foo };
--- /dev/null
+#include <stdio.h>
+
+void
+foo ()
+{
+ printf ("TEST1\n");
+}
--- /dev/null
+#include <stdio.h>
+
+__attribute__ ((visibility ("hidden")))
+void
+foo ()
+{
+ printf ("TEST1\n");
+}
--- /dev/null
+#include <stdio.h>
+
+__attribute__ ((visibility ("protected")))
+void
+foo ()
+{
+ printf ("TEST1\n");
+}
--- /dev/null
+#include <stdio.h>
+
+void
+foo (void)
+{
+ printf ("TEST2\n");
+}
+
+static void (*const init_array []) (void)
+ __attribute__ ((used, section (".init_array"), aligned (sizeof (void *))))
+ = { foo };
--- /dev/null
+FOO {
+ global: foo;
+ local: *;
+};
--- /dev/null
+TEST2
+TEST1
+MAIN
--- /dev/null
+#include <stdio.h>
+
+int
+main (void)
+{
+ printf ("MAIN\n");
+ return 0;
+}
--- /dev/null
+TEST1
+TEST1
+MAIN
--- /dev/null
+# 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
}
}
}
+
+# 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
+ }
+ }
+}