mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 20:14:06 +08:00
PR ld/14962
* ldexp.h (struct ldexp_control): Add "assign_name". * ldexp.c (fold_name <NAME>): Compare and clear assign_name on match. (exp_fold_tree_1): Remove existing code testing for self assignment. Instead set and test expld.assign_name. * ldlang.c (scan_for_self_assignment): Delete. (print_assignment): Instead set and test expld.assign_name.
This commit is contained in:
parent
faa7371af5
commit
4194268f43
10
ld/ChangeLog
10
ld/ChangeLog
@ -1,3 +1,13 @@
|
||||
2012-12-17 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR ld/14962
|
||||
* ldexp.h (struct ldexp_control): Add "assign_name".
|
||||
* ldexp.c (fold_name <NAME>): Compare and clear assign_name on match.
|
||||
(exp_fold_tree_1): Remove existing code testing for self assignment.
|
||||
Instead set and test expld.assign_name.
|
||||
* ldlang.c (scan_for_self_assignment): Delete.
|
||||
(print_assignment): Instead set and test expld.assign_name.
|
||||
|
||||
2012-12-11 Roland McGrath <mcgrathr@google.com>
|
||||
|
||||
* emulparams/elf_nacl.sh (nacl_rodata_addr): New shell function.
|
||||
|
37
ld/ldexp.c
37
ld/ldexp.c
@ -572,6 +572,9 @@ fold_name (etree_type *tree)
|
||||
break;
|
||||
|
||||
case NAME:
|
||||
if (expld.assign_name != NULL
|
||||
&& strcmp (expld.assign_name, tree->name.name) == 0)
|
||||
expld.assign_name = NULL;
|
||||
if (expld.phase == lang_first_phase_enum)
|
||||
;
|
||||
else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
|
||||
@ -852,8 +855,6 @@ exp_fold_tree_1 (etree_type *tree)
|
||||
}
|
||||
else
|
||||
{
|
||||
etree_type *name;
|
||||
|
||||
struct bfd_link_hash_entry *h = NULL;
|
||||
|
||||
if (tree->type.node_class == etree_provide)
|
||||
@ -871,25 +872,20 @@ exp_fold_tree_1 (etree_type *tree)
|
||||
}
|
||||
}
|
||||
|
||||
name = tree->assign.src;
|
||||
if (name->type.node_class == etree_trinary)
|
||||
{
|
||||
exp_fold_tree_1 (name->trinary.cond);
|
||||
if (expld.result.valid_p)
|
||||
name = (expld.result.value
|
||||
? name->trinary.lhs : name->trinary.rhs);
|
||||
}
|
||||
|
||||
if (name->type.node_class == etree_name
|
||||
&& name->type.node_code == NAME
|
||||
&& strcmp (tree->assign.dst, name->name.name) == 0)
|
||||
/* Leave it alone. Do not replace a symbol with its own
|
||||
output address, in case there is another section sizing
|
||||
pass. Folding does not preserve input sections. */
|
||||
break;
|
||||
|
||||
expld.assign_name = tree->assign.dst;
|
||||
exp_fold_tree_1 (tree->assign.src);
|
||||
if (expld.result.valid_p
|
||||
/* expld.assign_name remaining equal to tree->assign.dst
|
||||
below indicates the evaluation of tree->assign.src did
|
||||
not use the value of tree->assign.dst. We don't allow
|
||||
self assignment until the final phase for two reasons:
|
||||
1) Expressions are evaluated multiple times. With
|
||||
relaxation, the number of times may vary.
|
||||
2) Section relative symbol values cannot be correctly
|
||||
converted to absolute values, as is required by many
|
||||
expressions, until final section sizing is complete. */
|
||||
if ((expld.result.valid_p
|
||||
&& (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))
|
||||
@ -937,6 +933,7 @@ exp_fold_tree_1 (etree_type *tree)
|
||||
&& h->type == bfd_link_hash_new)
|
||||
h->type = bfd_link_hash_undefined;
|
||||
}
|
||||
expld.assign_name = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -139,6 +139,11 @@ struct ldexp_control {
|
||||
|
||||
/* Principally used for diagnostics. */
|
||||
bfd_boolean assigning_to_dot;
|
||||
/* If evaluating an assignment, the destination. Cleared if an
|
||||
etree_name NAME matches this, to signal a self-assignment.
|
||||
Note that an etree_name DEFINED does not clear this field, nor
|
||||
does the false branch of a trinary expression. */
|
||||
const char *assign_name;
|
||||
|
||||
/* Working results. */
|
||||
etree_value_type result;
|
||||
|
59
ld/ldlang.c
59
ld/ldlang.c
@ -3951,63 +3951,12 @@ print_output_section_statement
|
||||
output_section_statement);
|
||||
}
|
||||
|
||||
/* Scan for the use of the destination in the right hand side
|
||||
of an expression. In such cases we will not compute the
|
||||
correct expression, since the value of DST that is used on
|
||||
the right hand side will be its final value, not its value
|
||||
just before this expression is evaluated. */
|
||||
|
||||
static bfd_boolean
|
||||
scan_for_self_assignment (const char * dst, etree_type * rhs)
|
||||
{
|
||||
if (rhs == NULL || dst == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch (rhs->type.node_class)
|
||||
{
|
||||
case etree_binary:
|
||||
return (scan_for_self_assignment (dst, rhs->binary.lhs)
|
||||
|| scan_for_self_assignment (dst, rhs->binary.rhs));
|
||||
|
||||
case etree_trinary:
|
||||
return (scan_for_self_assignment (dst, rhs->trinary.lhs)
|
||||
|| scan_for_self_assignment (dst, rhs->trinary.rhs));
|
||||
|
||||
case etree_assign:
|
||||
case etree_provided:
|
||||
case etree_provide:
|
||||
if (strcmp (dst, rhs->assign.dst) == 0)
|
||||
return TRUE;
|
||||
return scan_for_self_assignment (dst, rhs->assign.src);
|
||||
|
||||
case etree_unary:
|
||||
return scan_for_self_assignment (dst, rhs->unary.child);
|
||||
|
||||
case etree_value:
|
||||
if (rhs->value.str)
|
||||
return strcmp (dst, rhs->value.str) == 0;
|
||||
return FALSE;
|
||||
|
||||
case etree_name:
|
||||
if (rhs->name.name)
|
||||
return strcmp (dst, rhs->name.name) == 0;
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_assignment (lang_assignment_statement_type *assignment,
|
||||
lang_output_section_statement_type *output_section)
|
||||
{
|
||||
unsigned int i;
|
||||
bfd_boolean is_dot;
|
||||
bfd_boolean computation_is_valid = TRUE;
|
||||
etree_type *tree;
|
||||
asection *osec;
|
||||
|
||||
@ -4018,15 +3967,14 @@ print_assignment (lang_assignment_statement_type *assignment,
|
||||
{
|
||||
is_dot = FALSE;
|
||||
tree = assignment->exp->assert_s.child;
|
||||
computation_is_valid = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *dst = assignment->exp->assign.dst;
|
||||
|
||||
is_dot = (dst[0] == '.' && dst[1] == 0);
|
||||
expld.assign_name = dst;
|
||||
tree = assignment->exp->assign.src;
|
||||
computation_is_valid = is_dot || !scan_for_self_assignment (dst, tree);
|
||||
}
|
||||
|
||||
osec = output_section->bfd_section;
|
||||
@ -4037,7 +3985,9 @@ print_assignment (lang_assignment_statement_type *assignment,
|
||||
{
|
||||
bfd_vma value;
|
||||
|
||||
if (computation_is_valid)
|
||||
if (assignment->exp->type.node_class == etree_assert
|
||||
|| is_dot
|
||||
|| expld.assign_name != NULL)
|
||||
{
|
||||
value = expld.result.value;
|
||||
|
||||
@ -4073,6 +4023,7 @@ print_assignment (lang_assignment_statement_type *assignment,
|
||||
minfo (" ");
|
||||
#endif
|
||||
}
|
||||
expld.assign_name = NULL;
|
||||
|
||||
minfo (" ");
|
||||
exp_print_tree (assignment->exp);
|
||||
|
Loading…
Reference in New Issue
Block a user