Author: sewardj
Date: 2008-02-11 02:45:30 +0000 (Mon, 11 Feb 2008)
New Revision: 7393

Log:
So far, VG_(get_data_description) tries to find the name, type and
offset of the variable associated with a data address in the global
variables and in the local variables of the topmost frame of a given
thread's stack.  This extends it so it considers all frames of the
stacks of all threads.



Modified:
   branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
   branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c
   branches/DATASYMS/coregrind/m_execontext.c
   branches/DATASYMS/coregrind/m_libcassert.c
   branches/DATASYMS/coregrind/m_machine.c
   branches/DATASYMS/coregrind/m_stacktrace.c
   branches/DATASYMS/coregrind/m_translate.c
   branches/DATASYMS/coregrind/pub_core_stacktrace.h
   branches/DATASYMS/include/pub_tool_debuginfo.h
   branches/DATASYMS/include/pub_tool_machine.h
   branches/DATASYMS/include/pub_tool_stacktrace.h
   branches/DATASYMS/massif/ms_main.c
   branches/DATASYMS/memcheck/mc_main.c


Modified: branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-10 22:41:39 UTC 
(rev 7392)
+++ branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-11 02:45:30 UTC 
(rev 7393)
@@ -37,19 +37,20 @@
 #include "pub_core_basics.h"
 #include "pub_core_vki.h"
 #include "pub_core_threadstate.h"
-#include "pub_core_debuginfo.h"   /* self */
+#include "pub_core_debuginfo.h"  /* self */
 #include "pub_core_demangle.h"
 #include "pub_core_libcbase.h"
 #include "pub_core_libcassert.h"
 #include "pub_core_libcprint.h"
 #include "pub_core_libcfile.h"
 #include "pub_core_options.h"
-#include "pub_core_redir.h"       // VG_(redir_notify_{new,delete}_SegInfo)
+#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
 #include "pub_core_aspacemgr.h"
-#include "pub_core_machine.h"     // VG_PLAT_USES_PPCTOC
+#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
 #include "pub_core_xarray.h"
 #include "pub_core_oset.h"
-#include "priv_misc.h"            /* dinfo_zalloc/free */
+#include "pub_core_stacktrace.h" // VG_(get_StackTrace)
+#include "priv_misc.h"           /* dinfo_zalloc/free */
 #include "priv_storage.h"
 #include "priv_tytypes.h"
 #include "priv_readdwarf.h"
@@ -104,6 +105,51 @@
 static DebugInfo* debugInfo_list = NULL;
 
 
+/* Find 'di' in the debugInfo_list and move it one step closer the the
+   front of the list, so as to make subsequent searches for it
+   cheaper.  When used in a controlled way, makes a major improvement
+   in some DebugInfo-search-intensive situations, most notably stack
+   unwinding on amd64-linux. */
+static void move_DebugInfo_one_step_forward ( DebugInfo* di )
+{
+   DebugInfo *di0, *di1, *di2;
+   if (di == debugInfo_list)
+      return; /* already at head of list */
+   vg_assert(di != NULL);
+   di0 = debugInfo_list;
+   di1 = NULL;
+   di2 = NULL;
+   while (True) {
+      if (di0 == NULL || di0 == di) break;
+      di2 = di1;
+      di1 = di0;
+      di0 = di0->next;
+   }
+   vg_assert(di0 == di);
+   if (di0 != NULL && di1 != NULL && di2 != NULL) {
+      DebugInfo* tmp;
+      /* di0 points to di, di1 to its predecessor, and di2 to di1's
+         predecessor.  Swap di0 and di1, that is, move di0 one step
+         closer to the start of the list. */
+      vg_assert(di2->next == di1);
+      vg_assert(di1->next == di0);
+      tmp = di0->next;
+      di2->next = di0;
+      di0->next = di1;
+      di1->next = tmp;
+   }
+   else
+   if (di0 != NULL && di1 != NULL && di2 == NULL) {
+      /* it's second in the list. */
+      vg_assert(debugInfo_list == di1);
+      vg_assert(di1->next == di0);
+      di1->next = di0->next;
+      di0->next = di1;
+      debugInfo_list = di0;
+   }
+}
+
+
 /*------------------------------------------------------------*/
 /*--- Notification (acquire/discard) helpers               ---*/
 /*------------------------------------------------------------*/
@@ -912,15 +958,15 @@
    return True;
 }
 
