aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2017-05-18 20:31:52 -0300
committerAlexandre Oliva <aoliva@redhat.com>2017-05-18 20:31:52 -0300
commit17ae5ed8b9f453404f41598a7d4cfcb23f028e7b (patch)
tree9049f443aa27ad3ffff3b1e87f5f362897e4c34b
parent2d2a3a89f67843a7dbefca43f8f61e5c4ac2edbd (diff)
downloadgdb-17ae5ed8b9f453404f41598a7d4cfcb23f028e7b.zip
gdb-17ae5ed8b9f453404f41598a7d4cfcb23f028e7b.tar.gz
gdb-17ae5ed8b9f453404f41598a7d4cfcb23f028e7b.tar.bz2
LVU: defer reset-view checks that depend on late-resolved addresses
-rw-r--r--gas/dwarf2dbg.c68
-rw-r--r--gas/dwarf2dbg.h2
-rw-r--r--gas/write.c2
3 files changed, 68 insertions, 4 deletions
diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c
index 29346c9..5f49e38 100644
--- a/gas/dwarf2dbg.c
+++ b/gas/dwarf2dbg.c
@@ -227,6 +227,10 @@ static struct dwarf2_line_info current = {
lists. */
static symbolS *force_reset_view;
+/* This symbol evaluates to an expression that, if nonzero, indicates
+ some view assert check failed. */
+static symbolS *view_assert_failed;
+
/* The size of an address on the target. */
static unsigned int sizeof_address;
@@ -349,15 +353,36 @@ set_or_check_view (struct line_entry *e, struct line_entry *p,
}
}
- if (S_IS_DEFINED (e->loc.view) && symbol_constant_p (e->loc.view)
- && viewx.X_op == O_constant)
+ if (S_IS_DEFINED (e->loc.view) && symbol_constant_p (e->loc.view))
{
expressionS *value = symbol_get_value_expression (e->loc.view);
/* We can't compare the view numbers at this point, because in
VIEWX we've only determined whether we're to reset it so
far. */
- if (!value->X_add_number != !viewx.X_add_number)
- as_bad (_("view number mismatch"));
+ if (viewx.X_op == O_constant)
+ {
+ if (!value->X_add_number != !viewx.X_add_number)
+ as_bad (_("view number mismatch"));
+ }
+ /* Record the expression to check it later. It is the result of
+ a logical not, thus 0 or 1. We just add up all such deferred
+ expressions, and resolve it at the end. */
+ else if (!value->X_add_number)
+ {
+ symbolS *deferred = make_expr_symbol (&viewx);
+ if (view_assert_failed)
+ {
+ expressionS chk;
+ memset (&chk, 0, sizeof (chk));
+ chk.X_unsigned = 1;
+ chk.X_op = O_add;
+ chk.X_add_number = 0;
+ chk.X_add_symbol = view_assert_failed;
+ chk.X_op_symbol = deferred;
+ deferred = make_expr_symbol (&chk);
+ }
+ view_assert_failed = deferred;
+ }
}
if (viewx.X_op != O_constant || viewx.X_add_number)
@@ -2156,3 +2181,38 @@ dwarf2_finish (void)
out_debug_info (info_seg, abbrev_seg, line_seg, ranges_seg);
}
}
+
+/* Perform any deferred checks pertaining to debug information. */
+
+void
+dwarf2dbg_final_check (void)
+{
+ /* Perform reset-view checks. Don't evaluate view_assert_failed
+ recursively: it could be very deep. It's a chain of adds, with
+ each chain element pointing to the next in X_add_symbol, and
+ holding the check value in X_op_symbol. */
+ while (view_assert_failed)
+ {
+ gas_assert (!symbol_resolved_p (view_assert_failed));
+
+ expressionS *expr = symbol_get_value_expression (view_assert_failed);
+ symbolS *sym = view_assert_failed;
+
+ /* If view_assert_failed looks like a compound check in the
+ chain, break it up. */
+ if (expr->X_op == O_add && expr->X_add_number == 0 && expr->X_unsigned)
+ {
+ view_assert_failed = expr->X_add_symbol;
+ sym = expr->X_op_symbol;
+ }
+ else
+ view_assert_failed = NULL;
+
+ offsetT failed = resolve_symbol_value (sym);
+ if (!symbol_resolved_p (sym) || failed)
+ {
+ as_bad (_("view number mismatch"));
+ break;
+ }
+ }
+}
diff --git a/gas/dwarf2dbg.h b/gas/dwarf2dbg.h
index 7b5fcd1..49826fd 100644
--- a/gas/dwarf2dbg.h
+++ b/gas/dwarf2dbg.h
@@ -100,6 +100,8 @@ extern int dwarf2dbg_estimate_size_before_relax (fragS *);
extern int dwarf2dbg_relax_frag (fragS *);
extern void dwarf2dbg_convert_frag (fragS *);
+extern void dwarf2dbg_final_check (void);
+
/* An enumeration which describes the sizes of offsets (to DWARF sections)
and the mechanism by which the size is indicated. */
enum dwarf2_format {
diff --git a/gas/write.c b/gas/write.c
index dd9e4af..09f6f0b 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -1902,6 +1902,8 @@ write_object_file (void)
/* Relaxation has completed. Freeze all syms. */
finalize_syms = 1;
+ dwarf2dbg_final_check ();
+
#ifdef md_post_relax_hook
md_post_relax_hook;
#endif