Copying symbol type in ld script assignments

There is a call to update_definedness between code that evaluates an
assignment expression value and code that transfers symbol
attributes.  When script assignment expressions contain DEFINED, that
can mean the wrong symbol type is copied.  This patch tracks symbols
read during expression evaluation, rather than examining the
expression and re-evaluating conditionals.  Not only does this
simplify the code, it also means ld can now copy symbol types in more
complex expressions.

An unfortunate side effect of copying symbol type for more complex
expressions affects mmix, which uses
 PROVIDE (Main = DEFINED (Main) ? Main : (DEFINED (_start) ? _start : _start.));
in a default script.  So now _start or _start. symbol type may be
copied, losing the function type specially set up for Main.  This can
be avoided by making bfd_copy_link_hash_symbol_type do nothing for
mmix.

bfd/
	* elf64-mmix.c (bfd_elf64_bfd_copy_link_hash_symbol_type): Define.
ld/
	* ldexp.h (struct ldexp_control): Add "assign_src".
	* ldexp.c (fold_trinary): Save and restore assign_src around
	condition evaluation.
	(fold_name <NAME>): Set expld.assign_src.
	(try_copy_symbol_type): Delete.
	(exp_fold_tree_1): Set symbol type using expld.assign_src.
This commit is contained in:
Alan Modra
2017-11-27 18:43:03 +10:30
parent a83ef4d139
commit cd5b2babea
5 changed files with 38 additions and 34 deletions

View File

@ -1,3 +1,7 @@
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> 2017-11-28 H.J. Lu <hongjiu.lu@intel.com>
PR ld/22502 PR ld/22502

View File

@ -2908,6 +2908,9 @@ mmix_elf_relax_section (bfd *abfd,
#define elf_backend_omit_section_dynsym \ #define elf_backend_omit_section_dynsym \
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define bfd_elf64_bfd_copy_link_hash_symbol_type \
_bfd_generic_copy_link_hash_symbol_type
#define bfd_elf64_bfd_is_local_label_name \ #define bfd_elf64_bfd_is_local_label_name \
mmix_elf_is_local_label_name mmix_elf_is_local_label_name

View File

@ -1,3 +1,12 @@
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.
(fold_name <NAME>): Set expld.assign_src.
(try_copy_symbol_type): Delete.
(exp_fold_tree_1): Set symbol type using expld.assign_src.
2017-11-28 H.J. Lu <hongjiu.lu@intel.com> 2017-11-28 H.J. Lu <hongjiu.lu@intel.com>
PR ld/22502 PR ld/22502

View File

@ -673,7 +673,10 @@ fold_binary (etree_type *tree)
static void static void
fold_trinary (etree_type *tree) fold_trinary (etree_type *tree)
{ {
struct bfd_link_hash_entry *save = expld.assign_src;
exp_fold_tree_1 (tree->trinary.cond); exp_fold_tree_1 (tree->trinary.cond);
expld.assign_src = save;
if (expld.result.valid_p) if (expld.result.valid_p)
exp_fold_tree_1 (expld.result.value exp_fold_tree_1 (expld.result.value
? tree->trinary.lhs ? tree->trinary.lhs
@ -790,6 +793,10 @@ fold_name (etree_type *tree)
if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail) if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
bfd_link_add_undef (link_info.hash, h); bfd_link_add_undef (link_info.hash, h);
} }
if (expld.assign_src == NULL)
expld.assign_src = h;
else
expld.assign_src = (struct bfd_link_hash_entry *) 0 - 1;
} }
break; break;
@ -1001,19 +1008,6 @@ is_align_conditional (const etree_type *tree)
return FALSE; return FALSE;
} }
/* Subroutine of exp_fold_tree_1 for copying a symbol type. */
static void
try_copy_symbol_type (struct bfd_link_hash_entry *h, etree_type *src)
{
struct bfd_link_hash_entry *hsrc;
hsrc = bfd_link_hash_lookup (link_info.hash, src->name.name,
FALSE, FALSE, TRUE);
if (hsrc != NULL)
bfd_copy_link_hash_symbol_type (link_info.output_bfd, h, hsrc);
}
static void static void
exp_fold_tree_1 (etree_type *tree) exp_fold_tree_1 (etree_type *tree)
{ {
@ -1162,6 +1156,7 @@ exp_fold_tree_1 (etree_type *tree)
} }
expld.assign_name = tree->assign.dst; expld.assign_name = tree->assign.dst;
expld.assign_src = NULL;
exp_fold_tree_1 (tree->assign.src); exp_fold_tree_1 (tree->assign.src);
/* expld.assign_name remaining equal to tree->assign.dst /* expld.assign_name remaining equal to tree->assign.dst
below indicates the evaluation of tree->assign.src did below indicates the evaluation of tree->assign.src did
@ -1209,27 +1204,15 @@ exp_fold_tree_1 (etree_type *tree)
if (tree->type.node_class == etree_provide) if (tree->type.node_class == etree_provide)
tree->type.node_class = etree_provided; tree->type.node_class = etree_provided;
/* Copy the symbol type if this is a simple assignment of /* Copy the symbol type if this is an expression only
one symbol to another. Also, handle the case of a foldable referencing a single symbol. (If the expression
ternary conditional with names on either side. */ contains ternary conditions, ignoring symbols on
if (tree->assign.src->type.node_class == etree_name) false branches.) */
try_copy_symbol_type (h, tree->assign.src); if (expld.result.valid_p
else if (tree->assign.src->type.node_class == etree_trinary) && expld.assign_src != NULL
{ && expld.assign_src != (struct bfd_link_hash_entry *) 0 - 1)
exp_fold_tree_1 (tree->assign.src->trinary.cond); bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
if (expld.result.valid_p) expld.assign_src);
{
if (expld.result.value
&& tree->assign.src->trinary.lhs->type.node_class
== etree_name)
try_copy_symbol_type (h, tree->assign.src->trinary.lhs);
if (!expld.result.value
&& tree->assign.src->trinary.rhs->type.node_class
== etree_name)
try_copy_symbol_type (h, tree->assign.src->trinary.rhs);
}
}
} }
else if (expld.phase == lang_final_phase_enum) else if (expld.phase == lang_final_phase_enum)
{ {

View File

@ -163,6 +163,11 @@ struct ldexp_control {
does the false branch of a trinary expression. */ does the false branch of a trinary expression. */
const char *assign_name; const char *assign_name;
/* If evaluating an assignment, the source if it is an expression
referencing single etree_name NAME, or a trinary expression where
the true branch references a single etree_name NAME. */
struct bfd_link_hash_entry *assign_src;
/* Working results. */ /* Working results. */
etree_value_type result; etree_value_type result;
bfd_vma dot; bfd_vma dot;