Author: sewardj
Date: 2008-02-21 01:50:10 +0000 (Thu, 21 Feb 2008)
New Revision: 7430

Log:
When evaluating Dwarf3 expressions, clearly distinguish between those
that denote values (addresses) and those that denote identities of
registers.  Use this to handle DW_AT_frame_base expressions whose
expression denotes a register name rather than a value.



Modified:
   branches/DATASYMS/coregrind/m_debuginfo/d3basics.c
   branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
   branches/DATASYMS/coregrind/m_debuginfo/priv_d3basics.h
   branches/DATASYMS/coregrind/m_debuginfo/tytypes.c


Modified: branches/DATASYMS/coregrind/m_debuginfo/d3basics.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/d3basics.c  2008-02-20 15:20:33 UTC 
(rev 7429)
+++ branches/DATASYMS/coregrind/m_debuginfo/d3basics.c  2008-02-21 01:50:10 UTC 
(rev 7430)
@@ -408,9 +408,8 @@
 
 #  define FAIL(_str)                                          \
       do {                                                    \
-         GXResult res;                                        \
-         res.res = 0;                                         \
-         res.failure = (_str);                                \
+         res.kind = GXR_Failure;                              \
+         res.word = (UWord)(_str);                            \
          return res;                                          \
       } while (0)
 
@@ -436,16 +435,44 @@
    UChar*   limit;
    Int      sp; /* # of top element: valid is -1 .. N_EXPR_STACK-1 */
    Addr     stack[N_EXPR_STACK]; /* stack of addresses, as per D3 spec */
-   GXResult fbval;
+   GXResult fbval, res;
    Addr     a1;
    Word     sw1;
    UWord    uw1;
+   Bool     ok;
 
    sp = -1;
    vg_assert(expr);
    vg_assert(exprszB >= 0);
    limit = expr + exprszB;
 
+   /* Deal with the case where the entire expression is a single
+      Register Name Operation (D3 spec sec 2.6.1).  Then the
+      denotation of the expression as a whole is a register name. */
+   if (exprszB == 1
+       && expr[0] >= DW_OP_reg0 && expr[0] <= DW_OP_reg31) {
+      res.kind = GXR_RegNo;
+      res.word = (UWord)(expr[0] - DW_OP_reg0);
+      return res;
+   }
+   if (exprszB > 1
+       && expr[0] == DW_OP_regx) {
+      /* JRS: 2008Feb20: I believe the following is correct, but would
+         like to see a test case show up before enabling it. */
+      vg_assert(0);
+      expr++;
+      res.kind = GXR_RegNo;
+      res.word = (UWord)read_leb128U( &expr );
+      if (expr != limit)
+         FAIL("evaluate_Dwarf3_Expr: DW_OP_regx*: invalid expr size");
+      else
+         return res;
+      /*NOTREACHED*/
+   }
+
+   /* Evidently this expresion denotes a value, not a register name.
+      So evaluate it accordingly. */
+
    if (push_initial_zero)
       PUSH(0);
 
@@ -479,19 +506,37 @@
                FAIL("evaluate_Dwarf3_Expr: DW_OP_fbreg with "
                     "no expr for fbreg present");
             fbval = ML_(evaluate_GX)(fbGX, NULL, regs);
-            if (fbval.failure)
-               return fbval;
+            /* Convert fbval into something we can use.  If we got a
+               Value, no problem.  However, as per D3 spec sec 3.3.5
+               (Low Level Information) sec 2, we could also get a
+               RegNo, and that is taken to mean the value in the
+               indicated register.  So we have to manually
+               "dereference" it. */
+            a1 = 0;
+            switch (fbval.kind) {
+               case GXR_Failure:
+                  return fbval; /* propagate failure */
+               case GXR_Value:
+                  a1 = fbval.word; break; /* use as-is */
+               case GXR_RegNo:
+                  ok = get_Dwarf_Reg( &a1, fbval.word, regs );
+                  if (!ok) return fbval; /* propagate failure */
+                  break;
+               default:
+                  vg_assert(0);
+            }
             sw1 = (Word)read_leb128S( &expr );
-            PUSH( fbval.res + sw1 );
+            PUSH( a1 + sw1 );
             break;
          /* DW_OP_breg* denotes 'contents of specified register, plus
             constant offset'.  So provided we know what the register's
             value is, we can evaluate this.  Contrast DW_OP_reg*,
             which indicates that denoted location is in a register
-            itself.  For DW_OP_reg* we must always fail, since this
-            function is intended to compute a memory address of some
-            kind.  See D3 Spec sec 2.6.1 ("Register Name Operations")
-            for details. */
+            itself.  If DW_OP_reg* shows up here the expression is
+            malformed, since we are evaluating for value now, and
+            DW_OP_reg* denotes a register location, not a value.  See
+            D3 Spec sec 2.6.1 ("Register Name Operations") for
+            details. */
          case DW_OP_breg0 ... DW_OP_breg31:
             if (!regs)
                FAIL("evaluate_Dwarf3_Expr: DW_OP_breg* but no reg info");