-/* Try to form some description of data_addr by looking at the DWARF3
-   debug info we have.  This only looks at stack locations (for the
-   top frame of the thread from which ip/sp/fp are taken) and at
-   global variables.  Result (or as much as will fit) is put into into
-   dname[0 .. n_dname-1] and is guaranteed to be zero terminated. */
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/// begin Generate data description from DWARF3 debug info
 
 /* Evaluate the location expression/list for var, to see whether or
    not data_addr falls within the variable.  If so also return the
-   offset of data_addr from the start of the variable.*/
+   offset of data_addr from the start of the variable.  Note that
+   regs, which supplies ip,sp,fp values, will be NULL for global
+   variables, and non-NULL for local variables. */
 static Bool data_address_is_in_var ( /*OUT*/UWord* offset,
                                      DiVariable*   var,
                                      RegSummary*   regs,
@@ -928,12 +974,13 @@
 {
    SizeT    var_szB;
    GXResult res;
+   Bool     show = False;
    vg_assert(var->name);
    vg_assert(var->typeV);
    vg_assert(var->gexprV);
    var_szB = ML_(sizeOfType)(var->typeV);
 
-   if (1) {
+   if (show) {
       VG_(printf)("VVVV: find loc: %s :: ", var->name );
       ML_(pp_Type_C_ishly)( var->typeV );
       VG_(printf)("\n");
@@ -941,41 +988,149 @@
 
    res = ML_(evaluate_GX)( var->gexprV, var->fbGXv, regs );
 
-   if (1) VG_(printf)("VVVV: -> 0x%lx %s\n", res.res, 
-                      res.failure ? res.failure : "(success)");
+   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 = res.res - data_addr;
+      *offset = data_addr - res.res;
       return True;
    } else {
       return False;
    }
 }
-Bool VG_(get_data_description)( Addr data_addr,
-                                Addr ip, Addr sp, Addr fp,
-                                /*OUT*/Char* dname, Int n_dname )
+
+/* Determine if data_addr is a local variable in the frame
+   characterised by (ip,sp,fp), and if so write its description into
+   dname[0..n_dname-1], and return True.  If not, return False. */
+static 
+Bool consider_vars_in_frame ( /*OUT*/Char* dname, Int n_dname,
+                              Addr data_addr,
+                              Addr ip, Addr sp, Addr fp )
 {
+   Word       i;
    DebugInfo* di;
    RegSummary regs;
-   DebugInfo* di_for_ip;
 
-   vg_assert(n_dname > 1);
-   dname[n_dname-1] = 0;
+   static UInt n_search = 0;
+   static UInt n_steps = 0;
+   n_search++;
 
-   if (0) VG_(printf)("GDnO: dataaddr %p, ip at error %p\n",
-                      data_addr, ip );
+   /* first, find the DebugInfo that pertains to 'ip'. */
+   for (di = debugInfo_list; di; di = di->next) {
+      n_steps++;
+      /* text segment missing? unlikely, but handle it .. */
+      if (di->text_size == 0)
+         continue;
+      /* Ok.  So does this text mapping bracket the ip? */
+      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
+         break;
+   }
+ 
+   /* Didn't find it.  Strange -- means ip is a code address outside
+      of any mapped text segment.  Unlikely but not impossible -- app
+      could be generating code to run. */
+   if (!di)
+      return False;
 
-   /* Loop over the DebugInfos we have.  Check data_addr against the
-      outermost scope of all of them (as that should be a global
-      scope).  Also, identify the di which contains the PC address.
-      That will be the one in which we need to look to find info on
-      nested scopes. */
+   if (0 && ((n_search & 0x1) == 0))
+      VG_(printf)("consider_vars_in_frame: %u searches, "
+                  "%u DebugInfos looked at\n", 
+                  n_search, n_steps);
+   /* Start of performance-enhancing hack: once every ??? (chosen
+      hackily after profiling) successful searches, move the found
+      DebugInfo one step closer to the start of the list.  This makes
+      future searches cheaper. */
+   if ((n_search & 0xFFFF) == 0) {
+      /* Move si one step closer to the start of the list. */
+      move_DebugInfo_one_step_forward( di );
+   }
+   /* End of performance-enhancing hack. */
 
+   /* any var info at all? */
+   if (!di->varinfo)
+      return False;
+
+   /* Work through the scopes from most deeply nested outwards,
+      looking for code address ranges that bracket 'ip'.  The
+      variables on each such address range found are in scope right
+      now.  Don't descend to level zero as that is the global
+      scope. */
    regs.ip = ip;
    regs.sp = sp;
    regs.fp = fp;
 
-   di_for_ip = NULL;
+   /* "for each scope, working outwards ..." */
+   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
+      XArray*      vars;
+      Word         j;
+      DiAddrRange* arange;
+      OSet*        this_scope 
+         = *(OSet**)VG_(indexXA)( di->varinfo, i );
+      if (!this_scope)
+         continue;
+      /* Find the set of variables in this scope that
+         bracket the program counter. */
+      arange = VG_(OSetGen_LookupWithCmp)(
+                  this_scope, &ip, 
+                  ML_(cmp_for_DiAddrRange_range)
+               );
+      if (!arange)
+         continue;
+      /* stay sane */
+      vg_assert(arange->aMin <= arange->aMax);
+      /* It must bracket the ip we asked for, else
+         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
+      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
+      /* But it mustn't cover the entire address range.  We only
+         expect that to happen for the global scope (level 0), which
+         we're not looking at here. */
+      vg_assert(! (arange->aMin == (Addr)0
+                   && arange->aMax == ~(Addr)0) );
+      vars = arange->vars;
+      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
+         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
+         SizeT       offset;
+         if (data_address_is_in_var( &offset, var, &regs, data_addr )) {
+            VG_(snprintf)(
+               dname, (SizeT)n_dname,
+               "Address 0x%lx is %lu bytes inside local var \"%s\"",
+               data_addr, offset, var->name);
+            dname[n_dname-1] = 0;
+            return True;
+         }
+      }
+   }
+
+   return False;
+}
+
+/* Try to form some description of data_addr by looking at the DWARF3
+   debug info we have.  This considers all global variables, and all
+   frames in the stacks of all threads.  Result (or as much as will
+   fit) is put into into dname[0 .. n_dname-1] and is guaranteed to be
+   zero terminated. */
+Bool VG_(get_data_description)( Addr data_addr,
+                                /*OUT*/Char* dname, Int n_dname )
+{
+#  define N_FRAMES 8
+   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
+   UInt n_frames;
+
+   Addr       stack_min, stack_max;
+   ThreadId   tid;
+   Bool       found;
+   DebugInfo* di;
+   Word       j;
+
+   vg_assert(n_dname > 1);
+   dname[n_dname-1] = 0;
+
+   if (0) VG_(printf)("GDD: dataaddr %p\n", data_addr);
+
+   /* First, see if data_addr is (or is part of) a global variable.
+      Loop over the DebugInfos we have.  Check data_addr against the
+      outermost scope of all of them, as that should be a global
+      scope. */
    for (di = debugInfo_list; di != NULL; di = di->next) {
       OSet*        global_scope;
       Int          gs_size;
@@ -987,9 +1142,6 @@
       /* text segment missing? unlikely, but handle it .. */
       if (di->text_size == 0)
          continue;
-      /* Ok.  So does this text mapping bracket the ip? */
-      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
-         di_for_ip = di;
       /* any var info at all? */
       if (!di->varinfo)
          continue;
@@ -1012,8 +1164,8 @@
          = VG_(OSetGen_Lookup)( global_scope, &zero );
       /* The global range from (Addr)0 to ~(Addr)0 must exist */
       vg_assert(global_arange);
-      vg_assert(global_arange->aMin ==  (Addr)0);
-      vg_assert(global_arange->aMax == ~(Addr)0);
+      vg_assert(global_arange->aMin == (Addr)0
+                && global_arange->aMax == ~(Addr)0);
       /* Any vars in this range? */
       if (!global_arange->vars)
          continue;
@@ -1025,7 +1177,15 @@
          SizeT offset;
          DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
          vg_assert(var->name);
-         if (data_address_is_in_var( &offset, var, &regs, data_addr )) {
+         /* Note we use a NULL RegSummary* here.  It can't make any
+            sense for a global variable to have a location expression
+            which depends on a SP/FP/IP value.  So don't supply any.
+            This means, if the evaluation of the location
+            expression/list requires a register, we have to let it
+            fail. */
+         if (data_address_is_in_var( &offset, var, 
+                                     NULL/* RegSummary* */, 
+                                     data_addr )) {
             VG_(snprintf)(
                dname, (SizeT)n_dname,
                "Address 0x%lx is %lu bytes inside global var \"%s\"",
@@ -1036,59 +1196,49 @@
       }
    }
 
-   if (0) {
-      VG_(printf)("di_for_ip %p\n", di_for_ip);
-      VG_(printf)("vi %p\n", di_for_ip->varinfo);
-      VG_(printf)("vi size %d\n", (Int)VG_(sizeXA)(di_for_ip->varinfo));
+   /* Ok, well it's not a global variable.  So now let's snoop around
+      in the stacks of all the threads.  First try to figure out which
+      thread's stack data_addr is in. */
+
+   /* Perhaps it's on a thread's stack? */
+   found = False;
+   VG_(thread_stack_reset_iter)(&tid);
+   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
+      if (stack_min >= stack_max)
+         continue; /* ignore obviously stupid cases */
+      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
+          && data_addr <= stack_max) {
+         found = True;
+         break;
+      }
    }
+   if (!found)
+      return False;
 
-   /* Now that we've considered all the globals in scope, consider the
-      locals. */
-   if (di_for_ip && di_for_ip->varinfo) {
-      Word i;
-      /* Work through the scopes from most deeply nested outwards,
-         looking for code address ranges that bracket 'ip'.  The
-         variables on each such address range found are in scope right
-         now.  Don't descend to level zero as that is the global
-         scope. */
-      /* "for each scope, working outwards ..." */
-      for (i = VG_(sizeXA)(di_for_ip->varinfo) - 1; i >= 1; i--) {
-         XArray*      vars;
-         Word         j;
-         DiAddrRange* arange;
-         OSet*        this_scope 
-            = *(OSet**)VG_(indexXA)( di_for_ip->varinfo, i );
-         if (!this_scope)
-            continue;
-         /* Find the set of variables in this scope that
-            bracket the program counter. */
-         arange = VG_(OSetGen_LookupWithCmp)(
-                     this_scope, &ip, 
-                     ML_(cmp_for_DiAddrRange_range)
-                  );
-         if (!arange)
-            continue;
-         vg_assert(arange->aMin <= ip && ip <= arange->aMax);
-         vars = arange->vars;
-         for (j = 0; j < VG_(sizeXA)( vars ); j++) {
-            DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
-            SizeT       offset;
-            if (data_address_is_in_var( &offset, var, &regs, data_addr )) {
-               VG_(snprintf)(
-                  dname, (SizeT)n_dname,
-                  "Address 0x%lx is %lu bytes inside local var \"%s\"",
-                  data_addr, offset, var->name);
-               dname[n_dname-1] = 0;
-               return True;
-            }
-         }
+   /* We conclude data_addr is in thread tid's stack.  Unwind the
+      stack to get a bunch of (ip,sp,fp) triples describing the
+      frames, and for each frame, consider the local variables. */
+
+   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
+                                   sps, fps, 0/*first_ip_delta*/ );
+   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
+   for (j = 0; j < n_frames; j++) {
+      if (consider_vars_in_frame( dname, n_dname,
+                                  data_addr,
+                                  ips[j], sps[j], fps[j] )) {
+         dname[n_dname-1] = 0;
+         return True;
       }
    }
 
    /* We didn't find anything useful. */
    return False;
+#  undef N_FRAMES
 }
 
+/// end Generate data description from DWARF3 debug info
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
 
 /* Map a code address to the name of a shared object file or the
    executable.  Returns False if no idea; otherwise True.  Doesn't
@@ -1537,37 +1687,20 @@
    if (cfsi == NULL)
       return False;
 
-   if (0 && ((n_search & 0xFFFFF) == 0))
-      VG_(printf)("%u %u\n", n_search, n_steps);
+   if (0 && ((n_search & 0x7FFFF) == 0))
+      VG_(printf)("VG_(use_CF_info): %u searches, "
+                  "%u DebugInfos looked at\n", 
+                  n_search, n_steps);
 
-   /* Start of performance-enhancing hack: once every 16 (chosen
+   /* Start of performance-enhancing hack: once every 64 (chosen
       hackily after profiling) successful searches, move the found
       DebugInfo one step closer to the start of the list.  This makes
       future searches cheaper.  For starting konqueror on amd64, this
       in fact reduces the total amount of searching done by the above
       find-the-right-DebugInfo loop by more than a factor of 20. */
-   if ((n_search & 0xF) == 0) {
+   if ((n_search & 0x3F) == 0) {
       /* Move si one step closer to the start of the list. */
-      DebugInfo* si0 = debugInfo_list;
-      DebugInfo* si1 = NULL;
-      DebugInfo* si2 = NULL;
-      DebugInfo* tmp;
-      while (True) {
-         if (si0 == NULL) break;
-         if (si0 == si) break;
-         si2 = si1;
-         si1 = si0;
-         si0 = si0->next;
-      }
-      if (si0 == si && si0 != NULL && si1 != NULL && si2 != NULL) {
-         /* si0 points to si, si1 to its predecessor, and si2 to si1's
-            predecessor.  Swap si0 and si1, that is, move si0 one step
-            closer to the start of the list. */
-         tmp = si0->next;
-         si2->next = si0;
-         si0->next = si1;
-         si1->next = tmp;
-      }
+      move_DebugInfo_one_step_forward( si );
    }
    /* End of performance-enhancing hack. */
 

Modified: branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c        2008-02-10 
22:41:39 UTC (rev 7392)
+++ branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c        2008-02-11 
02:45:30 UTC (rev 7393)
@@ -480,12 +480,13 @@
    and {FP,SP}_REG decls */
 static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, RegSummary* regs )
 {
+   vg_assert(regs);
 #  if defined(VGP_amd64_linux)
-   if (regno == 6) { *a = regs->fp; return True; }
-   if (regno == 7) { *a = regs->sp; return True; }
+   if (regno == 6/*RBP*/) { *a = regs->fp; return True; }
+   if (regno == 7/*RSP*/) { *a = regs->sp; return True; }
 #  elif defined(VGP_x86_linux)
-   if (regno == 5) { *a = regs->fp; return True; }
-   if (regno == 4) { *a = regs->sp; return True; }
+   if (regno == 5/*EBP*/) { *a = regs->fp; return True; }
+   if (regno == 4/*ESP*/) { *a = regs->sp; return True; }
 #  else
 #    error "Unknown platform"
 #  endif
@@ -499,30 +500,30 @@
 {
 #  define N_EXPR_STACK 20
 
-#  define FAIL(_str)                                       \
-      do {                                                 \
-         GXResult res;                                     \
-         res.res = 0;                                      \
-         res.failure = (_str);                             \
-         return res;                                       \
+#  define FAIL(_str)                                          \
+      do {                                                    \
+         GXResult res;                                        \
+         res.res = 0;                                         \
+         res.failure = (_str);                                \
+         return res;                                          \
       } while (0)
 
-#  define PUSH(_arg)                                       \
-      do {                                                 \
-         vg_assert(sp >= -1 && sp < N_EXPR_STACK);         \
-         if (sp == N_EXPR_STACK-1)                         \
+#  define PUSH(_arg)                                          \
+      do {                                                    \
+         vg_assert(sp >= -1 && sp < N_EXPR_STACK);            \
+         if (sp == N_EXPR_STACK-1)                            \
             FAIL("evaluate_Dwarf3_Expr: stack overflow(1)");  \
-         sp++;                                             \
-         stack[sp] = (_arg);                               \
+         sp++;                                                \
+         stack[sp] = (_arg);                                  \
       } while (0)
 
-#  define POP(_lval)                                       \
-      do {                                                 \
-         vg_assert(sp >= -1 && sp < N_EXPR_STACK);         \
-         if (sp == -1)                                     \
+#  define POP(_lval)                                          \
+      do {                                                    \
+         vg_assert(sp >= -1 && sp < N_EXPR_STACK);            \
+         if (sp == -1)                                        \
             FAIL("evaluate_Dwarf3_Expr: stack underflow(1)"); \
-         _lval = stack[sp];                                \
-         sp--;                                             \
+         _lval = stack[sp];                                   \
+         sp--;                                                \
       } while (0)
 
    UChar    opcode;
@@ -574,6 +575,8 @@
             PUSH( fbval.res + sw1 );
             break;
          case DW_OP_breg0 ... DW_OP_breg31:
+            if (!regs)
+               FAIL("evaluate_Dwarf3_Expr: DW_OP_breg* but no reg info");
             a1 = 0;
             if (!get_Dwarf_Reg( &a1, opcode - DW_OP_breg0, regs ))
                FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_breg*");
@@ -605,14 +608,19 @@
 #  undef N_EXPR_STACK
 }
 
-/* Evaluate a guarded expression, using 'ip' to select which of the
-   embedded DWARF3 location expressions to use. */
+/* Evaluate a guarded expression, using regs->ip to select which of
+   the embedded DWARF3 location expressions to use.  If regs is NULL,
+   then we assume (and check) that there is only one guard and that it
+   covers the entire address range, i.o.w. that there's only one guard
+   and it always evaluates to True, so we don't need to know
+   regs->ip. */
 GXResult ML_(evaluate_GX)( GExpr* gx, GExpr* fbGX, RegSummary* regs )
 {
    GXResult res;
    Addr     aMin, aMax;
    UChar    uc;
    UShort   nbytes;
+   UWord    nGuards = 0;
    UChar* p = &gx->payload[0];
    uc = *p++; /*biasMe*/
    vg_assert(uc == 0 || uc == 1);
@@ -631,9 +639,22 @@
       aMin   = * (Addr*)p;   p += sizeof(Addr);
       aMax   = * (Addr*)p;   p += sizeof(Addr);
       nbytes = * (UShort*)p; p += sizeof(UShort);
-      if (aMin <= regs->ip && regs->ip <= aMax) {
-         /* found a matching range.  Evaluate the expression. */
-         return evaluate_Dwarf3_Expr( p, (UWord)nbytes, fbGX, regs );
+      nGuards++;
+      if (regs == NULL) {
+         vg_assert(aMin == (Addr)0);
+         vg_assert(aMax == ~(Addr)0);
+         /* Assert this is the first guard. */
+         vg_assert(nGuards == 1);
+         res = evaluate_Dwarf3_Expr( p, (UWord)nbytes, fbGX, regs );
+         /* Now check there are no more guards. */
+         p += (UWord)nbytes;
+         vg_assert(*p == 1); /*isEnd*/
+         return res;
+      } else {
+         if (aMin <= regs->ip && regs->ip <= aMax) {
+            /* found a matching range.  Evaluate the expression. */
+            return evaluate_Dwarf3_Expr( p, (UWord)nbytes, fbGX, regs );
+         }
       }
       /* else keep searching */
       p += (UWord)nbytes;

Modified: branches/DATASYMS/coregrind/m_execontext.c
===================================================================
--- branches/DATASYMS/coregrind/m_execontext.c  2008-02-10 22:41:39 UTC (rev 
7392)
+++ branches/DATASYMS/coregrind/m_execontext.c  2008-02-11 02:45:30 UTC (rev 
7393)
@@ -307,6 +307,8 @@
       ips[0] = VG_(get_IP)(tid);
    } else {
       n_ips = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size),
+                                   NULL/*array to dump SP values in*/,
+                                   NULL/*array to dump FP values in*/,
                                    first_ip_delta );
    }
 

Modified: branches/DATASYMS/coregrind/m_libcassert.c
===================================================================
--- branches/DATASYMS/coregrind/m_libcassert.c  2008-02-10 22:41:39 UTC (rev 
7392)
+++ branches/DATASYMS/coregrind/m_libcassert.c  2008-02-11 02:45:30 UTC (rev 
7393)
@@ -142,8 +142,13 @@
  
    stacktop = tst->os_state.valgrind_stack_init_SP;
  
-   VG_(get_StackTrace2)(0/*tid is unknown*/, 
-                        ips, BACKTRACE_DEPTH, ip, sp, fp, lr, sp, stacktop);
+   VG_(get_StackTrace_wrk)(
+      0/*tid is unknown*/, 
+      ips, BACKTRACE_DEPTH, 
+      NULL/*array to dump SP values in*/,
+      NULL/*array to dump FP values in*/,
+      ip, sp, fp, lr, sp, stacktop
+   );
    VG_(pp_StackTrace)  (ips, BACKTRACE_DEPTH);
  
    VG_(show_sched_status)();

Modified: branches/DATASYMS/coregrind/m_machine.c
===================================================================
--- branches/DATASYMS/coregrind/m_machine.c     2008-02-10 22:41:39 UTC (rev 
7392)
+++ branches/DATASYMS/coregrind/m_machine.c     2008-02-11 02:45:30 UTC (rev 
7393)
@@ -193,22 +193,23 @@
    }
 }
 
-static ThreadId thread_stack_iter = VG_INVALID_THREADID;
-
-void VG_(thread_stack_reset_iter)(void)
+void VG_(thread_stack_reset_iter)(/*OUT*/ThreadId* tid)
 {
-   thread_stack_iter = 1;
+   *tid = (ThreadId)(-1);
 }
 
-Bool VG_(thread_stack_next)(ThreadId* tid, Addr* stack_min, Addr* stack_max)
+Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
+                            /*OUT*/Addr* stack_min, 
+                            /*OUT*/Addr* stack_max)
 {
    ThreadId i;
-   for (i = thread_stack_iter; i < VG_N_THREADS; i++) {
+   for (i = (*tid)+1; i < VG_N_THREADS; i++) {
+      if (i == VG_INVALID_THREADID)
+         continue;
       if (VG_(threads)[i].status != VgTs_Empty) {
          *tid       = i;
          *stack_min = VG_(get_SP)(i);
          *stack_max = VG_(threads)[i].client_stack_highest_word;
-         thread_stack_iter = i + 1;
          return True;
       }
    }

Modified: branches/DATASYMS/coregrind/m_stacktrace.c
===================================================================
--- branches/DATASYMS/coregrind/m_stacktrace.c  2008-02-10 22:41:39 UTC (rev 
7392)
+++ branches/DATASYMS/coregrind/m_stacktrace.c  2008-02-11 02:45:30 UTC (rev 
7393)
@@ -56,10 +56,11 @@
    first parameter, else send zero.  This helps generate better stack
    traces on ppc64-linux and has no effect on other platforms.
 */
-UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
-                            Addr* ips, UInt n_ips, 
-                            Addr ip, Addr sp, Addr fp, Addr lr,
-                            Addr fp_min, Addr fp_max_orig )
+UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
+                               /*OUT*/Addr* ips, UInt n_ips,
+                               /*OUT*/Addr* sps, /*OUT*/Addr* fps,
+                               Addr ip, Addr sp, Addr fp, Addr lr,
+                               Addr fp_min, Addr fp_max_orig )
 {
 #  if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
                                || defined(VGP_ppc32_aix5) \
@@ -91,7 +92,8 @@
    fp_max -= sizeof(Addr);
 
    if (debug)
-      VG_(printf)("n_ips=%d fp_min=%p fp_max_orig=%p, fp_max=%p ip=%p fp=%p\n",
+      VG_(printf)("n_ips=%d fp_min=%p fp_max_orig=%p, "
+                  "fp_max=%p ip=%p fp=%p\n",
                  n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
 
    /* Assertion broken before main() is reached in pthreaded programs;  the
@@ -115,6 +117,8 @@
 
    /* fp is %ebp.  sp is %esp.  ip is %eip. */
 
+   if (sps) sps[0] = sp;
+   if (fps) fps[0] = fp;
    ips[0] = ip;
    i = 1;
 
@@ -154,6 +158,8 @@
          sp = fp + sizeof(Addr) /*saved %ebp*/ 
                  + sizeof(Addr) /*ra*/;
          fp = (((UWord*)fp)[0]);
+         if (sps) sps[i] = sp;
+         if (fps) fps[i] = fp;
          ips[i++] = ip;
          if (debug)
             VG_(printf)("     ipsF[%d]=0x%08lx\n", i-1, ips[i-1]);
@@ -164,6 +170,8 @@
       /* That didn't work out, so see if there is any CF info to hand
          which can be used. */
       if ( VG_(use_CF_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
+         if (sps) sps[i] = sp;
+         if (fps) fps[i] = fp;
          ips[i++] = ip;
          if (debug)
             VG_(printf)("     ipsC[%d]=0x%08lx\n", i-1, ips[i-1]);
@@ -182,6 +190,8 @@
    /* fp is %rbp.  sp is %rsp.  ip is %rip. */
 
    ips[0] = ip;
+   if (sps) sps[0] = sp;
+   if (fps) fps[0] = fp;
    i = 1;
 
    /* Loop unwinding the stack. Note that the IP value we get on
@@ -210,6 +220,8 @@
       /* First off, see if there is any CFI info to hand which can
          be used. */
       if ( VG_(use_CF_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
+         if (sps) sps[i] = sp;
+         if (fps) fps[i] = fp;
          ips[i++] = ip;
          if (debug)
             VG_(printf)("     ipsC[%d]=%08p\n", i-1, ips[i-1]);
@@ -231,6 +243,8 @@
          sp = fp + sizeof(Addr) /*saved %rbp*/ 
                  + sizeof(Addr) /*ra*/;
          fp = (((UWord*)fp)[0]);
+         if (sps) sps[i] = sp;
+         if (fps) fps[i] = fp;
          ips[i++] = ip;
          if (debug)
             VG_(printf)("     ipsF[%d]=%08p\n", i-1, ips[i-1]);
@@ -252,6 +266,8 @@
       */
       if (fp_min <= sp && sp < fp_max) {
          ip = ((UWord*)sp)[0];
+         if (sps) sps[i] = sp;
+         if (fps) fps[i] = fp;
          ips[i++] = ip;
          if (debug)
             VG_(printf)("     ipsH[%d]=%08p\n", i-1, ips[i-1]);
@@ -314,6 +330,8 @@
 #     undef M_VG_ERRTXT
    }
 
+   if (sps) sps[0] = sp;
+   if (fps) fps[0] = fp;
    ips[0] = ip;
    i = 1;
 
@@ -360,7 +378,8 @@
                used by the unwinding so far with 'redirs_used'. */
             if (ip == (Addr)&VG_(ppctoc_magic_redirect_return_stub)
                 && VG_(is_valid_tid)(tid_if_known)) {
-               Word hsp = VG_(threads)[tid_if_known].arch.vex.guest_REDIR_SP;
+               Word hsp = VG_(threads)[tid_if_known]
+                             .arch.vex.guest_REDIR_SP;
                hsp -= 2 * redirs_used;
                redirs_used ++;
                if (hsp >= 1 && hsp < redir_stack_size)
@@ -370,6 +389,8 @@
 #           endif
 
             fp = (((UWord*)fp)[0]);
+            if (sps) sps[i] = sp;
+            if (fps) fps[i] = fp;
             ips[i++] = ip;
             if (debug)
                VG_(printf)("     ipsF[%d]=%08p\n", i-1, ips[i-1]);
@@ -389,7 +410,10 @@
    return n_found;
 }
 
-UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips, 
+UInt VG_(get_StackTrace) ( ThreadId tid, 
+                           /*OUT*/StackTrace ips, UInt n_ips,
+                           /*OUT*/StackTrace sps,
+                           /*OUT*/StackTrace fps,
                            Word first_ip_delta )
 {
    /* thread in thread table */
@@ -431,11 +455,14 @@
    ip += first_ip_delta;
 
    if (0)
-      VG_(printf)("tid %d: stack_highest=0x%08lx ip=0x%08lx sp=0x%08lx 
fp=0x%08lx\n",
+      VG_(printf)("tid %d: stack_highest=0x%08lx ip=0x%08lx "
+                  "sp=0x%08lx fp=0x%08lx\n",
                  tid, stack_highest_word, ip, sp, fp);
 
-   return VG_(get_StackTrace2)(tid, ips, n_ips, ip, sp, fp, lr, sp, 
-                                    stack_highest_word);
+   return VG_(get_StackTrace_wrk)(tid, ips, n_ips, 
+                                       sps, fps,
+                                       ip, sp, fp, lr, sp, 
+                                       stack_highest_word);
 }
 
 static void printIpDesc(UInt n, Addr ip)
@@ -471,8 +498,11 @@
 void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt n_ips )
 {
    Addr ips[n_ips];
-   UInt n_ips_obtained = VG_(get_StackTrace)(tid, ips, n_ips,
-                                             0/*first_ip_delta*/);
+   UInt n_ips_obtained 
+      = VG_(get_StackTrace)(tid, ips, n_ips,
+                            NULL/*array to dump SP values in*/,
+                            NULL/*array to dump FP values in*/,
+                            0/*first_ip_delta*/);
    VG_(pp_StackTrace)(ips, n_ips_obtained);
 }
 

Modified: branches/DATASYMS/coregrind/m_translate.c
===================================================================
--- branches/DATASYMS/coregrind/m_translate.c   2008-02-10 22:41:39 UTC (rev 
7392)
+++ branches/DATASYMS/coregrind/m_translate.c   2008-02-11 02:45:30 UTC (rev 
7393)
@@ -1011,9 +1011,9 @@
    wrapped/redirected function to lead to our magic return stub, which
    restores LR and R2 from said stack and returns for real.
 
-   VG_(get_StackTrace2) understands that the LR value may point to the
-   return stub address, and that in that case it can get the real LR
-   value from the hidden stack instead. */
+   VG_(get_StackTrace_wrk) understands that the LR value may point to
+   the return stub address, and that in that case it can get the real
+   LR value from the hidden stack instead. */
 static 
 Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
 {

Modified: branches/DATASYMS/coregrind/pub_core_stacktrace.h
===================================================================
--- branches/DATASYMS/coregrind/pub_core_stacktrace.h   2008-02-10 22:41:39 UTC 
(rev 7392)
+++ branches/DATASYMS/coregrind/pub_core_stacktrace.h   2008-02-11 02:45:30 UTC 
(rev 7393)
@@ -38,16 +38,24 @@
 
 #include "pub_tool_stacktrace.h"
 
-// Variant that gives a little more control over the stack-walking.
+// Variant that gives a little more control over the stack-walking
+// (this is the "worker" function that actually does the walking).
 // If you know what the thread ID for this stack is, send that
 // as the first parameter, else send zero.  This helps generate
 // better stack traces on ppc64-linux and has no effect on other
 // platforms.
-extern UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
-                                   StackTrace ips, UInt n_ips, 
-                                   Addr ip, Addr sp, Addr fp, Addr lr,
-                                   Addr fp_min, Addr fp_max );
+//
+// The acquired IP values are placed in
+// ips[0 .. min(n_ips,return_value)].  If sps and fps are non-NULL,
+// the corresponding frame-pointer and stack-pointer values for each
+// frame are stored there.
 
+UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
+                               /*OUT*/Addr* ips, UInt n_ips,
+                               /*OUT*/Addr* sps, /*OUT*/Addr* fps,
+                               Addr ip, Addr sp, Addr fp, Addr lr,
+                               Addr fp_min, Addr fp_max_orig );
+
 #endif   // __PUB_CORE_STACKTRACE_H
 
 /*--------------------------------------------------------------------*/

Modified: branches/DATASYMS/include/pub_tool_debuginfo.h
===================================================================
--- branches/DATASYMS/include/pub_tool_debuginfo.h      2008-02-10 22:41:39 UTC 
(rev 7392)
+++ branches/DATASYMS/include/pub_tool_debuginfo.h      2008-02-11 02:45:30 UTC 
(rev 7393)
@@ -83,12 +83,11 @@
                                          /*OUT*/OffT* offset );
 
 /* Try to form some description of data_addr by looking at the DWARF3
-   debug info we have.  This only looks at stack locations (for the
-   top frame of the thread from which ip/sp/fp are taken) and at
-   global variables.  Result (or as much as will fit) is put into into
-   dname[0 .. n_dname-1] and is guaranteed to be zero terminated. */
+   debug info we have.  This considers all global variables, and all
+   frames in the stacks of all threads.  Result (or as much as will
+   fit) is put into into dname[0 .. n_dname-1] and is guaranteed to be
+   zero terminated. */
 extern Bool VG_(get_data_description)( Addr data_addr,
-                                       Addr ip, Addr sp, Addr fp,
                                        /*OUT*/Char* dname, Int n_dname );
 
 /* Succeeds if the address is within a shared object or the main executable.

Modified: branches/DATASYMS/include/pub_tool_machine.h
===================================================================
--- branches/DATASYMS/include/pub_tool_machine.h        2008-02-10 22:41:39 UTC 
(rev 7392)
+++ branches/DATASYMS/include/pub_tool_machine.h        2008-02-11 02:45:30 UTC 
(rev 7393)
@@ -94,11 +94,13 @@
 // doing leak checking.
 extern void VG_(apply_to_GP_regs)(void (*f)(UWord val));
 
-// This iterator lets you inspect each live thread's stack bounds.  The
-// params are all 'out' params.  Returns False at the end.
-extern void VG_(thread_stack_reset_iter) ( void );
-extern Bool VG_(thread_stack_next)       ( ThreadId* tid, Addr* stack_min,
-                                                          Addr* stack_max );
+// This iterator lets you inspect each live thread's stack bounds.
+// Returns False at the end.  'tid' is the iterator and you can only
+// safely change it by making calls to these functions.
+extern void VG_(thread_stack_reset_iter) ( /*OUT*/ThreadId* tid );
+extern Bool VG_(thread_stack_next)       ( /*MOD*/ThreadId* tid,
+                                           /*OUT*/Addr* stack_min, 
+                                           /*OUT*/Addr* stack_max );
 
 // Returns .client_stack_highest_word for the given thread
 extern Addr VG_(thread_get_stack_max) ( ThreadId tid );

Modified: branches/DATASYMS/include/pub_tool_stacktrace.h
===================================================================
--- branches/DATASYMS/include/pub_tool_stacktrace.h     2008-02-10 22:41:39 UTC 
(rev 7392)
+++ branches/DATASYMS/include/pub_tool_stacktrace.h     2008-02-11 02:45:30 UTC 
(rev 7393)
@@ -34,13 +34,20 @@
 // The basic stack trace type:  just an array of code addresses.
 typedef Addr* StackTrace;
 
-// Walks the stack to get instruction pointers from the top stack frames for
-// thread 'tid'.  Maximum of 'n_ips' addresses put into 'ips';  0 is the top
-// of the stack, 1 is its caller, etc.  Everything from ips[n_ips] onwards
-// is undefined and should not be read.  The initial IP value to 
-// use is adjusted by first_ip_delta before the stack is unwound.
-// A safe value to pass is zero.
-extern UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips,
+// Walks the stack to get instruction pointers from the top stack frames 
+// for thread 'tid'.  Maximum of 'n_ips' addresses put into 'ips';
+// 0 is the top of the stack, 1 is its caller, etc.  Everything from
+// ips[return_value] onwards is undefined and should not be read.
+// The initial IP value to use is adjusted by first_ip_delta before
+// the stack is unwound. A safe value to pass is zero.
+//
+// If sps and fps are non-NULL, the corresponding frame-pointer and
+// stack-pointer values for each frame are stored there.
+
+extern UInt VG_(get_StackTrace) ( ThreadId tid, 
+                                  /*OUT*/StackTrace ips, UInt n_ips,
+                                  /*OUT*/StackTrace sps,
+                                  /*OUT*/StackTrace fps,
                                   Word first_ip_delta );
 
 // Apply a function to every element in the StackTrace.  The parameter 'n'

Modified: branches/DATASYMS/massif/ms_main.c
===================================================================
--- branches/DATASYMS/massif/ms_main.c  2008-02-10 22:41:39 UTC (rev 7392)
+++ branches/DATASYMS/massif/ms_main.c  2008-02-11 02:45:30 UTC (rev 7393)
@@ -809,7 +809,9 @@
 
       // Ask for more IPs than clo_depth suggests we need.
       n_ips = VG_(get_StackTrace)( tid, ips, clo_depth + overestimate,
-                                        0/*first_ip_delta*/ );
+                                   NULL/*array to dump SP values in*/,
+                                   NULL/*array to dump FP values in*/,
+                                   0/*first_ip_delta*/ );
       tl_assert(n_ips > 0);
 
       // If the original stack trace is smaller than asked-for, redo=False.

Modified: branches/DATASYMS/memcheck/mc_main.c
===================================================================
--- branches/DATASYMS/memcheck/mc_main.c        2008-02-10 22:41:39 UTC (rev 
7392)
+++ branches/DATASYMS/memcheck/mc_main.c        2008-02-11 02:45:30 UTC (rev 
7393)
@@ -3371,6 +3371,7 @@
 /* Describe an address as best you can, for error messages,
    putting the result in ai. */
 static void describe_addr ( Addr a, 
+                            /* FIXME: get rid of the next 3 args */
                             Addr ip_at_error,
                             Addr sp_at_error,
                             Addr fp_at_error,
@@ -3418,7 +3419,7 @@
    VG_(memset)( &ai->Addr.Variable.descr, 
                 0, sizeof(ai->Addr.Variable.descr));
    if (VG_(get_data_description)(
-             a, ip_at_error, sp_at_error, fp_at_error,
+             a,
              &ai->Addr.Variable.descr[0],
              sizeof(ai->Addr.Variable.descr)-1 )) {
       ai->tag = Addr_Variable;
@@ -3440,9 +3441,9 @@
       return;
    }
    /* Perhaps it's on a thread's stack? */
-   VG_(thread_stack_reset_iter)();
+   VG_(thread_stack_reset_iter)(&tid);
    while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
-      if (stack_min <= a && a <= stack_max) {
+      if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
          ai->tag            = Addr_Stack;
          ai->Addr.Stack.tid = tid;
          return;


-------------------------------------------------------------------------
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
Valgrind-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-developers

Reply via email to