summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2019-01-29 11:20:02 +0000
committerNick Clifton <nickc@redhat.com>2019-01-29 11:20:02 +0000
commit12542b2a6da22f5ab2fd4043e8bded1444ed42ad (patch)
treef4e4db21d7b811ecf09b63348a597b0d9b2acd2f
parent5bbcb18fc7f83b649cca32d670a1891792fc7b79 (diff)
downloadbinutils-gdb-12542b2a6da22f5ab2fd4043e8bded1444ed42ad.tar.gz
Fix error in expression evalutation in linker output maps.
PR 24008 * ldexp.h (lang_phase_type): Add lang_fixed_phase_enum. * ldexp.c (fold_name): Move expld.assign_name check later to avoid an extra lookup. (exp_fold_tree_1): When lang_fixed_phase_enum, don't change symbol values, and don't clear expld.assign_name. * ldlang.c (lang_map): Set expld.phase to lang_fixed_phase_enum. (print_assignment): Resolve entire assignment expression. Don't access symbol u.def unless symbol is defined.
-rw-r--r--ld/ChangeLog15
-rw-r--r--ld/ldexp.c84
-rw-r--r--ld/ldexp.h4
-rw-r--r--ld/ldlang.c9
4 files changed, 69 insertions, 43 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 5d5a0a19323..52e47812f50 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,18 @@
+2019-01-29 Nick Clifton <nickc@redhat.com>
+
+ * Import from mainline:
+ 2019-01-28 Alan Modra <amodra@gmail.com>
+
+ PR 24008
+ * ldexp.h (lang_phase_type): Add lang_fixed_phase_enum.
+ * ldexp.c (fold_name): Move expld.assign_name check later to
+ avoid an extra lookup.
+ (exp_fold_tree_1): When lang_fixed_phase_enum, don't change symbol
+ values, and don't clear expld.assign_name.
+ * ldlang.c (lang_map): Set expld.phase to lang_fixed_phase_enum.
+ (print_assignment): Resolve entire assignment expression.
+ Don't access symbol u.def unless symbol is defined.
+
2019-01-29 Eric Botcazou <ebotcazou@adacore.com>
* testsuite/ld-ifunc/ifunc.exp: Skip pr23169 on SPARC.
diff --git a/ld/ldexp.c b/ld/ldexp.c
index a8b833a6bb8..60b17ef5764 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -720,23 +720,6 @@ fold_name (etree_type *tree)
break;
case NAME:
- if (expld.assign_name != NULL
- && strcmp (expld.assign_name, tree->name.name) == 0)
- {
- /* Self-assignment is only allowed for absolute symbols
- defined in a linker script. */
- h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
- &link_info,
- tree->name.name,
- FALSE, FALSE, TRUE);
- if (!(h != NULL
- && (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak)
- && h->u.def.section == bfd_abs_section_ptr
- && (def = symbol_defined (tree->name.name)) != NULL
- && def->iteration == (lang_statement_iteration & 255)))
- expld.assign_name = NULL;
- }
if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
new_rel_from_abs (expld.dot);
else
@@ -787,6 +770,18 @@ fold_name (etree_type *tree)
expld.assign_src = h;
else
expld.assign_src = (struct bfd_link_hash_entry *) - 1;
+
+ /* Self-assignment is only allowed for absolute symbols
+ defined in a linker script. */
+ if (expld.assign_name != NULL
+ && strcmp (expld.assign_name, tree->name.name) == 0
+ && !(h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ && h->u.def.section == bfd_abs_section_ptr
+ && (def = symbol_defined (tree->name.name)) != NULL
+ && def->iteration == (lang_statement_iteration & 255)))
+ expld.assign_name = NULL;
}
break;
@@ -1158,7 +1153,8 @@ exp_fold_tree_1 (etree_type *tree)
converted to absolute values, as is required by many
expressions, until final section sizing is complete. */
if (expld.phase == lang_final_phase_enum
- || expld.assign_name != NULL)
+ || expld.phase == lang_fixed_phase_enum
+ || expld.assign_name != NULL)
{
if (tree->type.node_class == etree_provide)
tree->type.node_class = etree_provided;
@@ -1199,28 +1195,40 @@ exp_fold_tree_1 (etree_type *tree)
(&link_info, h, link_info.output_bfd,
expld.result.section, expld.result.value);
}
- h->type = bfd_link_hash_defined;
- h->u.def.value = expld.result.value;
- h->u.def.section = expld.result.section;
- h->linker_def = ! tree->assign.type.lineno;
- h->ldscript_def = 1;
- h->rel_from_abs = expld.rel_from_abs;
- if (tree->assign.hidden)
- bfd_link_hide_symbol (link_info.output_bfd,
- &link_info, h);
-
- /* Copy the symbol type if this is an expression only
- referencing a single symbol. (If the expression
- contains ternary conditions, ignoring symbols on
- false branches.) */
- if (expld.assign_src != NULL
- && (expld.assign_src
- != (struct bfd_link_hash_entry *) -1))
- bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
- expld.assign_src);
+ if (expld.phase == lang_fixed_phase_enum)
+ {
+ if (h->type == bfd_link_hash_defined)
+ {
+ expld.result.value = h->u.def.value;
+ expld.result.section = h->u.def.section;
+ }
+ }
+ else
+ {
+ h->type = bfd_link_hash_defined;
+ h->u.def.value = expld.result.value;
+ h->u.def.section = expld.result.section;
+ h->linker_def = ! tree->assign.type.lineno;
+ h->ldscript_def = 1;
+ h->rel_from_abs = expld.rel_from_abs;
+ if (tree->assign.hidden)
+ bfd_link_hide_symbol (link_info.output_bfd,
+ &link_info, h);
+
+ /* Copy the symbol type if this is an expression only
+ referencing a single symbol. (If the expression
+ contains ternary conditions, ignoring symbols on
+ false branches.) */
+ if (expld.assign_src != NULL
+ && (expld.assign_src
+ != (struct bfd_link_hash_entry *) -1))
+ bfd_copy_link_hash_symbol_type (link_info.output_bfd,
+ h, expld.assign_src);
+ }
}
}
- expld.assign_name = NULL;
+ if (expld.phase != lang_fixed_phase_enum)
+ expld.assign_name = NULL;
}
break;
diff --git a/ld/ldexp.h b/ld/ldexp.h
index 8dc1bf941f3..71395bc6c46 100644
--- a/ld/ldexp.h
+++ b/ld/ldexp.h
@@ -106,7 +106,9 @@ typedef enum
/* During assignment of symbol values when relaxation in progress. */
lang_assigning_phase_enum,
/* Final assignment of symbol values. */
- lang_final_phase_enum
+ lang_final_phase_enum,
+ /* Run after symbol values have been fixed, for lang_map. */
+ lang_fixed_phase_enum
} lang_phase_type;
union lang_statement_union;
diff --git a/ld/ldlang.c b/ld/ldlang.c
index bddce6d81ac..33f6bda292a 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2315,6 +2315,7 @@ lang_map (void)
obstack_begin (&map_obstack, 1000);
bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0);
}
+ expld.phase = lang_fixed_phase_enum;
lang_statement_iteration++;
print_statements ();
@@ -4244,9 +4245,7 @@ print_assignment (lang_assignment_statement_type *assignment,
const char *dst = assignment->exp->assign.dst;
is_dot = (dst[0] == '.' && dst[1] == 0);
- if (!is_dot)
- expld.assign_name = dst;
- tree = assignment->exp->assign.src;
+ tree = assignment->exp;
}
osec = output_section->bfd_section;
@@ -4281,7 +4280,9 @@ print_assignment (lang_assignment_statement_type *assignment,
h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
FALSE, FALSE, TRUE);
- if (h)
+ if (h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak))
{
value = h->u.def.value;
value += h->u.def.section->output_section->vma;