@@ -504,9 +549,11 @@
             break;
          /* As per comment on DW_OP_breg*, the following denote that
             the value in question is in a register, not in memory.  So
-            we simply return failure. */
+            we simply return failure. (iow, the expression is
+            malformed). */
          case DW_OP_reg0 ... DW_OP_reg31:
-            FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* (value is in a register)");
+            FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* "
+                 "whilst evaluating for a value");
             break;
          case DW_OP_plus_uconst:
             POP(uw1);
@@ -525,13 +572,10 @@
    }
 
    vg_assert(sp >= 0 && sp < N_EXPR_STACK);
-
-   { GXResult res; 
-     res.res = stack[sp];
-     res.failure = NULL;
-     return res;
-   }
-
+   res.word = stack[sp];
+   res.kind = GXR_Value;
+   return res;
+ 
 #  undef POP
 #  undef PUSH
 #  undef FAIL
@@ -558,8 +602,8 @@
       uc = *p++;
       if (uc == 1) { /*isEnd*/
          /* didn't find any matching range. */
-         res.res = 0;
-         res.failure = "no matching range";
+         res.kind = GXR_Failure;
+         res.word = (UWord)"no matching range";
          return res;
       }
       vg_assert(uc == 0);
@@ -593,6 +637,21 @@
 }
 
 
+void ML_(pp_GXResult) ( GXResult res )
+{
+   switch (res.kind) {
+      case GXR_Failure:
+         VG_(printf)("GXR_Failure(%s)", (HChar*)res.word); break;
+      case GXR_Value:
+         VG_(printf)("GXR_Value(0x%lx)", res.word); break;
+      case GXR_RegNo:
+         VG_(printf)("GXR_RegNo(%lu)", res.word); break;
+      default:
+         VG_(printf)("GXR_???"); break;
+   }
+}
+
+
 /*--------------------------------------------------------------------*/
 /*--- end                                               d3basics.c ---*/
 /*--------------------------------------------------------------------*/

Modified: branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-20 15:20:33 UTC 
(rev 7429)
+++ branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-21 01:50:10 UTC 
(rev 7430)
@@ -1613,11 +1613,16 @@
 
    res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs );
 
-   if (show) VG_(printf)("VVVV: -> 0x%lx %s\n", res.res, 
-                         res.failure ? res.failure : "(success)");
-   if (!res.failure && res.res <= data_addr
-                    && data_addr < res.res + var_szB) {
-      *offset = data_addr - res.res;
+   if (show) {
+      VG_(printf)("VVVV: -> ");
+      ML_(pp_GXResult)( res );
+      VG_(printf)("\n");
+   }
+
+   if (res.kind == GXR_Value 
+       && res.word <= data_addr
+       && data_addr < res.word + var_szB) {
+      *offset = data_addr - res.word;
       return True;
    } else {
       return False;

Modified: branches/DATASYMS/coregrind/m_debuginfo/priv_d3basics.h
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/priv_d3basics.h     2008-02-20 
15:20:33 UTC (rev 7429)
+++ branches/DATASYMS/coregrind/m_debuginfo/priv_d3basics.h     2008-02-21 
01:50:10 UTC (rev 7430)
@@ -595,14 +595,20 @@
    struct { Addr ip; Addr sp; Addr fp; }
    RegSummary;
 
-/* This describes the result of evaluating a DWARF3 expression.  If
-   .failure is NULL, then evaluation succeeded and produced .res as
-   the result.  Else .failure is a zero terminated const string
-   summarising the reason for failure.  */
+/* This describes the result of evaluating a DWARF3 expression.
+   GXR_Failure: failed; .word is an asciiz string summarising why
+   GXR_Value:   evaluated to a value, in .word
+   GXR_RegNo:   evaluated to a DWARF3 register number, in .word
+*/
 typedef
-   struct { UWord res; HChar* failure; }
+   struct { 
+      enum { GXR_Failure, GXR_Value, GXR_RegNo } kind;
+      UWord word;
+   }
    GXResult;
 
+void ML_(pp_GXResult) ( GXResult res );
+
 /* Evaluate a guarded expression.  If regs is NULL, then gx is assumed
    (and checked) to contain just a single guarded expression, with a
    guard which covers the entire address space and so always evaluates

Modified: branches/DATASYMS/coregrind/m_debuginfo/tytypes.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/tytypes.c   2008-02-20 15:20:33 UTC 
(rev 7429)
+++ branches/DATASYMS/coregrind/m_debuginfo/tytypes.c   2008-02-21 01:50:10 UTC 
(rev 7430)
@@ -438,10 +438,14 @@
                        field->loc->bytes, field->loc->nbytes,
                        NULL/*fbGX*/, NULL/*RegSummary*/,
                        True/*push_initial_zero*/ );
-               if (0) VG_(printf)("QQQ %lu %s\n", res.res,res.failure);
-               if (res.failure)
+               if (0) {
+                  VG_(printf)("QQQ ");
+                  ML_(pp_GXResult)(res);
+                  VG_(printf)("\n");
+               }
+               if (res.kind != GXR_Value)
                   continue;
-               offMin = res.res;
+               offMin = res.word;
                offMax1 = offMin + ML_(sizeOfType)( field->typeR );
                if (offMin == offMax1)
                   continue;


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Valgrind-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers

Reply via email to