mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 17:18:55 +00:00
* 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:
88
ld/ldlang.c
88
ld/ldlang.c
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user