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:
Alan Modra 2017-11-27 13:40:43 +10:30
parent cd5b2babea
commit 165f707ac8
12 changed files with 82 additions and 53 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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