diff options
author | Julian Brown <julian@codesourcery.com> | 2005-05-18 13:57:35 +0000 |
---|---|---|
committer | Julian Brown <julian@codesourcery.com> | 2005-05-18 13:57:35 +0000 |
commit | 4c506f7f04e08cbf2cdff33036c59f937c535b23 (patch) | |
tree | 2f6beb5c5e943f71a812c7176552becc7751899d | |
parent | 520c5f6ca4bc5172512e8af4425793c852f9068a (diff) | |
download | gdb-4c506f7f04e08cbf2cdff33036c59f937c535b23.zip gdb-4c506f7f04e08cbf2cdff33036c59f937c535b23.tar.gz gdb-4c506f7f04e08cbf2cdff33036c59f937c535b23.tar.bz2 |
* 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.
-rw-r--r-- | ld/ChangeLog | 12 | ||||
-rw-r--r-- | ld/ld.texinfo | 30 | ||||
-rw-r--r-- | ld/ldlang.c | 94 |
3 files changed, 127 insertions, 9 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 8e3f5cb..f9c2e63 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,15 @@ +2005-05-18 Julian Brown <julian@codesourcery.com> + + Backport from mainline: + 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-03-24 Nick Clifton <nickc@redhat.com> * po/fr.po: Updated French translation. diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 99afaf2..a8b7362 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -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 diff --git a/ld/ldlang.c b/ld/ldlang.c index c38423e..bdeddfe 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -2718,12 +2718,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; @@ -2732,14 +2783,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, @@ -2748,11 +2802,35 @@ 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; - minfo ("0x%V", value); - if (is_dot) - print_dot = value; + if (result.section) + value += result.section->bfd_section->vma; + + 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; + + if (result.section) + value += result.section->bfd_section->vma; + + minfo ("[0x%V]", value); + } + else + minfo (" "); + } } else { |