* 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:
parent
c3357c6410
commit
3b83e13a45
3 changed files with 119 additions and 9 deletions
10
ld/ChangeLog
10
ld/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue