look like that much, but it's a good first step; there's more to come.
- vg_errcontext.c:gen_suppressions() and vg_symtab2.c:VG_(mini_stack_dump)()
had very similar stack-trace-traversing loops. I factored these out into
the higher-order function VG_(apply_ExeContext)(). I put this into
vg_execontext.c, which is the obvious spot. This is good because before
this change we had two functions, neither in vg_execontext.c, which were
crawling all over ExeContexts -- they shouldn't have to do that.
- Removed VG_(mini_stack_dump)(), which was almost identical to
VG_(pp_ExeContext)().
- Removed dead function VG_(get_EIP_from_ExeContext)().
- Replaced a call to VG_(get_ExeContext2)() with the simpler
VG_(get_ExeContext)() in vg_scheduler.c.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3394
extern ExeContext* VG_(get_ExeContext2) ( Addr ip, Addr fp,
Addr fp_min, Addr fp_max );
-
/* ---------------------------------------------------------------------
Exports of vg_errcontext.c.
------------------------------------------------------------------ */
typedef struct _CodeRedirect CodeRedirect;
extern Bool VG_(is_object_file) ( const void *hdr );
-extern void VG_(mini_stack_dump) ( Addr ips[], UInt n_ips );
extern SegInfo * VG_(read_seg_symbols) ( Segment *seg );
extern void VG_(symtab_incref) ( SegInfo * );
extern void VG_(symtab_decref) ( SegInfo *, Addr a );
vg_assert( tid < VG_N_THREADS );
}
-static void gen_suppression(Error* err)
+static void printSuppForIp(UInt n, Addr ip)
{
- Int i;
static UChar buf[M_VG_ERRTXT];
- Bool main_done = False;
+
+ if ( VG_(get_fnname_nodemangle) (ip, buf, M_VG_ERRTXT) ) {
+ VG_(printf)(" fun:%s\n", buf);
+ } else if ( VG_(get_objname)(ip, buf+7, M_VG_ERRTXT-7) ) {
+ VG_(printf)(" obj:%s\n", buf);
+ } else {
+ VG_(printf)(" ???:??? "
+ "# unknown, suppression will not work, sorry\n");
+ }
+}
+
+static void gen_suppression(Error* err)
+{
ExeContext* ec = VG_(get_error_where)(err);
Int stop_at = VG_(clo_backtrace_size);
TL_(print_extra_suppression_info)(err);
}
- /* This loop condensed from VG_(mini_stack_dump)() */
- i = 0;
- do {
- Addr eip = ec->ips[i];
- if (i > 0)
- eip -= MIN_INSTR_SIZE; // point to calling line
- if ( VG_(get_fnname_nodemangle) (eip, buf, M_VG_ERRTXT) ) {
- // Stop after "main"; if main() is recursive, stop after last main().
-
- if ( ! VG_(clo_show_below_main)) {
- if (VG_STREQ(buf, "main"))
- main_done = True;
- else if (main_done)
- break;
- }
- VG_(printf)(" fun:%s\n", buf);
- } else if ( VG_(get_objname)(eip, buf, M_VG_ERRTXT) ) {
- VG_(printf)(" obj:%s\n", buf);
- } else {
- VG_(printf)(" ???:??? "
- "# unknown, suppression will not work, sorry\n");
- }
- i++;
- } while (i < stop_at && ec->ips[i] != 0);
+ // Print stack trace elements
+ VG_(apply_ExeContext)(printSuppForIp, ec, stop_at);
VG_(printf)("}\n");
}
}
+static void printIpDesc(UInt n, Addr ip)
+{
+ static UChar buf[M_VG_ERRTXT];
+
+ VG_(describe_eip)(ip, buf, M_VG_ERRTXT);
+ VG_(message)(Vg_UserMsg, " %s %s", ( n == 0 ? "at" : "by" ), buf);
+}
+
/* Print an ExeContext. */
-void VG_(pp_ExeContext) ( ExeContext* e )
+void VG_(pp_ExeContext) ( ExeContext* ec )
{
- init_ExeContext_storage();
- VG_(mini_stack_dump) ( e->ips, VG_(clo_backtrace_size) );
+ vg_assert( VG_(clo_backtrace_size) > 0 );
+ VG_(apply_ExeContext)( printIpDesc, ec, VG_(clo_backtrace_size) );
}
}
+void VG_(apply_ExeContext)( void(*action)(UInt n, Addr ip),
+ ExeContext* ec, UInt n_ips )
+{
+ #define MYBUF_LEN 10 // only needs to be long enough for "main"
+
+ Bool main_done = False;
+ Char mybuf[MYBUF_LEN]; // ok to stack allocate mybuf[] -- it's tiny
+ Int i = 0;
+
+ vg_assert(n_ips > 0);
+ do {
+ Addr ip = ec->ips[i];
+ if (i > 0)
+ ip -= MIN_INSTR_SIZE; // point to calling line
+
+ // Stop after "main"; if main() is recursive, stop after last main().
+ if ( ! VG_(clo_show_below_main)) {
+ VG_(get_fnname_nodemangle)( ip, mybuf, MYBUF_LEN );
+ if ( VG_STREQ("main", mybuf) )
+ main_done = True;
+ else if (main_done)
+ break;
+ }
+
+ // Act on the ip
+ action(i, ip);
+
+ i++;
+ } while (i < n_ips && ec->ips[i] != 0);
+
+ #undef MYBUF_LEN
+}
+
+
/* Take a snapshot of the client's stack, putting the up to 'n_ips' IPs
into 'ips'. In order to be thread-safe, we pass in the thread's IP
and FP. Returns number of IPs put in 'ips'. */
}
-Addr VG_(get_EIP_from_ExeContext) ( ExeContext* e, UInt n )
-{
- if (n > VG_(clo_backtrace_size)) return 0;
- return e->ips[n];
-}
-
Addr VG_(get_EIP) ( ThreadId tid )
{
return INSTR_PTR(VG_(threads)[ tid ].arch);
for (i = 1; i < VG_N_THREADS; i++) {
if (VG_(threads)[i].status == VgTs_Empty) continue;
VG_(printf)("\nThread %d: status = %s\n", i, name_of_thread_state(VG_(threads)[i].status));
- VG_(pp_ExeContext)(
- VG_(get_ExeContext2)( INSTR_PTR(VG_(threads)[i].arch),
- FRAME_PTR(VG_(threads)[i].arch),
- STACK_PTR(VG_(threads)[i].arch),
- VG_(threads)[i].stack_highest_word)
- );
+ VG_(pp_ExeContext)( VG_(get_ExeContext)( i ) );
}
VG_(printf)("\n");
}
ExeContext *e = VG_(get_ExeContext)( tid );
int count =
VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], (void*)arg[2] );
- VG_(mini_stack_dump)(e->ips, VG_(clo_backtrace_size));
+ VG_(pp_ExeContext)(e);
SET_CLREQ_RETVAL( tid, count );
break; }
#undef APPEND
}
-/* Print a mini stack dump, showing the current location. */
-void VG_(mini_stack_dump) ( Addr eips[], UInt n_eips )
-{
- UInt i;
- static UChar buf[M_VG_ERRTXT];
- Bool main_done = False;
-
- Int stop_at = n_eips;
-
- vg_assert(stop_at > 0);
-
- /* This loop is the basis for the one in VG_(gen_suppressions)(); if you
- change this, change it too! */
- i = 0;
- do {
- Addr eip = eips[i];
- if (i > 0)
- eip -= MIN_INSTR_SIZE; // point to calling line
- VG_(describe_eip)(eip, buf, M_VG_ERRTXT);
-
- if ( ! VG_(clo_show_below_main)) {
- // Stop after "main"; if main() is recursive, stop after last main().
- if (VG_(strstr)(buf, " main ("))
- main_done = True;
- else if (main_done)
- break;
- }
- VG_(message)(Vg_UserMsg, " %s %s", ( i == 0 ? "at" : "by" ), buf);
- i++;
-
- } while (i < (UInt)stop_at && eips[i] != 0);
-}
-
-
/*------------------------------------------------------------*/
/*--- SegInfo accessor functions ---*/
/*------------------------------------------------------------*/
*/
extern ExeContext* VG_(get_ExeContext) ( ThreadId tid );
-/* Get the nth IP from the ExeContext. 0 is the IP of the top function, 1
- is its caller, etc. Returns 0 if there isn't one, or if n is greater
- than VG_(clo_backtrace_size), set by the --num-callers option. */
-extern Addr VG_(get_EIP_from_ExeContext) ( ExeContext* e, UInt n );
+/* Apply a function to every element in the ExeContext. The parameter 'n'
+ gives the index of the passed ip. Doesn't go below main() unless
+ --show-below-main=yes is set. */
+extern void VG_(apply_ExeContext)( void(*action)(UInt n, Addr ip),
+ ExeContext* ec, UInt n_ips );
/* Just grab the client's IP, as a much smaller and cheaper
indication of where they are. Use is basically same as for
caller, etc. */
extern UInt VG_(stack_snapshot) ( ThreadId tid, Addr* ips, UInt n_ips );
-/* Does the same thing as VG_(pp_ExeContext)(), just with slightly
- different input. */
-extern void VG_(mini_stack_dump) ( Addr ips[], UInt n_ips );
-
-
/*====================================================================*/
/*=== Error reporting ===*/
/*====================================================================*/