mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-30 12:44:10 +08:00
PR22471, undefined reference to linker-defined symbols
This patch processes linker script assignment statements before ld opens DT_NEEDED libraries, in order to define symbols like __bss_start that might also be defined by a library, falsely triggering an error about "DSO missing from command line". The initial value won't be correct when assigning a symbol from dot, and I make no attempt to handle all expressions. For example, an assignment like "_start_foo = ADDR (.foo)" isn't valid until sections are laid out, so won't define _start_foo early. What's here should be enough for most common scripts, and hopefully won't perturb fragile scripts. bfd/ PR 22471 * elflink.c (_bfd_elf_merge_symbol): Allow weak symbols to override early passes over linker script symbols. * linker.c (_bfd_generic_link_add_one_symbol): Allow symbols to override early passes over linker script symbols. Clear ldscript_def on symbol definitions. ld/ PR 22471 * ldexp.c (struct definedness_hash_entry): Delete "by_script". Make "iteration" an 8-bit field, and update mask in all uses. (definedness_newfunc): Don't init "by_script". (update_definedness): Test ldscript_def rather than by_script. (is_sym_value): Likewise. (fold_name <DEFINED>): Return a result for first phase. Test ldscript_def. (fold_name <NAME>): Return a result for first phase. * ldlang.c (open_input_bfds): Process all assignments, not just defsym. (lang_process): Increment lang_statement_iteration before open_input_bfds. * testsuite/ld-mips-elf/tlsdyn-o32-1.d: Adjust for larger .dynsym. * testsuite/ld-mips-elf/tlsdyn-o32-1.got: Likewise. * testsuite/ld-mips-elf/tlsdyn-o32-2.d: Likewise. * testsuite/ld-mips-elf/tlsdyn-o32-2.got: Likewise. * testsuite/ld-mips-elf/tlsdyn-o32-3.d: Likewise. * testsuite/ld-mips-elf/tlsdyn-o32-3.got: Likewise.
This commit is contained in:
parent
cd5b2babea
commit
165f707ac8
@ -1,3 +1,12 @@
|
||||
2017-11-28 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 22471
|
||||
* elflink.c (_bfd_elf_merge_symbol): Allow weak symbols to override
|
||||
early passes over linker script symbols.
|
||||
* linker.c (_bfd_generic_link_add_one_symbol): Allow symbols to
|
||||
override early passes over linker script symbols. Clear ldscript_def
|
||||
on symbol definitions.
|
||||
|
||||
2017-11-28 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf64-mmix.c (bfd_elf64_bfd_copy_link_hash_symbol_type): Define.
|
||||
|
@ -1471,10 +1471,15 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||
treated as strong if the new symbol is from a dynamic library.
|
||||
This reflects the way glibc's ld.so works.
|
||||
|
||||
Also allow a weak symbol to override a linker script symbol
|
||||
defined by an early pass over the script. This is done so the
|
||||
linker knows the symbol is defined in an object file, for the
|
||||
DEFINED script function.
|
||||
|
||||
Do this before setting *type_change_ok or *size_change_ok so that
|
||||
we warn properly when dynamic library symbols are overridden. */
|
||||
|
||||
if (newdef && !newdyn && olddyn)
|
||||
if (newdef && !newdyn && (olddyn || h->root.ldscript_def))
|
||||
newweak = FALSE;
|
||||
if (olddef && newdyn)
|
||||
oldweak = FALSE;
|
||||
|
@ -1443,9 +1443,14 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
|
||||
do
|
||||
{
|
||||
enum link_action action;
|
||||
int prev;
|
||||
|
||||
prev = h->type;
|
||||
/* Treat symbols defined by early linker script pass as undefined. */
|
||||
if (h->ldscript_def)
|
||||
prev = bfd_link_hash_undefined;
|
||||
cycle = FALSE;
|
||||
action = link_action[(int) row][(int) h->type];
|
||||
action = link_action[(int) row][prev];
|
||||
switch (action)
|
||||
{
|
||||
case FAIL:
|
||||
@ -1489,6 +1494,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
|
||||
h->u.def.section = section;
|
||||
h->u.def.value = value;
|
||||
h->linker_def = 0;
|
||||
h->ldscript_def = 0;
|
||||
|
||||
/* If we have been asked to, we act like collect2 and
|
||||
identify all functions that might be global
|
||||
@ -1588,6 +1594,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
|
||||
else
|
||||
h->u.c.p->section = section;
|
||||
h->linker_def = 0;
|
||||
h->ldscript_def = 0;
|
||||
break;
|
||||
|
||||
case REF:
|
||||
|
22
ld/ChangeLog
22
ld/ChangeLog
@ -1,3 +1,25 @@
|
||||
2017-11-28 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 22471
|
||||
* ldexp.c (struct definedness_hash_entry): Delete "by_script". Make
|
||||
"iteration" an 8-bit field, and update mask in all uses.
|
||||
(definedness_newfunc): Don't init "by_script".
|
||||
(update_definedness): Test ldscript_def rather than by_script.
|
||||
(is_sym_value): Likewise.
|
||||
(fold_name <DEFINED>): Return a result for first phase. Test
|
||||
ldscript_def.
|
||||
(fold_name <NAME>): Return a result for first phase.
|
||||
* ldlang.c (open_input_bfds): Process all assignments, not just
|
||||
defsym.
|
||||
(lang_process): Increment lang_statement_iteration before
|
||||
open_input_bfds.
|
||||
* testsuite/ld-mips-elf/tlsdyn-o32-1.d: Adjust for larger .dynsym.
|
||||
* testsuite/ld-mips-elf/tlsdyn-o32-1.got: Likewise.
|
||||
* testsuite/ld-mips-elf/tlsdyn-o32-2.d: Likewise.
|
||||
* testsuite/ld-mips-elf/tlsdyn-o32-2.got: Likewise.
|
||||
* testsuite/ld-mips-elf/tlsdyn-o32-3.d: Likewise.
|
||||
* testsuite/ld-mips-elf/tlsdyn-o32-3.got: Likewise.
|
||||
|
||||
2017-11-28 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ldexp.h (struct ldexp_control): Add "assign_src".
|
||||
|
64
ld/ldexp.c
64
ld/ldexp.c
@ -60,15 +60,12 @@ struct definedness_hash_entry
|
||||
section statement, the section we'd like it relative to. */
|
||||
asection *final_sec;
|
||||
|
||||
/* Low bits of iteration count. Symbols with matching iteration have
|
||||
been defined in this pass over the script. */
|
||||
unsigned int iteration : 8;
|
||||
|
||||
/* Symbol was defined by an object file. */
|
||||
unsigned int by_object : 1;
|
||||
|
||||
/* Symbols was defined by a script. */
|
||||
unsigned int by_script : 1;
|
||||
|
||||
/* Low bit of iteration count. Symbols with matching iteration have
|
||||
been defined in this pass over the script. */
|
||||
unsigned int iteration : 1;
|
||||
};
|
||||
|
||||
static struct bfd_hash_table definedness_table;
|
||||
@ -286,7 +283,6 @@ definedness_newfunc (struct bfd_hash_entry *entry,
|
||||
einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name);
|
||||
|
||||
ret->by_object = 0;
|
||||
ret->by_script = 0;
|
||||
ret->iteration = 0;
|
||||
return &ret->root;
|
||||
}
|
||||
@ -320,7 +316,7 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
|
||||
/* If the symbol was already defined, and not by a script, then it
|
||||
must be defined by an object file or by the linker target code. */
|
||||
ret = TRUE;
|
||||
if (!defentry->by_script
|
||||
if (!h->ldscript_def
|
||||
&& (h->type == bfd_link_hash_defined
|
||||
|| h->type == bfd_link_hash_defweak
|
||||
|| h->type == bfd_link_hash_common))
|
||||
@ -332,7 +328,6 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
defentry->by_script = 1;
|
||||
defentry->iteration = lang_statement_iteration;
|
||||
defentry->final_sec = bfd_abs_section_ptr;
|
||||
if (expld.phase == lang_final_phase_enum
|
||||
@ -686,6 +681,9 @@ fold_trinary (etree_type *tree)
|
||||
static void
|
||||
fold_name (etree_type *tree)
|
||||
{
|
||||
struct bfd_link_hash_entry *h;
|
||||
struct definedness_hash_entry *def;
|
||||
|
||||
memset (&expld.result, 0, sizeof (expld.result));
|
||||
|
||||
switch (tree->type.node_code)
|
||||
@ -703,23 +701,18 @@ fold_name (etree_type *tree)
|
||||
break;
|
||||
|
||||
case DEFINED:
|
||||
if (expld.phase != lang_first_phase_enum)
|
||||
{
|
||||
struct bfd_link_hash_entry *h;
|
||||
struct definedness_hash_entry *def;
|
||||
|
||||
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
|
||||
&link_info,
|
||||
tree->name.name,
|
||||
FALSE, FALSE, TRUE);
|
||||
new_number (h != NULL
|
||||
&& (h->type == bfd_link_hash_defined
|
||||
|| h->type == bfd_link_hash_defweak
|
||||
|| h->type == bfd_link_hash_common)
|
||||
&& ((def = symbol_defined (tree->name.name)) == NULL
|
||||
|| def->by_object
|
||||
|| def->iteration == (lang_statement_iteration & 1)));
|
||||
}
|
||||
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
|
||||
&link_info,
|
||||
tree->name.name,
|
||||
FALSE, FALSE, TRUE);
|
||||
new_number (h != NULL
|
||||
&& (h->type == bfd_link_hash_defined
|
||||
|| h->type == bfd_link_hash_defweak
|
||||
|| h->type == bfd_link_hash_common)
|
||||
&& (!h->ldscript_def
|
||||
|| (def = symbol_defined (tree->name.name)) == NULL
|
||||
|| def->by_object
|
||||
|| def->iteration == (lang_statement_iteration & 255)));
|
||||
break;
|
||||
|
||||
case NAME:
|
||||
@ -728,9 +721,6 @@ fold_name (etree_type *tree)
|
||||
{
|
||||
/* Self-assignment is only allowed for absolute symbols
|
||||
defined in a linker script. */
|
||||
struct bfd_link_hash_entry *h;
|
||||
struct definedness_hash_entry *def;
|
||||
|
||||
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
|
||||
&link_info,
|
||||
tree->name.name,
|
||||
@ -740,17 +730,13 @@ fold_name (etree_type *tree)
|
||||
|| h->type == bfd_link_hash_defweak)
|
||||
&& h->u.def.section == bfd_abs_section_ptr
|
||||
&& (def = symbol_defined (tree->name.name)) != NULL
|
||||
&& def->iteration == (lang_statement_iteration & 1)))
|
||||
&& def->iteration == (lang_statement_iteration & 255)))
|
||||
expld.assign_name = NULL;
|
||||
}
|
||||
if (expld.phase == lang_first_phase_enum)
|
||||
;
|
||||
else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
|
||||
if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
|
||||
new_rel_from_abs (expld.dot);
|
||||
else
|
||||
{
|
||||
struct bfd_link_hash_entry *h;
|
||||
|
||||
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
|
||||
&link_info,
|
||||
tree->name.name,
|
||||
@ -765,7 +751,7 @@ fold_name (etree_type *tree)
|
||||
output_section = h->u.def.section->output_section;
|
||||
if (output_section == NULL)
|
||||
{
|
||||
if (expld.phase == lang_mark_phase_enum)
|
||||
if (expld.phase <= lang_mark_phase_enum)
|
||||
new_rel (h->u.def.value, h->u.def.section);
|
||||
else
|
||||
einfo (_("%X%S: unresolvable symbol `%s'"
|
||||
@ -957,12 +943,12 @@ is_sym_value (const etree_type *tree, bfd_vma val)
|
||||
return (tree->type.node_class == etree_name
|
||||
&& tree->type.node_code == NAME
|
||||
&& (def = symbol_defined (tree->name.name)) != NULL
|
||||
&& def->by_script
|
||||
&& def->iteration == (lang_statement_iteration & 1)
|
||||
&& def->iteration == (lang_statement_iteration & 255)
|
||||
&& (h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
|
||||
&link_info,
|
||||
tree->name.name,
|
||||
FALSE, FALSE, TRUE)) != NULL
|
||||
&& h->ldscript_def
|
||||
&& h->type == bfd_link_hash_defined
|
||||
&& h->u.def.section == bfd_abs_section_ptr
|
||||
&& h->u.def.value == val);
|
||||
|
@ -3359,9 +3359,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
|
||||
#endif
|
||||
break;
|
||||
case lang_assignment_statement_enum:
|
||||
if (s->assignment_statement.exp->type.node_class != etree_assert
|
||||
&& s->assignment_statement.exp->assign.defsym)
|
||||
/* This is from a --defsym on the command line. */
|
||||
if (s->assignment_statement.exp->type.node_class != etree_assert)
|
||||
exp_fold_tree_no_dot (s->assignment_statement.exp);
|
||||
break;
|
||||
default:
|
||||
@ -7167,6 +7165,7 @@ lang_process (void)
|
||||
|
||||
/* Create a bfd for each input file. */
|
||||
current_target = default_target;
|
||||
lang_statement_iteration++;
|
||||
open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
|
||||
|
||||
#ifdef ENABLE_PLUGINS
|
||||
@ -7222,6 +7221,7 @@ lang_process (void)
|
||||
|
||||
/* Rescan archives in case new undefined symbols have appeared. */
|
||||
files = file_chain;
|
||||
lang_statement_iteration++;
|
||||
open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
|
||||
lang_list_remove_tail (&file_chain, &files);
|
||||
while (files.head != NULL)
|
||||
|
@ -5,7 +5,7 @@ Disassembly of section .text:
|
||||
|
||||
.* <__start>:
|
||||
.*: 3c1c0fc0 lui gp,0xfc0
|
||||
.*: 279c7c30 addiu gp,gp,31792
|
||||
.*: 279c7b80 addiu gp,gp,31616
|
||||
.*: 0399e021 addu gp,gp,t9
|
||||
.*: 27bdfff0 addiu sp,sp,-16
|
||||
.*: afbe0008 sw s8,8\(sp\)
|
||||
@ -55,7 +55,7 @@ Disassembly of section .text:
|
||||
|
||||
.* <other>:
|
||||
.*: 3c1c0fc0 lui gp,0xfc0
|
||||
.*: 279c7b70 addiu gp,gp,31600
|
||||
.*: 279c7ac0 addiu gp,gp,31424
|
||||
.*: 0399e021 addu gp,gp,t9
|
||||
.*: 27bdfff0 addiu sp,sp,-16
|
||||
.*: afbe0008 sw s8,8\(sp\)
|
||||
|
@ -13,6 +13,6 @@ OFFSET TYPE VALUE
|
||||
|
||||
|
||||
Contents of section .got:
|
||||
10000020 00000000 80000000 0040048c 00000000 .........@......
|
||||
10000020 00000000 80000000 0040053c 00000000 .........@......
|
||||
10000030 00000000 00000000 00000000 00000000 ................
|
||||
10000040 00000000 00000001 00000000 ............
|
||||
|
@ -5,7 +5,7 @@ Disassembly of section .text:
|
||||
|
||||
.* <__start>:
|
||||
.*: 3c1c0fc0 lui gp,0xfc0
|
||||
.*: 279c7c30 addiu gp,gp,31792
|
||||
.*: 279c7b80 addiu gp,gp,31616
|
||||
.*: 0399e021 addu gp,gp,t9
|
||||
.*: 27bdfff0 addiu sp,sp,-16
|
||||
.*: afbe0008 sw s8,8\(sp\)
|
||||
@ -55,7 +55,7 @@ Disassembly of section .text:
|
||||
|
||||
.* <other>:
|
||||
.*: 3c1c0fc0 lui gp,0xfc0
|
||||
.*: 279c7b70 addiu gp,gp,31600
|
||||
.*: 279c7ac0 addiu gp,gp,31424
|
||||
.*: 0399e021 addu gp,gp,t9
|
||||
.*: 27bdfff0 addiu sp,sp,-16
|
||||
.*: afbe0008 sw s8,8\(sp\)
|
||||
|
@ -13,6 +13,6 @@ OFFSET TYPE VALUE
|
||||
|
||||
|
||||
Contents of section .got:
|
||||
10000020 00000000 80000000 0040048c 00000000 .*
|
||||
10000020 00000000 80000000 0040053c 00000000 .*
|
||||
10000030 00000000 00000000 00000000 00000000 .*
|
||||
10000040 00000000 00000001 00000000 .*
|
||||
|
@ -5,7 +5,7 @@ Disassembly of section .text:
|
||||
|
||||
.* <other>:
|
||||
.*: 3c1c0fc0 lui gp,0xfc0
|
||||
.*: 279c7c30 addiu gp,gp,31792
|
||||
.*: 279c7b80 addiu gp,gp,31616
|
||||
.*: 0399e021 addu gp,gp,t9
|
||||
.*: 27bdfff0 addiu sp,sp,-16
|
||||
.*: afbe0008 sw s8,8\(sp\)
|
||||
@ -51,7 +51,7 @@ Disassembly of section .text:
|
||||
|
||||
.* <__start>:
|
||||
.*: 3c1c0fc0 lui gp,0xfc0
|
||||
.*: 279c7b80 addiu gp,gp,31616
|
||||
.*: 279c7ad0 addiu gp,gp,31440
|
||||
.*: 0399e021 addu gp,gp,t9
|
||||
.*: 27bdfff0 addiu sp,sp,-16
|
||||
.*: afbe0008 sw s8,8\(sp\)
|
||||
|
@ -13,6 +13,6 @@ OFFSET TYPE VALUE
|
||||
|
||||
|
||||
Contents of section .got:
|
||||
10000020 00000000 80000000 0040053c 00000000 .*
|
||||
10000020 00000000 80000000 004005ec 00000000 .*
|
||||
10000030 00000000 00000000 00000000 00000000 .*
|
||||
10000040 00000000 00000001 00000000 .*
|
||||
|
Loading…
Reference in New Issue
Block a user