Various improvements to DWARF handling to cope with changes in recent
versions of gcc as shipped with Fedora 12. Specific changes include:

  - Vastly increase the number of opcodes we understand how to
    evaluate when processing a location expression.

  - Process frame unwind data from the debug_frame ELF section as
    well as the eh_frame section.

  - Handle version 3 CIEs in frame unwind data.

  - Handle the compact form of DW_AT_data_member_location which just
    gives a constant offset from the start of it's base type instead
    of a full location expression.

Based on patches from Jakub Jelinek on bugs #210479 and #210566.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10939 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c
index a61ed05..efaf5a4 100644
--- a/coregrind/m_debuginfo/d3basics.c
+++ b/coregrind/m_debuginfo/d3basics.c
@@ -387,12 +387,8 @@
    if (regno == 7/*RSP*/) { *a = regs->sp; return True; }
 #  elif defined(VGP_ppc32_linux)
    if (regno == 1/*SP*/) { *a = regs->sp; return True; }
-   if (regno == 31) return False;
-   vg_assert(0);
 #  elif defined(VGP_ppc64_linux)
    if (regno == 1/*SP*/) { *a = regs->sp; return True; }
-   if (regno == 31) return False;
-   vg_assert(0);
 #  elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
    vg_assert(0); /* this function should never be called */
 #  else
@@ -443,7 +439,7 @@
 
 
 /* Evaluate a standard DWARF3 expression.  See detailed description in
-   priv_d3basics.h. */
+   priv_d3basics.h.  Doesn't handle DW_OP_piece/DW_OP_bit_piece yet.  */
 GXResult ML_(evaluate_Dwarf3_Expr) ( UChar* expr, UWord exprszB, 
                                      GExpr* fbGX, RegSummary* regs,
                                      const DebugInfo* di,
@@ -482,8 +478,8 @@
    Addr     stack[N_EXPR_STACK]; /* stack of addresses, as per D3 spec */
    GXResult fbval, res;
    Addr     a1;
-   Word     sw1;
-   UWord    uw1;
+   Word     sw1, sw2;
+   UWord    uw1, uw2;
    Bool     ok;
 
    sp = -1;
@@ -568,12 +564,15 @@
             switch (fbval.kind) {
                case GXR_Failure:
                   return fbval; /* propagate failure */
-               case GXR_Value:
+               case GXR_Addr:
                   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;
+               case GXR_Value:
+                  FAIL("evaluate_Dwarf3_Expr: DW_OP_{implicit,stack}_value "
+                       "in DW_AT_frame_base");
                default:
                   vg_assert(0);
             }
@@ -599,11 +598,23 @@
             a1 += sw1;
             PUSH( a1 );
             break;
+         case DW_OP_bregx:
+            if (!regs)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_bregx but no reg info");
+            a1 = 0;
+            uw1 = (UWord)read_leb128U( &expr );
+            if (!get_Dwarf_Reg( &a1, uw1, regs ))
+               FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_bregx reg value");
+            sw1 = (Word)read_leb128S( &expr );
+            a1 += sw1;
+            PUSH( a1 );
+            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. (iow, the expression is
             malformed). */
          case DW_OP_reg0 ... DW_OP_reg31:
+         case DW_OP_regx:
             FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* "
                  "whilst evaluating for a value");
             break;
@@ -637,6 +648,238 @@
                     "address not valid for client");
             }
             break;
