summaryrefslogtreecommitdiff
path: root/ld/ldexp.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2012-12-17 00:16:47 +0000
committerAlan Modra <amodra@bigpond.net.au>2012-12-17 00:16:47 +0000
commitf32ceb79186bcdce4ebec1d23f93a07a4aab6757 (patch)
treea31da0f0dda6e571ed226d607bc988a8c23bb700 /ld/ldexp.c
parent096928d1633f9604751d0b6ae0cfc9d3474cbe41 (diff)
downloadbinutils-redhat-f32ceb79186bcdce4ebec1d23f93a07a4aab6757.tar.gz
PR ld/14962
* ldexp.h (struct ldexp_control): Add "assign_name". * ldexp.c (fold_name <NAME>): Compare and clear assign_name on match. (exp_fold_tree_1): Remove existing code testing for self assignment. Instead set and test expld.assign_name. * ldlang.c (scan_for_self_assignment): Delete. (print_assignment): Instead set and test expld.assign_name.
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r--ld/ldexp.c37
1 files changed, 17 insertions, 20 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index cc43b7225c..5f4e9747e2 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -572,6 +572,9 @@ fold_name (etree_type *tree)
break;
case NAME:
+ if (expld.assign_name != NULL
+ && strcmp (expld.assign_name, tree->name.name) == 0)
+ expld.assign_name = NULL;
if (expld.phase == lang_first_phase_enum)
;
else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
@@ -852,8 +855,6 @@ exp_fold_tree_1 (etree_type *tree)
}
else
{
- etree_type *name;
-
struct bfd_link_hash_entry *h = NULL;
if (tree->type.node_class == etree_provide)
@@ -871,25 +872,20 @@ exp_fold_tree_1 (etree_type *tree)
}
}
- name = tree->assign.src;
- if (name->type.node_class == etree_trinary)
- {
- exp_fold_tree_1 (name->trinary.cond);
- if (expld.result.valid_p)
- name = (expld.result.value
- ? name->trinary.lhs : name->trinary.rhs);
- }
-
- if (name->type.node_class == etree_name
- && name->type.node_code == NAME
- && strcmp (tree->assign.dst, name->name.name) == 0)
- /* Leave it alone. Do not replace a symbol with its own
- output address, in case there is another section sizing
- pass. Folding does not preserve input sections. */
- break;
-
+ expld.assign_name = tree->assign.dst;
exp_fold_tree_1 (tree->assign.src);
- if (expld.result.valid_p
+ /* expld.assign_name remaining equal to tree->assign.dst
+ below indicates the evaluation of tree->assign.src did
+ not use the value of tree->assign.dst. We don't allow
+ self assignment until the final phase for two reasons:
+ 1) Expressions are evaluated multiple times. With
+ relaxation, the number of times may vary.
+ 2) Section relative symbol values cannot be correctly
+ converted to absolute values, as is required by many
+ expressions, until final section sizing is complete. */
+ if ((expld.result.valid_p
+ && (expld.phase == lang_final_phase_enum
+ || expld.assign_name != NULL))
|| (expld.phase <= lang_mark_phase_enum
&& tree->type.node_class == etree_assign
&& tree->assign.defsym))
@@ -937,6 +933,7 @@ exp_fold_tree_1 (etree_type *tree)
&& h->type == bfd_link_hash_new)
h->type = bfd_link_hash_undefined;
}
+ expld.assign_name = NULL;
}
break;