]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: Record ill-specified CFA rule and diagnose in dwarf_frame_cfa, not immediately...
authorRoland McGrath <roland@redhat.com>
Tue, 27 Apr 2010 01:45:36 +0000 (18:45 -0700)
committerRoland McGrath <roland@redhat.com>
Tue, 27 Apr 2010 01:45:36 +0000 (18:45 -0700)
libdw/ChangeLog
libdw/cfi.c
libdw/cfi.h
libdw/dwarf_frame_cfa.c

index 50fba721cd8ca3df80bee3ba312a765ce8ba6631..a6e8457246246864fe2fcc14665f222857f184ee 100644 (file)
@@ -1,5 +1,10 @@
 2010-04-26  Roland McGrath  <roland@redhat.com>
 
+       * cfi.h (struct Dwarf_Frame_s): Add cfa_invalid alternative in cfa_rule.
+       * cfi.c (execute_cfi): Set that instead of doing cfi_assert for
+       DW_CFA_def_cfa_{offset*,register} when a non-offset rule is in force.
+       * dwarf_frame_cfa.c (dwarf_frame_cfa): Handle cfa_invalid.
+
        * dwarf_getlocation.c (__libdw_intern_expression): Take new arg CFAP.
        Prepend DW_OP_call_frame_cfa if true.
        (getlocation): Update caller.
index 5936659a77449a748359d8362d79fb579540f497..3cb378b6d73a5028ccdd29d9a46202889ef2ad02 100644 (file)
@@ -117,6 +117,12 @@ execute_cfi (Dwarf_CFI *cache,
       return true;
     }
 
+  inline void require_cfa_offset (void)
+  {
+    if (unlikely (fs->cfa_rule != cfa_offset))
+      fs->cfa_rule = cfa_invalid;
+  }
+
 #define register_rule(regno, r_rule, r_value) do {     \
     if (unlikely (! enough_registers (regno)))         \
       goto out;                                                \
@@ -177,7 +183,7 @@ execute_cfi (Dwarf_CFI *cache,
 
        case DW_CFA_def_cfa_register:
          get_uleb128 (regno, program);
-         cfi_assert (fs->cfa_rule == cfa_offset);
+         require_cfa_offset ();
          fs->cfa_val_reg = regno;
          continue;
 
@@ -190,7 +196,7 @@ execute_cfi (Dwarf_CFI *cache,
        case DW_CFA_def_cfa_offset:
          get_uleb128 (offset, program);
        def_cfa_offset:
-         cfi_assert (fs->cfa_rule == cfa_offset);
+         require_cfa_offset ();
          fs->cfa_val_offset = offset;
          continue;
 
index 64f3f157465ec3edb31003e4e7c3321aeae374e0..e04e76ddb02a74279719002c0f3883fb8108c6b1 100644 (file)
@@ -1,5 +1,5 @@
 /* Internal definitions for libdw CFI interpreter.
-   Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2009-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -191,8 +191,11 @@ struct Dwarf_Frame_s
      which has the return_address_register and signal_frame flag.  */
   struct dwarf_fde *fde;
 
-  /* The CFA is unknown, is R+N, or is computed by a DWARF expression.  */
-  enum { cfa_undefined, cfa_offset, cfa_expr } cfa_rule;
+  /* The CFA is unknown, is R+N, or is computed by a DWARF expression.
+     A bogon in the CFI can indicate an invalid/incalculable rule.
+     We store that as cfa_invalid rather than barfing when processing it,
+     so callers can ignore the bogon unless they really need that CFA.  */
+  enum { cfa_undefined, cfa_offset, cfa_expr, cfa_invalid } cfa_rule;
   union
   {
     Dwarf_Op offset;
index 03c5fbd24fe3ab8622f371a56a983e6fc8dfa366..0ba26b2fddac9b082a0705e7ef5ed2bb37bf4e2e 100644 (file)
@@ -88,6 +88,11 @@ dwarf_frame_cfa (fs, ops, nops)
         ops, nops, IDX_debug_frame);
       break;
 
+    case cfa_invalid:
+      __libdw_seterrno (DWARF_E_INVALID_CFI);
+      result = -1;
+      break;
+
     default:
       abort ();
     }