mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
Undo dynamic symbol state after regular object sym type mismatch
We already handle the case of an object file first defining a symbol that a later shared library also defines where the symbol types are incompatible. This patch handles the reverse, when a later object file defines an incompatible symbol defined by an earlier shared library. bfd/ * elflink.c (_bfd_elf_merge_symbol): Undo dynamic linking state when a regular object file defines a symbol with incompatible type to that defined by an earlier shared lib. ld/ * testsuite/ld-elf/indirect5a.c, * testsuite/ld-elf/indirect5b.c, * testsuite/ld-elf/indirect5.map, * testsuite/ld-elf/indirect5.out: New test. * testsuite/ld-elf/indirect6a.c: Likewise. * testsuite/ld-elf/indirect.exp (check_dynamic_syms): New proc. Run new tests and check dynsyms.
This commit is contained in:
parent
c661778cb6
commit
c5d37467b1
@ -1,3 +1,9 @@
|
||||
2017-04-17 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elflink.c (_bfd_elf_merge_symbol): Undo dynamic linking
|
||||
state when a regular object file defines a symbol with
|
||||
incompatible type to that defined by an earlier shared lib.
|
||||
|
||||
2017-04-13 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* coffcode.h: Wrap some overly long _bfd_error_handler args.
|
||||
|
@ -1242,23 +1242,50 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||
oldfunc = (h->type != STT_NOTYPE
|
||||
&& bed->is_function_type (h->type));
|
||||
|
||||
/* If creating a default indirect symbol ("foo" or "foo@") from a
|
||||
dynamic versioned definition ("foo@@") skip doing so if there is
|
||||
an existing regular definition with a different type. We don't
|
||||
want, for example, a "time" variable in the executable overriding
|
||||
a "time" function in a shared library. */
|
||||
if (pold_alignment == NULL
|
||||
&& newdyn
|
||||
&& newdef
|
||||
&& !olddyn
|
||||
&& (olddef || h->root.type == bfd_link_hash_common)
|
||||
if (!(newfunc && oldfunc)
|
||||
&& ELF_ST_TYPE (sym->st_info) != h->type
|
||||
&& ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
|
||||
&& h->type != STT_NOTYPE
|
||||
&& !(newfunc && oldfunc))
|
||||
&& (newdef || bfd_is_com_section (sec))
|
||||
&& (olddef || h->root.type == bfd_link_hash_common))
|
||||
{
|
||||
*skip = TRUE;
|
||||
return TRUE;
|
||||
/* If creating a default indirect symbol ("foo" or "foo@") from
|
||||
a dynamic versioned definition ("foo@@") skip doing so if
|
||||
there is an existing regular definition with a different
|
||||
type. We don't want, for example, a "time" variable in the
|
||||
executable overriding a "time" function in a shared library. */
|
||||
if (newdyn
|
||||
&& !olddyn)
|
||||
{
|
||||
*skip = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* When adding a symbol from a regular object file after we have
|
||||
created indirect symbols, undo the indirection and any
|
||||
dynamic state. */
|
||||
if (hi != h
|
||||
&& !newdyn
|
||||
&& olddyn)
|
||||
{
|
||||
h = hi;
|
||||
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
|
||||
h->forced_local = 0;
|
||||
h->ref_dynamic = 0;
|
||||
h->def_dynamic = 0;
|
||||
h->dynamic_def = 0;
|
||||
if (h->root.u.undef.next || info->hash->undefs_tail == &h->root)
|
||||
{
|
||||
h->root.type = bfd_link_hash_undefined;
|
||||
h->root.u.undef.abfd = abfd;
|
||||
}
|
||||
else
|
||||
{
|
||||
h->root.type = bfd_link_hash_new;
|
||||
h->root.u.undef.abfd = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check TLS symbols. We don't check undefined symbols introduced
|
||||
|
10
ld/ChangeLog
10
ld/ChangeLog
@ -1,3 +1,13 @@
|
||||
2017-04-17 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* testsuite/ld-elf/indirect5a.c,
|
||||
* testsuite/ld-elf/indirect5b.c,
|
||||
* testsuite/ld-elf/indirect5.map,
|
||||
* testsuite/ld-elf/indirect5.out: New test.
|
||||
* testsuite/ld-elf/indirect6a.c: Likewise.
|
||||
* testsuite/ld-elf/indirect.exp (check_dynamic_syms): New proc.
|
||||
Run new tests and check dynsyms.
|
||||
|
||||
2017-04-11 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 21274
|
||||
|
@ -85,6 +85,9 @@ set build_tests {
|
||||
{"Build libindirect4c.so"
|
||||
"-shared" "-fPIC"
|
||||
{indirect4c.c} {} "libindirect4c.so"}
|
||||
{"Build libindirect5.so"
|
||||
"-shared -Wl,--version-script=indirect5.map" "-fPIC"
|
||||
{indirect5b.c} {} "libindirect5.so"}
|
||||
{"Build libpr18720c.so"
|
||||
"-shared" "-fPIC"
|
||||
{pr18720c.c} {} "libpr18720c.so"}
|
||||
@ -151,6 +154,18 @@ set run_tests {
|
||||
{"Run with libindirect4c.so 4"
|
||||
"-Wl,--no-as-needed tmpdir/libindirect4c.so tmpdir/indirect4b.o tmpdir/indirect4a.o" ""
|
||||
{dummy.c} "indirect4d" "indirect4.out"}
|
||||
{"Run indirect5 1"
|
||||
"-Wl,--no-as-needed tmpdir/libindirect5.so" ""
|
||||
{indirect5a.c} "indirect5a" "indirect5.out"}
|
||||
{"Run indirect5 2"
|
||||
"-Wl,--no-as-needed tmpdir/indirect5a.o tmpdir/libindirect5.so" ""
|
||||
{dummy.c} "indirect5b" "indirect5.out"}
|
||||
{"Run indirect6 1"
|
||||
"-Wl,--no-as-needed tmpdir/libindirect5.so" ""
|
||||
{indirect6a.c} "indirect6a" "indirect5.out"}
|
||||
{"Run indirect6 2"
|
||||
"-Wl,--no-as-needed tmpdir/indirect6a.o tmpdir/libindirect5.so" ""
|
||||
{dummy.c} "indirect6b" "indirect5.out"}
|
||||
{"Run with libpr18720c.so 1"
|
||||
"-Wl,--no-as-needed tmpdir/pr18720a.o tmpdir/pr18720b.o tmpdir/libpr18720c.so" ""
|
||||
{check-ptr-eq.c} "pr18720a" "pr18720.out"}
|
||||
@ -178,3 +193,62 @@ set run_tests {
|
||||
}
|
||||
|
||||
run_ld_link_exec_tests $run_tests
|
||||
|
||||
# Check that "bar" is not dynamic in the executable
|
||||
proc check_dynamic_syms { test } {
|
||||
global nm
|
||||
set cmd "$nm -D $test > dump.out"
|
||||
send_log "$cmd\n"
|
||||
catch "exec $cmd" comp_output
|
||||
if ![string match "" $comp_output] then {
|
||||
send_log "$comp_output\n"
|
||||
return 0
|
||||
}
|
||||
if { [string match "* bar\n*" [file_contents "dump.out"]] } then {
|
||||
verbose "output is [file_contents "dump.out"]"
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
foreach t [list indirect5a indirect5b indirect6a indirect6b] {
|
||||
set testname [concat $t "dynsym"]
|
||||
if { [check_dynamic_syms tmpdir/$t] } {
|
||||
pass $testname
|
||||
} else {
|
||||
fail $testname
|
||||
}
|
||||
}
|
||||
|
||||
send_log "$CC -fPIE -pie $srcdir/$subdir/main.c -o tmpdir/pie"
|
||||
catch "exec $CC -fPIE -pie $srcdir/$subdir/main.c -o tmpdir/pie" exec_output
|
||||
send_log "$exec_output"
|
||||
if { ! [string match "" $exec_output] } {
|
||||
return
|
||||
}
|
||||
|
||||
set pie_tests {
|
||||
{"Run indirect5 3"
|
||||
"-pie -Wl,--no-as-needed tmpdir/libindirect5.so" ""
|
||||
{indirect5a.c} "indirect5c" "indirect5.out" "-fPIE"}
|
||||
{"Run indirect5 4"
|
||||
"-pie -Wl,--no-as-needed tmpdir/indirect5a.o tmpdir/libindirect5.so" ""
|
||||
{dummy.c} "indirect5d" "indirect5.out" "-fPIE"}
|
||||
{"Run indirect6 3"
|
||||
"-pie -Wl,--no-as-needed tmpdir/libindirect5.so" ""
|
||||
{indirect6a.c} "indirect6c" "indirect5.out" "-fPIE"}
|
||||
{"Run indirect6 4"
|
||||
"-pie -Wl,--no-as-needed tmpdir/indirect6a.o tmpdir/libindirect5.so" "-fPIE"
|
||||
{dummy.c} "indirect6d" "indirect5.out" "-fPIE"}
|
||||
}
|
||||
|
||||
run_ld_link_exec_tests $pie_tests
|
||||
|
||||
foreach t [list indirect5c indirect5d indirect6c indirect6d] {
|
||||
set testname [concat $t "dynsym"]
|
||||
if { [check_dynamic_syms tmpdir/$t] } {
|
||||
pass $testname
|
||||
} else {
|
||||
fail $testname
|
||||
}
|
||||
}
|
||||
|
6
ld/testsuite/ld-elf/indirect5.map
Normal file
6
ld/testsuite/ld-elf/indirect5.map
Normal file
@ -0,0 +1,6 @@
|
||||
FOO
|
||||
{
|
||||
global:
|
||||
foo;
|
||||
bar;
|
||||
};
|
2
ld/testsuite/ld-elf/indirect5.out
Normal file
2
ld/testsuite/ld-elf/indirect5.out
Normal file
@ -0,0 +1,2 @@
|
||||
foo
|
||||
bar
|
9
ld/testsuite/ld-elf/indirect5a.c
Normal file
9
ld/testsuite/ld-elf/indirect5a.c
Normal file
@ -0,0 +1,9 @@
|
||||
extern void foo (long *);
|
||||
long bar;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
foo (&bar);
|
||||
return 0;
|
||||
}
|
15
ld/testsuite/ld-elf/indirect5b.c
Normal file
15
ld/testsuite/ld-elf/indirect5b.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
printf ("bar\n");
|
||||
}
|
||||
|
||||
void
|
||||
foo (long *x)
|
||||
{
|
||||
(void) x;
|
||||
printf ("foo\n");
|
||||
bar ();
|
||||
}
|
9
ld/testsuite/ld-elf/indirect6a.c
Normal file
9
ld/testsuite/ld-elf/indirect6a.c
Normal file
@ -0,0 +1,9 @@
|
||||
extern void foo (long *);
|
||||
long bar = 1;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
foo (&bar);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user