]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
LVU: defer reset-view checks that depend on late-resolved addresses
authorAlexandre Oliva <aoliva@redhat.com>
Thu, 18 May 2017 23:31:52 +0000 (20:31 -0300)
committerAlexandre Oliva <aoliva@redhat.com>
Thu, 18 May 2017 23:31:52 +0000 (20:31 -0300)
gas/dwarf2dbg.c
gas/dwarf2dbg.h
gas/write.c

index 29346c9cea09833b846d954d97e1e2db00073bc1..5f49e387644d91c2ad3ee270fb70b3e4af8a3cc0 100644 (file)
@@ -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;
 \f
@@ -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;
+       }
+    }
+}
index 7b5fcd1f90f5d72f127ee64857bb455f58455d2b..49826fd054a4e374e12368617f6b320385157c85 100644 (file)
@@ -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 {
index dd9e4af727b31a870c2df633e2936b4c9264de5b..09f6f0b678764042a9d17108194ab63598cb9383 100644 (file)
@@ -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