* 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>
|
2005-05-15 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* Makefile.am (AM_MAKEINFOFLAGS): Define.
|
* Makefile.am (AM_MAKEINFOFLAGS): Define.
|
||||||
|
|
|
@ -675,12 +675,40 @@ information about the link, including the following:
|
||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
Where object files and symbols are mapped into memory.
|
Where object files are mapped into memory.
|
||||||
@item
|
@item
|
||||||
How common symbols are allocated.
|
How common symbols are allocated.
|
||||||
@item
|
@item
|
||||||
All archive members included in the link, with a mention of the symbol
|
All archive members included in the link, with a mention of the symbol
|
||||||
which caused the archive member to be brought in.
|
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
|
@end itemize
|
||||||
|
|
||||||
@kindex -n
|
@kindex -n
|
||||||
|
|
88
ld/ldlang.c
88
ld/ldlang.c
|
@ -3133,12 +3133,63 @@ print_output_section_statement
|
||||||
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
|
static void
|
||||||
print_assignment (lang_assignment_statement_type *assignment,
|
print_assignment (lang_assignment_statement_type *assignment,
|
||||||
lang_output_section_statement_type *output_section)
|
lang_output_section_statement_type *output_section)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned int i;
|
||||||
int is_dot;
|
bfd_boolean is_dot;
|
||||||
|
bfd_boolean computation_is_valid = TRUE;
|
||||||
etree_type *tree;
|
etree_type *tree;
|
||||||
etree_value_type result;
|
etree_value_type result;
|
||||||
|
|
||||||
|
@ -3147,14 +3198,17 @@ print_assignment (lang_assignment_statement_type *assignment,
|
||||||
|
|
||||||
if (assignment->exp->type.node_class == etree_assert)
|
if (assignment->exp->type.node_class == etree_assert)
|
||||||
{
|
{
|
||||||
is_dot = 0;
|
is_dot = FALSE;
|
||||||
tree = assignment->exp->assert_s.child;
|
tree = assignment->exp->assert_s.child;
|
||||||
|
computation_is_valid = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char *dst = assignment->exp->assign.dst;
|
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;
|
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,
|
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;
|
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);
|
minfo ("0x%V", value);
|
||||||
if (is_dot)
|
if (is_dot)
|
||||||
print_dot = value;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue