* 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

@ -1,3 +1,13 @@
2005-05-17 Nick Clifton <nickc@redhat.com>
* 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.
2005-05-15 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.am (AM_MAKEINFOFLAGS): Define.

View file

@ -675,12 +675,40 @@ information about the link, including the following:
@itemize @bullet
@item
Where object files and symbols are mapped into memory.
Where object files are mapped into memory.
@item
How common symbols are allocated.
@item
All archive members included in the link, with a mention of the symbol
which caused the archive member to be brought in.
@item
The values assigned to symbols.
Note - symbols whose values are computed by an expression which
involves a reference to a previous value of the same symbol may not
have correct result displayed in the link map. This is because the
linker discards intermediate results and only retains the final value
of an expression. Under such circumstances the linker will display
the final value enclosed by square brackets. Thus for example a
linker script containing:
@smallexample
foo = 1
foo = foo * 4
foo = foo + 8
@end smallexample
will produce the following output in the link map if the @option{-M}
option is used:
@smallexample
0x00000001 foo = 0x1
[0x0000000c] foo = (foo * 0x4)
[0x0000000c] foo = (foo + 0x8)
@end smallexample
See @ref{Expressions} for more information about expressions in linker
scripts.
@end itemize
@kindex -n

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
{