+         case DW_OP_deref_size:
+            POP(uw1);
+            uw2 = *expr++;
+            if (VG_(am_is_valid_for_client)( (Addr)uw1, uw2,
+                                             VKI_PROT_READ )) {
+               switch (uw2) {
+                 case 1: uw1 = *(UChar*)uw1; break;
+                 case 2: uw1 = *(UShort*)uw1; break;
+                 case 4: uw1 = *(UInt*)uw1; break;
+                 case 8: uw1 = *(ULong*)uw1; break;
+                 default:
+                    FAIL("warning: evaluate_Dwarf3_Expr: unhandled "
+                         "DW_OP_deref_size size");
+               }
+               PUSH(uw1);
+            } else {
+               FAIL("warning: evaluate_Dwarf3_Expr: DW_OP_deref_size: "
+                    "address not valid for client");
+            }
+            break;
+         case DW_OP_lit0 ... DW_OP_lit31:
+            PUSH(opcode - DW_OP_lit0);
+            break;
+         case DW_OP_const1u:
+	    uw1 = *expr++;
+	    PUSH(uw1);
+            break;
+         case DW_OP_const2u:
+	    uw1 = *(UShort *)expr;
+	    expr += 2;
+	    PUSH(uw1);
+	    break;
+         case DW_OP_const4u:
+	    uw1 = *(UInt *)expr;
+	    expr += 4;
+	    PUSH(uw1);
+	    break;
+         case DW_OP_const8u:
+	    uw1 = *(ULong *)expr;
+	    expr += 8;
+	    PUSH(uw1);
+	    break;
+         case DW_OP_constu:
+            uw1 = read_leb128U( &expr );
+            PUSH(uw1);
+            break;
+         case DW_OP_const1s:
+	    uw1 = *(Char *)expr;
+	    expr++;
+	    PUSH(uw1);
+            break;
+         case DW_OP_const2s:
+	    uw1 = *(Short *)expr;
+	    expr += 2;
+	    PUSH(uw1);
+	    break;
+         case DW_OP_const4s:
+	    uw1 = *(Int *)expr;
+	    expr += 4;
+	    PUSH(uw1);
+	    break;
+         case DW_OP_const8s:
+	    uw1 = *(Long *)expr;
+	    expr += 8;
+	    PUSH(uw1);
+	    break;
+         case DW_OP_consts:
+            uw1 = read_leb128S( &expr );
+            PUSH(uw1);
+            break;
+         case DW_OP_dup:
+	    POP(uw1);
+	    PUSH(uw1);
+	    PUSH(uw1);
+	    break;
+	 case DW_OP_drop:
+	    POP(uw1);
+	    break;
+         case DW_OP_over:
+            uw1 = 1;
+            goto do_pick;
+	 case DW_OP_pick:
+	    uw1 = *expr++;
+         do_pick:
+            if (sp < (Int)uw1)
+               FAIL("evaluate_Dwarf3_Expr: stack underflow");
+            uw1 = stack[sp - uw1];
+            PUSH(uw1);
+            break;
+         case DW_OP_swap:
+            if (sp < 1)
+               FAIL("evaluate_Dwarf3_Expr: stack underflow");
+            uw1 = stack[sp];
+            stack[sp] = stack[sp - 1];
+            stack[sp - 1] = uw1;
+            break;
+         case DW_OP_rot:
+            if (sp < 2)
+               FAIL("evaluate_Dwarf3_Expr: stack underflow");
+            uw1 = stack[sp];
+            stack[sp] = stack[sp - 1];
+            stack[sp - 1] = stack[sp - 2];
+            stack[sp - 2] = uw1;
+            break;
+         case DW_OP_abs:
+            POP(sw1);
+            if (sw1 < 0)
+               sw1 = -sw1;
+            PUSH(sw1);
+            break;
+         case DW_OP_div:
+            POP(sw2);
+            if (sw2 == 0)
+               FAIL("evaluate_Dwarf3_Expr: division by zero");
+            POP(sw1);
+            sw1 /= sw2;
+            PUSH(sw1);
+            break;
+         case DW_OP_mod:
+            POP(sw2);
+            if (sw2 == 0)
+               FAIL("evaluate_Dwarf3_Expr: division by zero");
+            POP(sw1);
+            sw1 %= sw2;
+            PUSH(sw1);
+            break;
+#define BINARY(name, op, s) \
+         case DW_OP_##name:		\
+            POP(s##w2);			\
+            POP(s##w1);			\
+            s##w1 = s##w1 op s##w2;	\
+            PUSH(s##w1);		\
+            break
+#define UNARY(name, op, s) \
+         case DW_OP_##name:		\
+            POP(s##w1);			\
+            s##w1 = op s##w1;		\
+            PUSH(s##w1);		\
+            break
+         BINARY (and, &, u);
+         BINARY (minus, -, u);
+         BINARY (mul, *, u);
+         UNARY (neg, -, u);
+         UNARY (not, ~, u);
+         BINARY (or, |, u);
+         BINARY (plus, +, u);
+         BINARY (shl, <<, u);
+         BINARY (shr, >>, u);
+         BINARY (shra, >>, s);
+         BINARY (xor, ^, u);
+         BINARY (le, <=, s);
+         BINARY (lt, <, s);
+         BINARY (ge, >=, s);
+         BINARY (gt, >, s);
+         BINARY (ne, !=, u);
+         BINARY (eq, ==, u);
+#undef UNARY
+#undef BINARY
+         case DW_OP_skip:
+            sw1 = *(Short *)expr;
+            expr += 2;
+            if (expr + sw1 < limit - exprszB)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_skip before start of expr");
+            if (expr + sw1 >= limit)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_skip after end of expr");
+            expr += sw1;
+            break;
+         case DW_OP_bra:
+            sw1 = *(Short *)expr;
+            expr += 2;
+            if (expr + sw1 < limit - exprszB)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_bra before start of expr");
+            if (expr + sw1 >= limit)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_bra after end of expr");
+            POP(uw1);
+            if (uw1)
+               expr += sw1;
+            break;
+         case DW_OP_nop:
+            break;
+         case DW_OP_call_frame_cfa:
+            if (!regs)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_call_frame_cfa but no reg info");
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+            /* Valgrind on ppc32/ppc64 currently doesn't use unwind info.  */
+            uw1 = *(Addr *)(regs->sp);
+#else
+            uw1 = ML_(get_CFA)(regs->ip, regs->sp, regs->fp, 0, ~(UWord) 0);
+#endif
+            if (!uw1)
+               FAIL("evaluate_Dwarf3_Expr: Could not resolve "
+                    "DW_OP_call_frame_cfa");
+            PUSH(uw1);
+            break;
+         case DW_OP_implicit_value:
+            sw1 = (Word)read_leb128S( &expr );
+            uw1 = 0;
+            switch (sw1) {
+               case 1:
+                  uw1 = *(UChar *)expr;
+                  expr += 1;
+                  break;
+               case 2:
+                  uw1 = *(UShort *)expr;
+                  expr += 2;
+                  break;
+               case 4:
+                  uw1 = *(UInt *)expr;
+                  expr += 4;
+                  break;
+               case 8:
+                  uw1 = *(ULong *)expr;
+                  expr += 8;
+                  break;
+               default:
+                  FAIL("evaluate_Dwarf3_Expr: Unhandled "
+                       "DW_OP_implicit_value size");
+            }
+            if (expr != limit)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_implicit_value "
+                    "does not terminate expression");
+            res.word = uw1;
+            res.kind = GXR_Value;
+            return res;
+         case DW_OP_stack_value:
+            POP (uw1);
+            res.word = uw1;
+            res.kind = GXR_Value;
+            if (expr != limit)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_stack_value "
+                    "does not terminate expression");
+            break;
          default:
             if (!VG_(clo_xml))
                VG_(message)(Vg_DebugMsg, 
@@ -650,7 +893,7 @@
 
    vg_assert(sp >= 0 && sp < N_EXPR_STACK);
    res.word = stack[sp];
-   res.kind = GXR_Value;
+   res.kind = GXR_Addr;
    return res;
  
 #  undef POP
@@ -829,12 +1072,15 @@
          if (!badness)
             badness = "trivial GExpr denotes register (2)";
       }
-      else {
+      else if (0) {
          VG_(printf)(" ML_(evaluate_trivial_GX): unhandled:\n   ");
          ML_(pp_GX)( gx );
          VG_(printf)("\n");
          tl_assert(0);
       }
+      else
+         if (!badness)
+            badness = "non-trivial GExpr";
 
       VG_(addToXA)( results, &thisResult );
 
@@ -884,7 +1130,7 @@
 
    /* Well, we have success.  All subexpressions evaluated, and 
       they all agree.  Hurrah. */
-   res.kind = GXR_Value;
+   res.kind = GXR_Addr;
    res.word = (UWord)mul->ul; /* NB: narrowing from ULong */
    VG_(deleteXA)( results );
    return res;
@@ -896,6 +1142,8 @@
    switch (res.kind) {
       case GXR_Failure:
          VG_(printf)("GXR_Failure(%s)", (HChar*)res.word); break;
+      case GXR_Addr:
+         VG_(printf)("GXR_Addr(0x%lx)", res.word); break;
       case GXR_Value:
          VG_(printf)("GXR_Value(0x%lx)", res.word); break;
       case GXR_RegNo:
diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index 66ae82b..106d398 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -2003,6 +2003,94 @@
 }
 
 
+static CFSICacheEnt* cfsi_cache__find ( Addr ip )
+{
+   UWord         hash = ip % N_CFSI_CACHE;
+   CFSICacheEnt* ce = &cfsi_cache[hash];
+   static UWord  n_q = 0, n_m = 0;
+
+   n_q++;
+   if (0 && 0 == (n_q & 0x1FFFFF))
+      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
+
+   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
+      /* found an entry in the cache .. */
+   } else {
+      /* not found in cache.  Search and update. */
+      n_m++;
+      ce->ip = ip;
+      find_DiCfSI( &ce->di, &ce->ix, ip );
+   }
+
+   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
+      /* no DiCfSI for this address */
+      return NULL;
+   } else {
+      /* found a DiCfSI for this address */
+      return ce;
+   }
+}
+
+
+static Addr compute_cfa ( Addr ip, Addr sp, Addr fp,
+                          Addr min_accessible, Addr max_accessible,
+                          DebugInfo* di, DiCfSI* cfsi )
+{
+   CfiExprEvalContext eec;
+   Addr               cfa;
+   Bool               ok;
+
+   /* Compute the CFA. */
+   cfa = 0;
+   switch (cfsi->cfa_how) {
+      case CFIC_SPREL: 
+         cfa = sp + cfsi->cfa_off;
+         break;
+      case CFIC_FPREL: 
+         cfa = fp + cfsi->cfa_off;
+         break;
+      case CFIC_EXPR: 
+         if (0) {
+            VG_(printf)("CFIC_EXPR: ");
+            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
+            VG_(printf)("\n");
+         }
+         eec.ipHere = ip;
+         eec.spHere = sp;
+         eec.fpHere = fp;
+         eec.min_accessible = min_accessible;
+         eec.max_accessible = max_accessible;
+         ok = True;
+         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
+         if (!ok) return 0;
+         break;
+      default: 
+         vg_assert(0);
+   }
+   return cfa;
+}
+
+
+/* Get the call frame address (CFA) given an IP/SP/FP triple. */
+Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
+                    Addr min_accessible, Addr max_accessible )
+{
+   CFSICacheEnt* ce;
+   DebugInfo*    di;
+   DiCfSI*       cfsi;
+
+   ce = cfsi_cache__find(ip);
+
+   if (UNLIKELY(ce == NULL))
+      return 0; /* no info.  Nothing we can do. */
+
+   di = ce->di;
+   cfsi = &di->cfsi[ ce->ix ];
+
+   return compute_cfa(ip, sp, fp, min_accessible,  max_accessible, di, cfsi);
+}
+
+
 /* The main function for DWARF2/3 CFI-based stack unwinding.
    Given an IP/SP/FP triple, produce the IP/SP/FP values for the
    previous frame, if possible. */
@@ -2015,44 +2103,21 @@
                         Addr min_accessible,
                         Addr max_accessible )
 {
-   Bool       ok;
-   DebugInfo* di;
-   DiCfSI*    cfsi = NULL;
-   Addr       cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
-
+   Bool               ok;
+   DebugInfo*         di;
+   DiCfSI*            cfsi = NULL;
+   Addr               cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
+   CFSICacheEnt*      ce;
    CfiExprEvalContext eec;
 
-   static UWord n_q = 0, n_m = 0;
-   n_q++;
-   if (0 && 0 == (n_q & 0x1FFFFF))
-      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
+   ce = cfsi_cache__find(*ipP);
 
-   { UWord hash = (*ipP) % N_CFSI_CACHE;
-     CFSICacheEnt* ce = &cfsi_cache[hash];
-
-     if (LIKELY(ce->ip == *ipP) && LIKELY(ce->di != NULL)) {
-        /* found an entry in the cache .. */
-     } else {
-        /* not found in cache.  Search and update. */
-        n_m++;
-        ce->ip = *ipP;
-        find_DiCfSI( &ce->di, &ce->ix, *ipP );
-     }
-
-     if (UNLIKELY(ce->di == (DebugInfo*)1)) {
-        /* no DiCfSI for this address */
-        cfsi = NULL;
-        di = NULL;
-     } else {
-        /* found a DiCfSI for this address */
-        di = ce->di;
-        cfsi = &di->cfsi[ ce->ix ];
-     }
-   }
-
-   if (UNLIKELY(cfsi == NULL))
+   if (UNLIKELY(ce == NULL))
       return False; /* no info.  Nothing we can do. */
 
+   di = ce->di;
+   cfsi = &di->cfsi[ ce->ix ];
+
    if (0) {
       VG_(printf)("found cfisi: "); 
       ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
@@ -2065,32 +2130,10 @@
    fpHere = *fpP;
 
    /* First compute the CFA. */
-   cfa = 0;
-   switch (cfsi->cfa_how) {
-      case CFIC_SPREL: 
-         cfa = cfsi->cfa_off + spHere;
-         break;
-      case CFIC_FPREL: 
-         cfa = cfsi->cfa_off + fpHere;
-         break;
-      case CFIC_EXPR: 
-         if (0) {
-            VG_(printf)("CFIC_EXPR: ");
-            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
-            VG_(printf)("\n");
-         }
-         eec.ipHere = ipHere;
-         eec.spHere = spHere;
-         eec.fpHere = fpHere;
-         eec.min_accessible = min_accessible;
-         eec.max_accessible = max_accessible;
-         ok = True;
-         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
-         if (!ok) return False;
-         break;
-      default: 
-         vg_assert(0);
-   }
+   cfa = compute_cfa(ipHere, spHere, fpHere,
+                     min_accessible,  max_accessible, di, cfsi);
+   if (UNLIKELY(cfa == 0))
+      return False;
 
    /* Now we know the CFA, use it to roll back the registers we're
       interested in. */
@@ -2346,7 +2389,7 @@
       VG_(printf)("\n");
    }
 
-   if (res.kind == GXR_Value 
+   if (res.kind == GXR_Addr 
        && res.word <= data_addr
        && data_addr < res.word + var_szB) {
       *offset = data_addr - res.word;
@@ -3057,7 +3100,7 @@
    vg_assert(res_sp_6k.kind == res_fp_6k.kind);
    vg_assert(res_sp_6k.kind == res_fp_7k.kind);
 
-   if (res_sp_6k.kind == GXR_Value) {
+   if (res_sp_6k.kind == GXR_Addr) {
       StackBlock block;
       GXResult res;
       UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
@@ -3074,7 +3117,7 @@
          regs.sp = regs.fp = 0;
          regs.ip = ip;
          res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
-         tl_assert(res.kind == GXR_Value);
+         tl_assert(res.kind == GXR_Addr);
          if (debug)
          VG_(printf)("   %5ld .. %5ld (sp) %s\n",
                      res.word, res.word + ((UWord)mul.ul) - 1, var->name);
@@ -3093,7 +3136,7 @@
          regs.sp = regs.fp = 0;
          regs.ip = ip;
          res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
-         tl_assert(res.kind == GXR_Value);
+         tl_assert(res.kind == GXR_Addr);
          if (debug)
          VG_(printf)("   %5ld .. %5ld (FP) %s\n",
                      res.word, res.word + ((UWord)mul.ul) - 1, var->name);
@@ -3308,7 +3351,7 @@
             res = ML_(evaluate_trivial_GX)( var->gexpr, di );
 
             /* Not a constant address => not interesting */
-            if (res.kind != GXR_Value) {
+            if (res.kind != GXR_Addr) {
                if (0) VG_(printf)("FAIL\n");
                continue;
             }
diff --git a/coregrind/m_debuginfo/priv_d3basics.h b/coregrind/m_debuginfo/priv_d3basics.h
index 1368e0d..81f46ef 100644
--- a/coregrind/m_debuginfo/priv_d3basics.h
+++ b/coregrind/m_debuginfo/priv_d3basics.h
@@ -522,6 +522,9 @@
     DW_OP_form_tls_address = 0x9b,
     DW_OP_call_frame_cfa = 0x9c,
     DW_OP_bit_piece = 0x9d,
+    /* DWARF 4 extensions.  */
+    DW_OP_implicit_value = 0x9e,
+    DW_OP_stack_value = 0x9f,
     /* GNU extensions.  */
     DW_OP_GNU_push_tls_address = 0xe0,
     /* HP extensions.  */
@@ -596,12 +599,13 @@
 
 /* This describes the result of evaluating a DWARF3 expression.
    GXR_Failure: failed; .word is an asciiz string summarising why
+   GXR_Addr:    evaluated to an address of the object, in .word
    GXR_Value:   evaluated to a value, in .word
    GXR_RegNo:   evaluated to a DWARF3 register number, in .word
 */
 typedef
    struct { 
-      enum { GXR_Failure, GXR_Value, GXR_RegNo } kind;
+      enum { GXR_Failure, GXR_Addr, GXR_Value, GXR_RegNo } kind;
       UWord word;
    }
    GXResult;
@@ -644,6 +648,10 @@
    covered by the guard is also ignored. */
 GXResult ML_(evaluate_trivial_GX)( GExpr* gx, const DebugInfo* di );
 
+/* Compute call frame address (CFA) for IP/SP/FP.  */
+Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
+                    Addr min_accessible, Addr max_accessible );
+
 #endif /* ndef __PRIV_D3BASICS_H */
 
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/m_debuginfo/priv_readdwarf.h b/coregrind/m_debuginfo/priv_readdwarf.h
index dc9fb99..299daf4 100644
--- a/coregrind/m_debuginfo/priv_readdwarf.h
+++ b/coregrind/m_debuginfo/priv_readdwarf.h
@@ -62,7 +62,7 @@
    -------------------- */
 extern
 void ML_(read_callframe_info_dwarf3)
-    ( /*OUT*/struct _DebugInfo* di, UChar* ehframe );
+    ( /*OUT*/struct _DebugInfo* di, UChar* frame, SizeT frame_sz, Bool for_eh );
 
 
 #endif /* ndef __PRIV_READDWARF_H */
diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
index cff91f7..b790001 100644
--- a/coregrind/m_debuginfo/priv_storage.h
+++ b/coregrind/m_debuginfo/priv_storage.h
@@ -649,6 +649,11 @@
    this after finishing adding entries to these tables. */
 extern void ML_(canonicaliseTables) ( struct _DebugInfo* di );
 
+/* Canonicalise the call-frame-info table held by 'di', in preparation
+   for use. This is called by ML_(canonicaliseTables) but can also be
+   called on it's own to sort just this table. */
+extern void ML_(canonicaliseCFI) ( struct _DebugInfo* di );
+
 /* ------ Searching ------ */
 
 /* Find a symbol-table index containing the specified pointer, or -1
diff --git a/coregrind/m_debuginfo/priv_tytypes.h b/coregrind/m_debuginfo/priv_tytypes.h
index 880aa0e..354cf60 100644
--- a/coregrind/m_debuginfo/priv_tytypes.h
+++ b/coregrind/m_debuginfo/priv_tytypes.h
@@ -78,8 +78,13 @@
          struct {
             UChar* name;  /* in mallocville */
             UWord  typeR; /* should be Te_TyXXXX */
-            UChar* loc;   /* location expr, in mallocville */
-            UWord  nLoc;  /* number of bytes in .loc */
+            union {
+               UChar* loc;   /* location expr, in mallocville */
+               Word offset;  /* or offset from the beginning of containing
+                                entity */
+            } pos;
+            Word  nLoc;  /* number of bytes in .pos.loc if >= 0, or -1
+                            if .pos.offset should be used instead */
             Bool   isStruct;
          } Field;
          struct {
diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
index 15cf70a..bde2cf1 100644
--- a/coregrind/m_debuginfo/readdwarf.c
+++ b/coregrind/m_debuginfo/readdwarf.c
@@ -37,6 +37,7 @@
 #include "pub_core_libcprint.h"
 #include "pub_core_options.h"
 #include "pub_core_xarray.h"
+#include "pub_core_tooliface.h"    /* VG_(needs) */
 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
 #include "priv_d3basics.h"
 #include "priv_tytypes.h"
@@ -1777,11 +1778,11 @@
 #elif defined(VGP_ppc32_linux)
 #  define FP_REG         1
 #  define SP_REG         1
-#  define RA_REG_DEFAULT 8     // CAB: What's a good default ?
+#  define RA_REG_DEFAULT 65
 #elif defined(VGP_ppc64_linux)
 #  define FP_REG         1
 #  define SP_REG         1
-#  define RA_REG_DEFAULT 8     // CAB: What's a good default ?
+#  define RA_REG_DEFAULT 65
 #elif defined(VGP_x86_darwin)
 #  define FP_REG         5
 #  define SP_REG         4
@@ -1795,7 +1796,11 @@
 #endif
 
 /* the number of regs we are prepared to unwind */
-#define N_CFI_REGS 20
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+# define N_CFI_REGS 72
+#else
+# define N_CFI_REGS 20
+#endif
 
 /* Instructions for the automaton */
 enum dwarf_cfa_primary_ops
@@ -3446,23 +3451,33 @@
 
 
 void ML_(read_callframe_info_dwarf3)
-        ( /*OUT*/struct _DebugInfo* di, UChar* ehframe_image )
+        ( /*OUT*/struct _DebugInfo* di, UChar* frame_image, SizeT frame_size,
+          Bool for_eh )
 {
    Int    nbytes;
    HChar* how = NULL;
    Int    n_CIEs = 0;
-   UChar* data = ehframe_image;
+   UChar* data = frame_image;
+   UWord  ehframe_cfsis = 0;
+   Addr   frame_avma = for_eh ? di->ehframe_avma : 0;
 
 #  if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
-   /* These targets don't use CFI-based stack unwinding. */
+   /* These targets don't use CFI-based stack unwinding.  */
    return;
 #  endif
 
+   /* If we are reading .debug_frame after .eh_frame has been read, only
+      add FDEs which weren't covered in .eh_frame.  To be able to quickly
+      search the FDEs, the records must be sorted.  */
+   if ( ! for_eh && di->ehframe_size && di->cfsi_used ) {
+      ML_(canonicaliseCFI) ( di );
+      ehframe_cfsis = di->cfsi_used;
+   }
+
    if (di->trace_cfi) {
       VG_(printf)("\n-----------------------------------------------\n");
       VG_(printf)("CFI info: szB %ld, _avma %#lx, _image %p\n",
-                  di->ehframe_size, di->ehframe_avma,
-                  ehframe_image );
+                  frame_size, frame_avma, frame_image );
       VG_(printf)("CFI info: name %s\n",
                   di->filename );
    }
@@ -3495,11 +3510,11 @@
       Bool   dw64;
 
       /* Are we done? */
-      if (data == ehframe_image + di->ehframe_size)
+      if (data == frame_image + frame_size)
          return;
 
       /* Overshot the end?  Means something is wrong */
-      if (data > ehframe_image + di->ehframe_size) {
+      if (data > frame_image + frame_size) {
          how = "overran the end of .eh_frame";
          goto bad;
       }
@@ -3509,9 +3524,9 @@
 
       ciefde_start = data;
       if (di->trace_cfi) 
-         VG_(printf)("\ncie/fde.start   = %p (ehframe_image + 0x%lx)\n", 
+         VG_(printf)("\ncie/fde.start   = %p (frame_image + 0x%lx)\n", 
                      ciefde_start,
-                     ciefde_start - ehframe_image + 0UL);
+                     ciefde_start - frame_image + 0UL);
 
       ciefde_len = (ULong) read_UInt(data); data += sizeof(UInt);
       if (di->trace_cfi) 
@@ -3524,7 +3539,7 @@
       if (ciefde_len == 0) {
          if (di->ddump_frames)
             VG_(printf)("%08lx ZERO terminator\n\n",
-                        ((Addr)ciefde_start) - ((Addr)ehframe_image));
+                        ((Addr)ciefde_start) - ((Addr)frame_image));
          return;
       }
 
@@ -3550,8 +3565,10 @@
       if (di->trace_cfi) 
          VG_(printf)("cie.pointer     = %lld\n", cie_pointer);
 
-      /* If cie_pointer is zero, we've got a CIE; else it's an FDE. */
-      if (cie_pointer == 0) {
+      /* If cie_pointer is zero for .eh_frame or all ones for .debug_frame,
+         we've got a CIE; else it's an FDE. */
+      if (cie_pointer == (for_eh ? 0ULL
+                          : dw64 ? 0xFFFFFFFFFFFFFFFFULL : 0xFFFFFFFFULL)) {
 
          Int    this_CIE;
          UChar  cie_version;
@@ -3575,11 +3592,11 @@
 
 	 /* Record its offset.  This is how we will find it again
             later when looking at an FDE. */
-         the_CIEs[this_CIE].offset = (ULong)(ciefde_start - ehframe_image);
+         the_CIEs[this_CIE].offset = (ULong)(ciefde_start - frame_image);
 
          if (di->ddump_frames)
             VG_(printf)("%08lx %08lx %08lx CIE\n",
-                        ((Addr)ciefde_start) - ((Addr)ehframe_image),
+                        ((Addr)ciefde_start) - ((Addr)frame_image),
                         (Addr)ciefde_len,
                         (Addr)(UWord)cie_pointer );
 
@@ -3623,8 +3640,13 @@
             VG_(printf)("  Data alignment factor: %d\n",
                         (Int)the_CIEs[this_CIE].data_a_f);
 
-         the_CIEs[this_CIE].ra_reg = (Int)read_UChar(data); 
-         data += sizeof(UChar);
+         if (cie_version == 1) {
+            the_CIEs[this_CIE].ra_reg = (Int)read_UChar(data); 
+            data += sizeof(UChar);
+         } else {
+            the_CIEs[this_CIE].ra_reg = read_leb128( data, &nbytes, 0);
+            data += nbytes;
+         }
          if (di->trace_cfi) 
             VG_(printf)("cie.ra_reg      = %d\n", 
                         the_CIEs[this_CIE].ra_reg);
@@ -3702,7 +3724,7 @@
 	 }
 
          if (the_CIEs[this_CIE].ilen < 0
-             || the_CIEs[this_CIE].ilen > di->ehframe_size) {
+             || the_CIEs[this_CIE].ilen > frame_size) {
             how = "implausible # cie initial insns";
             goto bad;
          }
@@ -3717,8 +3739,8 @@
          if (di->trace_cfi || di->ddump_frames) {
             AddressDecodingInfo adi;
             adi.encoding      = the_CIEs[this_CIE].address_encoding;
-            adi.ehframe_image = ehframe_image;
-            adi.ehframe_avma  = di->ehframe_avma;
+            adi.ehframe_image = frame_image;
+            adi.ehframe_avma  = frame_avma;
             adi.text_bias     = di->text_debug_bias;
             show_CF_instructions( the_CIEs[this_CIE].instrs, 
                                   the_CIEs[this_CIE].ilen, &adi,
@@ -3747,9 +3769,12 @@
             cie_pointer bytes back from here. */
 
          /* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
-         look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt)) 
-                          - ehframe_image) 
-                    - cie_pointer;
+         if (for_eh)
+            look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt)) 
+                             - frame_image) 
+                       - cie_pointer;
+         else
+            look_for = cie_pointer;
 
          for (cie = 0; cie < n_CIEs; cie++) {
             if (0) VG_(printf)("look for %lld   %lld\n",
@@ -3764,8 +3789,8 @@
 	 }
 
          adi.encoding      = the_CIEs[cie].address_encoding;
-         adi.ehframe_image = ehframe_image;
-         adi.ehframe_avma  = di->ehframe_avma;
+         adi.ehframe_image = frame_image;
+         adi.ehframe_avma  = frame_avma;
          adi.text_bias     = di->text_debug_bias;
          fde_initloc = read_encoded_Addr(&nbytes, &adi, data);
          data += nbytes;
@@ -3773,8 +3798,8 @@
             VG_(printf)("fde.initloc     = %#lx\n", fde_initloc);
 
          adi.encoding      = the_CIEs[cie].address_encoding & 0xf;
-         adi.ehframe_image = ehframe_image;
-         adi.ehframe_avma  = di->ehframe_avma;
+         adi.ehframe_image = frame_image;
+         adi.ehframe_avma  = frame_avma;
          adi.text_bias     = di->text_debug_bias;
 
          /* WAS (incorrectly):
@@ -3800,7 +3825,7 @@
 
          if (di->ddump_frames)
             VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
-                        ((Addr)ciefde_start) - ((Addr)ehframe_image),
+                        ((Addr)ciefde_start) - ((Addr)frame_image),
                         (Addr)ciefde_len,
                         (Addr)(UWord)cie_pointer,
                         (Addr)look_for, 
@@ -3827,16 +3852,43 @@
             VG_(printf)("fde.ilen        = %d\n", (Int)fde_ilen);
 	 }
 
-         if (fde_ilen < 0 || fde_ilen > di->ehframe_size) {
+         if (fde_ilen < 0 || fde_ilen > frame_size) {
             how = "implausible # fde insns";
             goto bad;
          }
 
 	 data += fde_ilen;
 
+         if (ehframe_cfsis) {
+            Addr a_mid_lo, a_mid_hi;
+            Word mid, size, 
+                 lo = 0, 
+                 hi = ehframe_cfsis-1;
+            while (True) {
+               /* current unsearched space is from lo to hi, inclusive. */
+               if (lo > hi) break; /* not found */
+               mid      = (lo + hi) / 2;
+               a_mid_lo = di->cfsi[mid].base;
+               size     = di->cfsi[mid].len;
+               a_mid_hi = a_mid_lo + size - 1;
+               vg_assert(a_mid_hi >= a_mid_lo);
+               if (fde_initloc + fde_arange <= a_mid_lo) {
+                  hi = mid-1; continue;
+               }
+               if (fde_initloc > a_mid_hi) { lo = mid+1; continue; }
+               break;
+            }
+
+            /* The range this .debug_frame FDE covers has been already
+               covered in .eh_frame section.  Don't add it from .debug_frame
+               section again.  */            
+            if (lo <= hi)
+               continue;
+         }
+
          adi.encoding      = the_CIEs[cie].address_encoding;
-         adi.ehframe_image = ehframe_image;
-         adi.ehframe_avma  = di->ehframe_avma;
+         adi.ehframe_image = frame_image;
+         adi.ehframe_avma  = frame_avma;
          adi.text_bias     = di->text_debug_bias;
 
          if (di->trace_cfi)
diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c
index 174b9d2..e9ec841 100644
--- a/coregrind/m_debuginfo/readdwarf3.c
+++ b/coregrind/m_debuginfo/readdwarf3.c
@@ -2356,9 +2356,16 @@
          if (attr == DW_AT_type && ctsSzB > 0) {
             fieldE.Te.Field.typeR = (UWord)cts;
          }
-         if (attr == DW_AT_data_member_location && ctsMemSzB > 0) {
+         /* There are 2 different cases for DW_AT_data_member_location.
+            If it is a constant class attribute, it contains byte offset
+            from the beginning of the containing entity.
+            Otherwise it is a location expression.  */
+         if (attr == DW_AT_data_member_location && ctsSzB > 0) {
+            fieldE.Te.Field.nLoc = -1;
+            fieldE.Te.Field.pos.offset = cts;
+         } else if (attr == DW_AT_data_member_location && ctsMemSzB > 0) {
             fieldE.Te.Field.nLoc = (UWord)ctsMemSzB;
-            fieldE.Te.Field.loc
+            fieldE.Te.Field.pos.loc
                = ML_(dinfo_memdup)( "di.readdwarf3.ptD.member.2",
                                     (UChar*)(UWord)cts, 
                                     (SizeT)fieldE.Te.Field.nLoc );
@@ -2385,13 +2392,14 @@
       vg_assert(fieldE.Te.Field.name);
       if (fieldE.Te.Field.typeR == D3_INVALID_CUOFF)
          goto bad_DIE;
-      if (fieldE.Te.Field.loc) {
+      if (fieldE.Te.Field.nLoc) {
          if (!parent_is_struct) {
             /* If this is a union type, pretend we haven't seen the data
                member location expression, as it is by definition
                redundant (it must be zero). */
-            ML_(dinfo_free)(fieldE.Te.Field.loc);
-            fieldE.Te.Field.loc  = NULL;
+            if (fieldE.Te.Field.nLoc > 0)
+               ML_(dinfo_free)(fieldE.Te.Field.pos.loc);
+            fieldE.Te.Field.pos.loc = NULL;
             fieldE.Te.Field.nLoc = 0;
          }
          /* Record this child in the parent */
@@ -2616,10 +2624,10 @@
    /* For union members, Expr should be absent */
    if (0) VG_(printf)("YYYY Acquire Field\n");
    vg_assert(fieldE.tag == Te_Field);
-   vg_assert( (fieldE.Te.Field.nLoc > 0 && fieldE.Te.Field.loc != NULL)
-              || (fieldE.Te.Field.nLoc == 0 && fieldE.Te.Field.loc == NULL) );
+   vg_assert(fieldE.Te.Field.nLoc <= 0 || fieldE.Te.Field.pos.loc != NULL);
+   vg_assert(fieldE.Te.Field.nLoc != 0 || fieldE.Te.Field.pos.loc == NULL);
    if (fieldE.Te.Field.isStruct) {
-      vg_assert(fieldE.Te.Field.nLoc > 0);
+      vg_assert(fieldE.Te.Field.nLoc != 0);
    } else {
       vg_assert(fieldE.Te.Field.nLoc == 0);
    }
diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
index 4011852..df7bcb5 100644
--- a/coregrind/m_debuginfo/readelf.c
+++ b/coregrind/m_debuginfo/readelf.c
@@ -1691,6 +1691,7 @@
       UChar*     debug_str_img    = NULL; /* .debug_str    (dwarf2) */
       UChar*     debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
       UChar*     debug_loc_img    = NULL; /* .debug_loc    (dwarf2) */
+      UChar*     debug_frame_img  = NULL; /* .debug_frame  (dwarf2) */
       UChar*     dwarf1d_img      = NULL; /* .debug        (dwarf1) */
       UChar*     dwarf1l_img      = NULL; /* .line         (dwarf1) */
       UChar*     ehframe_img      = NULL; /* .eh_frame     (dwarf2) */
@@ -1710,6 +1711,7 @@
       SizeT      debug_str_sz    = 0;
       SizeT      debug_ranges_sz = 0;
       SizeT      debug_loc_sz    = 0;
+      SizeT      debug_frame_sz  = 0;
       SizeT      dwarf1d_sz      = 0;
       SizeT      dwarf1l_sz      = 0;
       SizeT      ehframe_sz      = 0;
@@ -1767,6 +1769,7 @@
          FIND(".debug_str",     debug_str_sz,    debug_str_img)
          FIND(".debug_ranges",  debug_ranges_sz, debug_ranges_img)
          FIND(".debug_loc",     debug_loc_sz,    debug_loc_img)
+         FIND(".debug_frame",   debug_frame_sz,  debug_frame_img)
 
          FIND(".debug",         dwarf1d_sz,      dwarf1d_img)
          FIND(".line",          dwarf1l_sz,      dwarf1l_img)
@@ -1959,6 +1962,8 @@
                FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz, 
                                                                debug_ranges_img)
                FIND(need_dwarf2, ".debug_loc",    debug_loc_sz,  debug_loc_img)
+               FIND(need_dwarf2, ".debug_frame",  debug_frame_sz,
+                                                               debug_frame_img)
                FIND(need_dwarf1, ".debug",        dwarf1d_sz,    dwarf1d_img)
                FIND(need_dwarf1, ".line",         dwarf1l_sz,    dwarf1l_img)
 
@@ -1996,10 +2001,14 @@
                          False, opd_img);
       }
 
-      /* Read .eh_frame (call-frame-info) if any */
+      /* Read .eh_frame and .debug_frame (call-frame-info) if any */
       if (ehframe_img) {
          vg_assert(ehframe_sz == di->ehframe_size);
-         ML_(read_callframe_info_dwarf3)( di, ehframe_img );
+         ML_(read_callframe_info_dwarf3)( di, ehframe_img, ehframe_sz, True );
+      }
+      if (debug_frame_sz) {
+         ML_(read_callframe_info_dwarf3)( di, debug_frame_img,
+                                          debug_frame_sz, False );
       }
 
       /* Read the stabs and/or dwarf2 debug information, if any.  It
diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
index 5e318fd..eab3280 100644
--- a/coregrind/m_debuginfo/storage.c
+++ b/coregrind/m_debuginfo/storage.c
@@ -1435,7 +1435,7 @@
    return 0;
 }
 
-static void canonicaliseCFI ( struct _DebugInfo* di )
+void ML_(canonicaliseCFI) ( struct _DebugInfo* di )
 {
    Word  i, j;
    const Addr minAvma = 0;
@@ -1528,7 +1528,7 @@
 {
    canonicaliseSymtab ( di );
    canonicaliseLoctab ( di );
-   canonicaliseCFI ( di );
+   ML_(canonicaliseCFI) ( di );
    canonicaliseVarInfo ( di );
 }
 
diff --git a/coregrind/m_debuginfo/tytypes.c b/coregrind/m_debuginfo/tytypes.c
index 4e3c9ee..46edf97 100644
--- a/coregrind/m_debuginfo/tytypes.c
+++ b/coregrind/m_debuginfo/tytypes.c
@@ -98,10 +98,15 @@
                      te->Te.Atom.value, te->Te.Atom.name);
          break;
       case Te_Field:
-         VG_(printf)("Te_Field(ty=0x%05lx,nLoc=%lu,loc=%p,\"%s\")",
-                     te->Te.Field.typeR, te->Te.Field.nLoc,
-                     te->Te.Field.loc,
-                     te->Te.Field.name ? te->Te.Field.name : (UChar*)"");
+         if (te->Te.Field.nLoc == -1)
+            VG_(printf)("Te_Field(ty=0x%05lx,pos.offset=%ld,\"%s\")",
+                        te->Te.Field.typeR, te->Te.Field.pos.offset,
+                        te->Te.Field.name ? te->Te.Field.name : (UChar*)"");
+         else
+            VG_(printf)("Te_Field(ty=0x%05lx,nLoc=%lu,pos.loc=%p,\"%s\")",
+                        te->Te.Field.typeR, te->Te.Field.nLoc,
+                        te->Te.Field.pos.loc,
+                        te->Te.Field.name ? te->Te.Field.name : (UChar*)"");
          break;
       case Te_Bound:
          VG_(printf)("Te_Bound[");
@@ -476,8 +481,11 @@
       if (r != 0) return r;
       r = UWord__cmp(te1->Te.Field.nLoc, te2->Te.Field.nLoc);
       if (r != 0) return r;
-      r = Bytevector__cmp(te1->Te.Field.loc, te2->Te.Field.loc,
-                          te1->Te.Field.nLoc);
+      if (te1->Te.Field.nLoc == -1)
+         r = Long__cmp(te1->Te.Field.pos.offset, te2->Te.Field.pos.offset);
+      else
+         r = Bytevector__cmp(te1->Te.Field.pos.loc, te2->Te.Field.pos.loc,
+                             te1->Te.Field.nLoc);
       return r;
    case Te_Bound:
       r = Bool__cmp(te1->Te.Bound.knownL, te2->Te.Bound.knownL);
@@ -568,7 +576,8 @@
          break;
       case Te_Field:
          if (te->Te.Field.name) ML_(dinfo_free)(te->Te.Field.name);
-         if (te->Te.Field.loc) ML_(dinfo_free)(te->Te.Field.loc);
+         if (te->Te.Field.nLoc > 0 && te->Te.Field.pos.loc)
+            ML_(dinfo_free)(te->Te.Field.pos.loc);
          break;
       case Te_Bound:
          break;
@@ -747,26 +756,32 @@
                field = ML_(TyEnts__index_by_cuOff)(tyents, NULL, fieldR);
                vg_assert(field);
                vg_assert(field->tag == Te_Field);
-               vg_assert(field->Te.Field.loc);
-               vg_assert(field->Te.Field.nLoc > 0);
-               /* Re data_bias in this call, we should really send in
-                  a legitimate value.  But the expression is expected
-                  to be a constant expression, evaluation of which
-                  will not need to use DW_OP_addr and hence we can
-                  avoid the trouble of plumbing the data bias through
-                  to this point (if, indeed, it has any meaning; from
-                  which DebugInfo would we take the data bias? */
-               res = ML_(evaluate_Dwarf3_Expr)(
-                       field->Te.Field.loc, field->Te.Field.nLoc,
-                       NULL/*fbGX*/, NULL/*RegSummary*/,
-                       0/*data_bias*/,
-                       True/*push_initial_zero*/);
-               if (0) {
-                  VG_(printf)("QQQ ");
-                  ML_(pp_GXResult)(res);
-                  VG_(printf)("\n");
+               vg_assert(field->Te.Field.nLoc < 0
+                         || (field->Te.Field.nLoc > 0
+                             && field->Te.Field.pos.loc));
+               if (field->Te.Field.nLoc == -1) {
+                  res.kind = GXR_Addr;
+                  res.word = field->Te.Field.pos.offset;
+               } else {
+                  /* Re data_bias in this call, we should really send in
+                     a legitimate value.  But the expression is expected
+                     to be a constant expression, evaluation of which
+                     will not need to use DW_OP_addr and hence we can
+                     avoid the trouble of plumbing the data bias through
+                     to this point (if, indeed, it has any meaning; from
+                     which DebugInfo would we take the data bias? */
+                   res =  ML_(evaluate_Dwarf3_Expr)(
+                          field->Te.Field.pos.loc, field->Te.Field.nLoc,
+                          NULL/*fbGX*/, NULL/*RegSummary*/,
+                          0/*data_bias*/,
+                          True/*push_initial_zero*/);
+                  if (0) {
+                     VG_(printf)("QQQ ");
+                     ML_(pp_GXResult)(res);
+                     VG_(printf)("\n");
+                  }
                }
-               if (res.kind != GXR_Value)
+               if (res.kind != GXR_Addr)
                   continue;
                mul = ML_(sizeOfType)( tyents, field->Te.Field.typeR );
                if (mul.b != True)