aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-11-27 13:40:43 +1030
committerAlan Modra <amodra@gmail.com>2017-11-28 22:57:00 +1030
commit165f707ac88916aedecc96fa518be8879704d6da (patch)
tree8ca3d6cbc5f8a0a0154ff5686e71a964a932966d
parentcd5b2babea487b0a71a14b593af98330efd8d73e (diff)
downloadgdb-165f707ac88916aedecc96fa518be8879704d6da.zip
gdb-165f707ac88916aedecc96fa518be8879704d6da.tar.gz
gdb-165f707ac88916aedecc96fa518be8879704d6da.tar.bz2
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.
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/elflink.c7
-rw-r--r--bfd/linker.c9
-rw-r--r--ld/ChangeLog22
-rw-r--r--ld/ldexp.c64
-rw-r--r--ld/ldlang.c6
-rw-r--r--ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d4
-rw-r--r--ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got2
-rw-r--r--ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d4
-rw-r--r--ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got2
-rw-r--r--ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d4
-rw-r--r--ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got2
12 files changed, 82 insertions, 53 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index dc3aa2f..c9c2407 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,14 @@
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.
2017-11-28 H.J. Lu <hongjiu.lu@intel.com>
diff --git a/bfd/elflink.c b/bfd/elflink.c
index ddd088c..fed7caa 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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;
diff --git a/bfd/linker.c b/bfd/linker.c
index a96c6ed..9c19df4 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -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:
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 058318d..2b20454 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,27 @@
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".
* ldexp.c (fold_trinary): Save and restore assign_src around
condition evaluation.
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 33ca289..1f1420b 100644
--- a/ld/ldexp.c
+++ b/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);
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 674004e..bf1b5d3 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -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)
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d b/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d
index 011df6c..17e42d0 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d
@@ -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\)
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got b/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got
index 1dbcab4..508fed2 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got
@@ -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 ............
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d b/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
index 011df6c..17e42d0 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
@@ -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\)
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got b/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
index fb50635..4a97099 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
@@ -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 .*
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d b/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
index 3828aca..fb3750a 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
@@ -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\)
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got b/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got
index 4a97099..d96375c 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got
@@ -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 .*