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.

ld/testsuite/

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.
This commit is contained in:
H.J. Lu 2006-07-12 15:45:33 +00:00
parent fb405f8a9f
commit d2dee3b25c
14 changed files with 348 additions and 1 deletions

View File

@ -1,3 +1,11 @@
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.

View File

@ -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))

View File

@ -1,3 +1,19 @@
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.

View File

@ -0,0 +1,5 @@
extern void foo (void);
static void (*const init_array []) (void)
__attribute__ ((used, section (".init_array"), aligned (sizeof (void *))))
= { foo };

View File

@ -0,0 +1,7 @@
#include <stdio.h>
void
foo ()
{
printf ("TEST1\n");
}

View File

@ -0,0 +1,8 @@
#include <stdio.h>
__attribute__ ((visibility ("hidden")))
void
foo ()
{
printf ("TEST1\n");
}

View File

@ -0,0 +1,8 @@
#include <stdio.h>
__attribute__ ((visibility ("protected")))
void
foo ()
{
printf ("TEST1\n");
}

11
ld/testsuite/ld-elf/foo.c Normal file
View File

@ -0,0 +1,11 @@
#include <stdio.h>
void
foo (void)
{
printf ("TEST2\n");
}
static void (*const init_array []) (void)
__attribute__ ((used, section (".init_array"), aligned (sizeof (void *))))
= { foo };

View File

@ -0,0 +1,4 @@
FOO {
global: foo;
local: *;
};

View File

@ -0,0 +1,3 @@
TEST2
TEST1
MAIN

View File

@ -0,0 +1,8 @@
#include <stdio.h>
int
main (void)
{
printf ("MAIN\n");
return 0;
}

View File

@ -0,0 +1,3 @@
TEST1
TEST1
MAIN

View File

@ -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

View File

@ -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
}
}
}