* ldlang.c (Scan_for_self_assignment): Check an assignment tree to

see if the same value is being used on the rhs as on the lhs.
	(print_assignment): Call scan_for_self_assignment and if it
	returns true, do no display the result of the computation but
	instead just the final value of the symbol on the lhs.
* ld.texinfo: Document this behaviour and provide an example of
	when it will happen.
This commit is contained in:
Nick Clifton
2005-05-17 14:35:21 +00:00
parent c3357c6410
commit 3b83e13a45
3 changed files with 119 additions and 9 deletions

View File

@@ -3133,12 +3133,63 @@ 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)
{
int i;
int is_dot;
unsigned int i;
bfd_boolean is_dot;
bfd_boolean computation_is_valid = TRUE;
etree_type *tree;
etree_value_type result;
@@ -3147,14 +3198,17 @@ print_assignment (lang_assignment_statement_type *assignment,
if (assignment->exp->type.node_class == etree_assert)
{
is_dot = 0;
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;
is_dot = (dst[0] == '.' && dst[1] == 0);
tree = assignment->exp->assign.src;
computation_is_valid = is_dot || (scan_for_self_assignment (dst, tree) == FALSE);
}
result = exp_fold_tree (tree, output_section, lang_final_phase_enum,
@@ -3163,11 +3217,29 @@ print_assignment (lang_assignment_statement_type *assignment,
{
bfd_vma value;
value = result.value + result.section->bfd_section->vma;
if (computation_is_valid)
{
value = result.value + result.section->bfd_section->vma;
minfo ("0x%V", value);
if (is_dot)
print_dot = value;
minfo ("0x%V", value);
if (is_dot)
print_dot = value;
}
else
{
struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
FALSE, FALSE, TRUE);
if (h)
{
value = h->u.def.value + result.section->bfd_section->vma;
minfo ("[0x%V]", value);
}
else
minfo ("[unresolved]");
}
}
else
{