This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] ELF: Don't check DT_NEEDED for linker script defined symbols
On Mon, Nov 27, 2017 at 07:12:59AM +1030, Alan Modra wrote:
> We already process some assignments in open_input_bfds to have
> --defsym symbols defined early, so (3) shouldn't be too hard.
I'm testing the following.
bfd/
* 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/
* ldexp.c (struct definedness_hash_entry): Delete by_script.
(definedness_newfunc): Adjust to suit.
(update_definedness): Test ldscript_def rather than by_script.
(is_sym_value): Likewise.
(fold_name <DEFINED>): Test ldscript_def.
(exp_fold_tree_1): Set script symbol values in early pass.
* ldlang.c (open_input_bfds): Process all assignments, not just
defsym.
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 99f867d..e0ed135 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/ldexp.c b/ld/ldexp.c
index 83d9f8f..dddb76d 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -63,9 +63,6 @@ struct definedness_hash_entry
/* 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;
@@ -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
@@ -713,7 +708,8 @@ fold_name (etree_type *tree)
&& (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
+ && (!h->ldscript_def
+ || (def = symbol_defined (tree->name.name)) == NULL
|| def->by_object
|| def->iteration == (lang_statement_iteration & 1)));
}
@@ -950,12 +946,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)
&& (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);
@@ -1173,11 +1169,10 @@ exp_fold_tree_1 (etree_type *tree)
converted to absolute values, as is required by many
expressions, until final section sizing is complete. */
if ((expld.result.valid_p
+ || (expld.phase <= lang_mark_phase_enum
+ && tree->type.node_class == etree_assign))
&& (expld.phase == lang_final_phase_enum
|| expld.assign_name != NULL))
- || (expld.phase <= lang_mark_phase_enum
- && tree->type.node_class == etree_assign
- && tree->assign.defsym))
{
if (h == NULL)
{
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 674004e..5e96dd4 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:
--
Alan Modra
Australia Development Lab, IBM