diff options
author | Maciej W. Rozycki <macro@imgtec.com> | 2017-03-27 12:39:07 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@imgtec.com> | 2017-04-04 23:21:44 +0100 |
commit | 80070c0d3491347f11283c5791b9dd040fedbd4f (patch) | |
tree | a1382b24857548833a7dd5bbcd8a2a16bb284603 /ld/ldlang.c | |
parent | 4c7bf4f91b7dd3ccbd12be55316fca8817059a24 (diff) | |
download | gdb-80070c0d3491347f11283c5791b9dd040fedbd4f.zip gdb-80070c0d3491347f11283c5791b9dd040fedbd4f.tar.gz gdb-80070c0d3491347f11283c5791b9dd040fedbd4f.tar.bz2 |
PR ld/21233: Avoid sweeping forced-undefined symbols in section GC
Complement commit 902e9fc76a0e ("PR ld/20828: Move symbol version
processing ahead of GC symbol sweep"), commit b531344c34b0 ("PR
ld/20828: Reorder the symbol sweep stage of section GC") and commit
81ff47b3a546 ("PR ld/20828: Fix linker script symbols wrongly forced
local with section GC"), and prevent symbols forcibly entered in the
output file with the use of the `--undefined=' or `--require-defined='
linker command line options or the EXTERN linker script command from
being swept in section garbage collection and consequently recorded in
the dynamic symbol table as local entries. This happens in certain
circumstances, where a symbol reference also exists in one of the static
input files, however only in a section which is garbage-collected and
does not make it to the output file, and the symbol is defined in a
dynamic object present in the link.
For example with the `i386-linux' target and the `pr21233.s' and
`pr21233-l.s' sources, and the `pr21233.ld' linker script included with
this change we get:
$ as -o pr21233-l.o pr21233-l.s
$ ld -shared -T pr21233.ld -o libpr21233.so pr21233-l.o
$ as -o pr21233.o pr21233.s
$ ld --gc-sections -e foo --require-defined=bar -T pr21233.ld -o pr21233 pr21233.o libpr21233.so
$ readelf --dyn-syms pr21233
Symbol table '.dynsym' contains 2 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 OBJECT LOCAL DEFAULT UND bar
$
which makes the run-time `bar' dependency of the `pr21233' executable
different from its corresponding link-time dependency, i.e. the presence
of `libpr21233.so' and its `bar' symbol is required at the link time,
however at the run time a copy of `libpr21233.so' without `bar' will do.
Similarly with `--undefined=' and EXTERN which do not actually require
the reference to the symbol requested to be satisfied with a definition
at the link time, however once the definition has been pulled at the
link time, so it should at the dynamic load time.
Additionally with the `mips-linux' target we get:
$ ld --gc-sections -e foo --require-defined=bar -T pr21233.ld -o pr21233 pr21233.o libpr21233.so
ld: BFD (GNU Binutils) 2.28.51.20170324 assertion fail .../bfd/elfxx-mips.c:3861
$
as the target is not prepared to handle such a local dynamic symbol.
With this change in effect we get:
$ readelf --dyn-syms pr21233
Symbol table '.dynsym' contains 2 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 OBJECT GLOBAL DEFAULT UND bar
$
instead, for both targets.
ld/
PR ld/21233
* ldlang.c (insert_undefined): Set `mark' for ELF symbols.
* testsuite/ld-elf/pr21233.sd: New test.
* testsuite/ld-elf/pr21233-l.sd: New test.
* testsuite/ld-elf/pr21233.ld: New test linker script.
* testsuite/ld-elf/pr21233-e.ld: New test linker script.
* testsuite/ld-elf/pr21233.s: New test source.
* testsuite/ld-elf/pr21233-l.s: New test source.
* testsuite/ld-elf/shared.exp: Run the new tests.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index 5a42659..266c099 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -3429,6 +3429,8 @@ insert_undefined (const char *name) { h->type = bfd_link_hash_undefined; h->u.undef.abfd = NULL; + if (is_elf_hash_table (link_info.hash)) + ((struct elf_link_hash_entry *) h)->mark = 1; bfd_link_add_undef (link_info.hash, h); } } |