noinst_HEADERS = \
core.h \
core_asm.h \
+ pub_core_execontext.h \
+ pub_core_stacktrace.h \
ume.h \
vg_symtab2.h \
vg_symtypes.h \
valgrind_LDADD=
stage2_SOURCES = \
+ execontext.c \
+ stacktrace.c \
ume.c \
\
vg_scheduler.c \
vg_default.c \
vg_demangle.c \
vg_errcontext.c \
- vg_execontext.c \
vg_hashtable.c \
vg_instrument.c \
vg_main.c \
// eg. x86-linux/core_platform.h
#include "core_os.h" // OS-specific stuff, eg. linux/core_os.h
+#include "pub_core_stacktrace.h" // for type 'StackTrace'
+
#include "valgrind.h"
#undef TL_
__attribute__ ((__noreturn__))
extern void VG_(core_panic) ( Char* str );
__attribute__ ((__noreturn__))
-extern void VG_(core_panic_at) ( Char* str, ExeContext *ec );
+extern void VG_(core_panic_at) ( Char* str, StackTrace ips );
/* Tools use VG_(strdup)() which doesn't expose ArenaId */
extern Char* VG_(arena_strdup) ( ArenaId aid, const Char* s);
Bool debugging_translation,
Int debugging_verbosity );
-/* ---------------------------------------------------------------------
- Exports of vg_execontext.c.
- ------------------------------------------------------------------ */
-
-/* Records the PC and a bit of the call chain. The first 4 IP
- values are used in comparisons do remove duplicate errors, and for
- comparing against suppression specifications. The rest are purely
- informational (but often important). */
-
-struct _ExeContext {
- struct _ExeContext * next;
- /* Variable-length array. The size is VG_(clo_backtrace_size); at
- least 1, at most VG_DEEPEST_BACKTRACE. [0] is the current IP,
- [1] is its caller, [2] is the caller of [1], etc. */
- Addr ips[0];
-};
-
-
-/* Print stats (informational only). */
-extern void VG_(print_ExeContext_stats) ( void );
-
-/* Like VG_(get_ExeContext), but with a slightly different type */
-extern ExeContext* VG_(get_ExeContext2) ( Addr ip, Addr fp,
- Addr fp_min, Addr fp_max );
-
/* ---------------------------------------------------------------------
Exports of vg_errcontext.c.
------------------------------------------------------------------ */
-
/*--------------------------------------------------------------------*/
-/*--- Storage, and equality on, execution contexts (backtraces). ---*/
-/*--- vg_execontext.c ---*/
+/*--- execontext.c ---*/
/*--------------------------------------------------------------------*/
/*
*/
#include "core.h"
-
+#include "pub_core_execontext.h"
/*------------------------------------------------------------*/
/*--- Low-level ExeContext storage. ---*/
/*------------------------------------------------------------*/
+/* The first 4 IP values are used in comparisons do remove duplicate errors,
+ and for comparing against suppression specifications. The rest are
+ purely informational (but often important). */
+
+struct _ExeContext {
+ struct _ExeContext * next;
+ /* Variable-length array. The size is VG_(clo_backtrace_size); at
+ least 1, at most VG_DEEPEST_BACKTRACE. [0] is the current IP,
+ [1] is its caller, [2] is the caller of [1], etc. */
+ Addr ips[0];
+};
+
/* Number of lists in which we keep track of ExeContexts. Should be
prime. */
#define N_EC_LISTS 4999 /* a prime number */
}
-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* ec )
{
- vg_assert( VG_(clo_backtrace_size) > 0 );
- VG_(apply_ExeContext)( printIpDesc, ec, VG_(clo_backtrace_size) );
+ VG_(pp_StackTrace)( ec->ips, VG_(clo_backtrace_size) );
}
case Vg_LowRes:
/* Just compare the top two callers. */
ec_cmp2s++;
- if (e1->ips[0] != e2->ips[0]
- || e1->ips[1] != e2->ips[1]) return False;
+ if (e1->ips[0] != e2->ips[0]) return False;
+
+ if (VG_(clo_backtrace_size) < 2) return True;
+ if (e1->ips[1] != e2->ips[1]) return False;
return True;
case Vg_MedRes:
}
}
-
-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'. */
-static UInt stack_snapshot2 ( Addr* ips, UInt n_ips, Addr ip, Addr fp,
- Addr fp_min, Addr fp_max_orig )
-{
- static const Bool debug = False;
- Int i;
- Addr fp_max;
- UInt n_found = 0;
-
- VGP_PUSHCC(VgpExeContext);
-
- /* First snaffle IPs from the client's stack into ips[0 .. n_ips-1],
- putting zeroes in when the trail goes cold, which we guess to be when
- FP is not a reasonable stack location. We also assert that FP
- increases down the chain. */
-
- // Gives shorter stack trace for tests/badjump.c
- // JRS 2002-aug-16: I don't think this is a big deal; looks ok for
- // most "normal" backtraces.
- // NJN 2002-sep-05: traces for pthreaded programs are particularly bad.
-
- // JRS 2002-sep-17: hack, to round up fp_max to the end of the
- // current page, at least. Dunno if it helps.
- // NJN 2002-sep-17: seems to -- stack traces look like 1.0.X again
- fp_max = (fp_max_orig + VKI_PAGE_SIZE - 1) & ~(VKI_PAGE_SIZE - 1);
- 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",
- n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
-
- /* Assertion broken before main() is reached in pthreaded programs; the
- * offending stack traces only have one item. --njn, 2002-aug-16 */
- /* vg_assert(fp_min <= fp_max);*/
-
- if (fp_min + 4000000 <= fp_max) {
- /* If the stack is ridiculously big, don't poke around ... but
- don't bomb out either. Needed to make John Regehr's
- user-space threads package work. JRS 20021001 */
- ips[0] = ip;
- i = 1;
- } else {
- /* Get whatever we safely can ... */
- ips[0] = ip;
- fp = FIRST_STACK_FRAME(fp);
- for (i = 1; i < n_ips; i++) {
- if (!(fp_min <= fp && fp <= fp_max)) {
- if (debug)
- VG_(printf)("... out of range %p\n", fp);
- break; /* fp gone baaaad */
- }
- // NJN 2002-sep-17: monotonicity doesn't work -- gives wrong traces...
- // if (fp >= ((UInt*)fp)[0]) {
- // VG_(printf)("nonmonotonic\n");
- // break; /* fp gone nonmonotonic */
- // }
- ips[i] = STACK_FRAME_RET(fp); /* ret addr */
- fp = STACK_FRAME_NEXT(fp); /* old fp */
- if (debug)
- VG_(printf)(" ips[%d]=%08p\n", i, ips[i]);
- }
- }
- n_found = i;
-
- /* Put zeroes in the rest. */
- for (; i < n_ips; i++) {
- ips[i] = 0;
- }
- VGP_POPCC(VgpExeContext);
-
- return n_found;
-}
-
/* This guy is the head honcho here. Take a snapshot of the client's
stack. Search our collection of ExeContexts to see if we already
have it, and if not, allocate a new one. Either way, return a
on the returned ExeContext* values themselves. Inspired by Hugs's
Text type.
*/
-ExeContext* VG_(get_ExeContext2) ( Addr ip, Addr fp,
- Addr fp_min, Addr fp_max_orig )
+ExeContext* VG_(record_ExeContext) ( ThreadId tid )
{
Int i;
Addr ips[VG_DEEPEST_BACKTRACE];
vg_assert(VG_(clo_backtrace_size) >= 1
&& VG_(clo_backtrace_size) <= VG_DEEPEST_BACKTRACE);
- stack_snapshot2( ips, VG_(clo_backtrace_size),
- ip, fp, fp_min, fp_max_orig );
+ VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size) );
/* Now figure out if we've seen this one before. First hash it so
as to determine the list number. */
return new_ec;
}
-static
-void get_needed_regs(ThreadId tid, Addr* ip, Addr* fp, Addr* sp,
- Addr* stack_highest_word)
-{
- /* thread in thread table */
- ThreadState* tst = & VG_(threads)[ tid ];
- *ip = INSTR_PTR(tst->arch);
- *fp = FRAME_PTR(tst->arch);
- *sp = STACK_PTR(tst->arch);
- *stack_highest_word = tst->stack_highest_word;
-
-#ifdef __x86__
- /* Nasty little hack to deal with sysinfo syscalls - if libc is
- using the sysinfo page for syscalls (the TLS version does), then
- ip will always appear to be in that page when doing a syscall,
- not the actual libc function doing the syscall. This check sees
- if IP is within the syscall code, and pops the return address
- off the stack so that ip is placed within the library function
- calling the syscall. This makes stack backtraces much more
- useful. */
- if (*ip >= VG_(client_trampoline_code)+VG_(tramp_syscall_offset) &&
- *ip < VG_(client_trampoline_code)+VG_(trampoline_code_length) &&
- VG_(is_addressable)(*sp, sizeof(Addr), VKI_PROT_READ)) {
- *ip = *(Addr *)*sp;
- *sp += sizeof(Addr);
- }
-#endif
- if (0)
- VG_(printf)("tid %d: stack_highest=%p ip=%p sp=%p fp=%p\n",
- tid, *stack_highest_word, *ip, *sp, *fp);
-}
-
-ExeContext* VG_(get_ExeContext) ( ThreadId tid )
-{
- Addr ip, fp, sp, stack_highest_word;
-
- get_needed_regs(tid, &ip, &fp, &sp, &stack_highest_word);
- return VG_(get_ExeContext2)(ip, fp, sp, stack_highest_word);
-}
-
-/* Take a snapshot of the client's stack, putting the up to 'n_ips'
- instruction pointers into 'ips'. In order to be thread-safe, we pass in
- the thread's IP and FP. Returns number of IPs put in 'ips'. */
-UInt VG_(stack_snapshot) ( ThreadId tid, Addr* ips, UInt n_ips )
-{
- Addr ip, fp, sp, stack_highest_word;
-
- get_needed_regs(tid, &ip, &fp, &sp, &stack_highest_word);
- return stack_snapshot2(ips, n_ips, ip, fp, sp, stack_highest_word);
-}
+StackTrace VG_(extract_StackTrace) ( ExeContext* e )
+{
+ return e->ips;
+}
/*--------------------------------------------------------------------*/
/*--- end ---*/
--- /dev/null
+/*--------------------------------------------------------------------*/
+/*--- ExeContexts: long-lived, non-dup'd stack traces. ---*/
+/*--- pub_core_execontext.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_EXECONTEXT_H
+#define __PUB_CORE_EXECONTEXT_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This module provides an abstract data type, ExeContext,
+// which is a stack trace stored in such a way that duplicates are
+// avoided. This also facilitates fast comparisons if necessary.
+//--------------------------------------------------------------------
+
+#include "pub_tool_execontext.h"
+
+#include "pub_core_stacktrace.h"
+
+// Print stats (informational only).
+extern void VG_(print_ExeContext_stats) ( void );
+
+// Extract the StackTrace from an ExeContext.
+extern StackTrace VG_(extract_StackTrace) ( ExeContext* e );
+
+#endif // __PUB_CORE_EXECONTEXT_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+/*--------------------------------------------------------------------*/
+/*--- Stack traces: getting, traversing, printing. ---*/
+/*--- pub_core_stacktrace.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_STACKTRACE_H
+#define __PUB_CORE_STACKTRACE_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This module deals with stack traces: getting them,
+// traversing them, and printing them.
+//--------------------------------------------------------------------
+
+#include "pub_tool_stacktrace.h"
+
+// Variant that gives a little more control over the stack-walking.
+extern UInt VG_(get_StackTrace2) ( StackTrace ips, UInt n_ips, Addr ip,
+ Addr fp, Addr fp_min, Addr fp_max );
+
+#endif // __PUB_CORE_STACKTRACE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+/*--------------------------------------------------------------------*/
+/*--- stacktrace.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "core.h"
+#include "pub_core_stacktrace.h"
+
+/*------------------------------------------------------------*/
+/*--- Exported functions. ---*/
+/*------------------------------------------------------------*/
+
+/* 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'. */
+UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips, Addr ip, Addr fp,
+ Addr fp_min, Addr fp_max_orig )
+{
+ static const Bool debug = False;
+ Int i;
+ Addr fp_max;
+ UInt n_found = 0;
+
+ VGP_PUSHCC(VgpExeContext);
+
+ /* First snaffle IPs from the client's stack into ips[0 .. n_ips-1],
+ putting zeroes in when the trail goes cold, which we guess to be when
+ FP is not a reasonable stack location. We also assert that FP
+ increases down the chain. */
+
+ // Gives shorter stack trace for tests/badjump.c
+ // JRS 2002-aug-16: I don't think this is a big deal; looks ok for
+ // most "normal" backtraces.
+ // NJN 2002-sep-05: traces for pthreaded programs are particularly bad.
+
+ // JRS 2002-sep-17: hack, to round up fp_max to the end of the
+ // current page, at least. Dunno if it helps.
+ // NJN 2002-sep-17: seems to -- stack traces look like 1.0.X again
+ fp_max = (fp_max_orig + VKI_PAGE_SIZE - 1) & ~(VKI_PAGE_SIZE - 1);
+ 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",
+ n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
+
+ /* Assertion broken before main() is reached in pthreaded programs; the
+ * offending stack traces only have one item. --njn, 2002-aug-16 */
+ /* vg_assert(fp_min <= fp_max);*/
+
+ if (fp_min + 4000000 <= fp_max) {
+ /* If the stack is ridiculously big, don't poke around ... but
+ don't bomb out either. Needed to make John Regehr's
+ user-space threads package work. JRS 20021001 */
+ ips[0] = ip;
+ i = 1;
+ } else {
+ /* Get whatever we safely can ... */
+ ips[0] = ip;
+ fp = FIRST_STACK_FRAME(fp);
+ for (i = 1; i < n_ips; i++) {
+ if (!(fp_min <= fp && fp <= fp_max)) {
+ if (debug)
+ VG_(printf)("... out of range %p\n", fp);
+ break; /* fp gone baaaad */
+ }
+ // NJN 2002-sep-17: monotonicity doesn't work -- gives wrong traces...
+ // if (fp >= ((UInt*)fp)[0]) {
+ // VG_(printf)("nonmonotonic\n");
+ // break; /* fp gone nonmonotonic */
+ // }
+ ips[i] = STACK_FRAME_RET(fp); /* ret addr */
+ fp = STACK_FRAME_NEXT(fp); /* old fp */
+ if (debug)
+ VG_(printf)(" ips[%d]=%08p\n", i, ips[i]);
+ }
+ }
+ n_found = i;
+
+ /* Put zeroes in the rest. */
+ for (; i < n_ips; i++) {
+ ips[i] = 0;
+ }
+ VGP_POPCC(VgpExeContext);
+
+ return n_found;
+}
+
+UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips )
+{
+ /* thread in thread table */
+ ThreadState* tst = & VG_(threads)[ tid ];
+ Addr ip = INSTR_PTR(tst->arch);
+ Addr fp = FRAME_PTR(tst->arch);
+ Addr sp = STACK_PTR(tst->arch);
+ Addr stack_highest_word = tst->stack_highest_word;
+
+#ifdef __x86__
+ /* Nasty little hack to deal with sysinfo syscalls - if libc is
+ using the sysinfo page for syscalls (the TLS version does), then
+ ip will always appear to be in that page when doing a syscall,
+ not the actual libc function doing the syscall. This check sees
+ if IP is within the syscall code, and pops the return address
+ off the stack so that ip is placed within the library function
+ calling the syscall. This makes stack backtraces much more
+ useful. */
+ if (ip >= VG_(client_trampoline_code)+VG_(tramp_syscall_offset) &&
+ ip < VG_(client_trampoline_code)+VG_(trampoline_code_length) &&
+ VG_(is_addressable)(sp, sizeof(Addr), VKI_PROT_READ)) {
+ ip = *(Addr *)sp;
+ sp += sizeof(Addr);
+ }
+#endif
+ if (0)
+ VG_(printf)("tid %d: stack_highest=%p ip=%p sp=%p fp=%p\n",
+ tid, stack_highest_word, ip, sp, fp);
+
+ return VG_(get_StackTrace2)(ips, n_ips, ip, fp, sp, stack_highest_word);
+}
+
+static void printIpDesc(UInt n, Addr ip)
+{
+ static UChar buf[M_VG_ERRTXT];
+
+ VG_(describe_IP)(ip, buf, M_VG_ERRTXT);
+ VG_(message)(Vg_UserMsg, " %s %s", ( n == 0 ? "at" : "by" ), buf);
+}
+
+/* Print a StackTrace. */
+void VG_(pp_StackTrace) ( StackTrace ips, UInt n_ips )
+{
+ vg_assert( n_ips > 0 );
+ VG_(apply_StackTrace)( printIpDesc, ips, n_ips );
+}
+
+/* Get and immediately print a StackTrace. */
+void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt n_ips )
+{
+ Addr ips[n_ips];
+ VG_(get_StackTrace)(tid, ips, n_ips);
+ VG_(pp_StackTrace) ( ips, n_ips);
+}
+
+
+void VG_(apply_StackTrace)( void(*action)(UInt n, Addr ip),
+ StackTrace ips, 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 = 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 && ips[i] != 0);
+
+ #undef MYBUF_LEN
+}
+
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
*/
#include "core.h"
+#include "pub_core_execontext.h"
/*------------------------------------------------------------*/
/*--- Globals ---*/
err->count = 1;
err->tid = tid;
if (NULL == where)
- err->where = VG_(get_ExeContext)( tid );
+ err->where = VG_(record_ExeContext)( tid );
else
err->where = where;
}
// Print stack trace elements
- VG_(apply_ExeContext)(printSuppForIp, ec, stop_at);
+ VG_(apply_StackTrace)(printSuppForIp, VG_(extract_StackTrace)(ec), stop_at);
VG_(printf)("}\n");
}
pp_Error( p_min, False );
if ((i+1 == VG_(clo_dump_error))) {
+ StackTrace ips = VG_(extract_StackTrace)(p_min->where);
VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
- p_min->where->ips[0], /*debugging*/True,
- 0xFE/*verbosity*/);
+ ips[0], /*debugging*/True, 0xFE/*verbosity*/);
}
p_min->count = 1 << 30;
{
Int i;
Char caller_name[M_VG_ERRTXT];
+ StackTrace ips = VG_(extract_StackTrace)(err->where);
for (i = 0; i < su->n_callers; i++) {
- Addr a = err->where->ips[i];
+ Addr a = ips[i];
vg_assert(su->callers[i].name != NULL);
switch (su->callers[i].ty) {
case ObjName:
#include "core.h"
#include "ume.h"
+#include "pub_core_execontext.h"
#include <dirent.h>
#include <dlfcn.h>
*/
#include "core.h"
+#include "pub_core_stacktrace.h"
/* ---------------------------------------------------------------------
Wrappers around system calls, and other stuff, to do with signals.
into the signal handler. Also, it could be somewhat risky if we
actully got the panic/exception within the execontext/stack
dump/symtab code. But it's better than nothing. */
-static inline ExeContext *get_real_execontext(Addr ret)
+static inline void get_and_pp_real_StackTrace(Addr ret)
{
- ExeContext *ec;
+ Addr ips[VG_DEEPEST_BACKTRACE];
Addr sp, fp;
Addr stacktop;
ThreadId tid = VG_(get_lwp_tid)(VG_(gettid)());
stacktop = (Addr)(tst->os_state.stack + tst->os_state.stacksize);
- ec = VG_(get_ExeContext2)(ret, fp, sp, stacktop);
-
- return ec;
+ VG_(get_StackTrace2)(ips, VG_(clo_backtrace_size),
+ ret, fp, sp, stacktop);
+ VG_(pp_StackTrace) (ips, VG_(clo_backtrace_size));
}
__attribute__ ((noreturn))
-static void report_and_quit ( const Char* report, ExeContext *ec )
+static void report_and_quit ( const Char* report, StackTrace ips )
{
- if (ec == NULL)
- ec = get_real_execontext((Addr)__builtin_return_address(0));
-
- VG_(pp_ExeContext)(ec);
+ if (ips == NULL)
+ get_and_pp_real_StackTrace((Addr)__builtin_return_address(0));
+ else
+ VG_(pp_StackTrace)(ips, VG_(clo_backtrace_size));
VG_(pp_sched_status)();
VG_(printf)("\n");
}
__attribute__ ((noreturn))
-static void panic ( Char* name, Char* report, Char* str, ExeContext *ec )
+static void panic ( Char* name, Char* report, Char* str, StackTrace ips )
{
VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
- report_and_quit(report, ec);
+ report_and_quit(report, ips);
}
void VG_(core_panic) ( Char* str )
panic("valgrind", VG_BUGS_TO, str, NULL);
}
-void VG_(core_panic_at) ( Char* str, ExeContext *ec )
+void VG_(core_panic_at) ( Char* str, StackTrace ips )
{
- panic("valgrind", VG_BUGS_TO, str, ec);
+ panic("valgrind", VG_BUGS_TO, str, ips);
}
void VG_(tool_panic) ( Char* str )
VG_USERREQ__DISCARD_TRANSLATIONS, and others */
#include "core.h"
+#include "pub_core_stacktrace.h"
+
/* ---------------------------------------------------------------------
Types and globals for the scheduler.
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_ExeContext)( i ) );
+ VG_(get_and_pp_StackTrace)( i, VG_(clo_backtrace_size) );
}
VG_(printf)("\n");
}
VG_(message)( Vg_UserMsg,
"Emulation warning: unsupported action:");
VG_(message)( Vg_UserMsg, " %s", what);
- VG_(pp_ExeContext) ( VG_(get_ExeContext) ( tid ) );
+ VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) );
}
break;
}
break; }
case VG_USERREQ__PRINTF_BACKTRACE: {
- ExeContext *e = VG_(get_ExeContext)( tid );
int count =
VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], (void*)arg[2] );
- VG_(pp_ExeContext)(e);
+ VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) );
SET_CLREQ_RETVAL( tid, count );
break; }
}
if (tid != VG_INVALID_THREADID) {
- ExeContext *ec = VG_(get_ExeContext)(tid);
- VG_(pp_ExeContext)(ec);
+ VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
}
}
from the client's code, then we can jump back into the scheduler
and have it delivered. Otherwise it's a Valgrind bug. */
{
+ Addr ips[ VG_(clo_backtrace_size) ];
Addr context_ip;
Char buf[1024];
ThreadState *tst = VG_(get_ThreadState)(VG_(get_lwp_tid)(VG_(gettid)()));
if (tid == 0) /* could happen after everyone has exited */
tid = VG_(master_tid);
tst = VG_(get_ThreadState)(tid);
- VG_(core_panic_at)("Killed by fatal signal",
- VG_(get_ExeContext2)(UCONTEXT_INSTR_PTR(uc),
- UCONTEXT_FRAME_PTR(uc),
- UCONTEXT_STACK_PTR(uc),
- (Addr)(tst->os_state.stack + tst->os_state.stacksize)));
+ VG_(get_StackTrace2)(ips, VG_(clo_backtrace_size),
+ UCONTEXT_INSTR_PTR(uc),
+ UCONTEXT_FRAME_PTR(uc),
+ UCONTEXT_STACK_PTR(uc),
+ (Addr)(tst->os_state.stack + tst->os_state.stacksize));
+ VG_(core_panic_at)("Killed by fatal signal", ips);
}
}
#endif /* TEST */
/* Print into buf info on code address, function name and filename */
-Char* VG_(describe_eip)(Addr eip, Char* buf, Int n_buf)
+Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
{
#define APPEND(str) \
{ UChar* sss; \
*/
#include "core.h"
+#include "pub_core_stacktrace.h"
/* All system calls are channelled through here, doing two things:
syscallname, start, end);
if (VG_(clo_verbosity) > 1) {
- ExeContext *ec = VG_(get_ExeContext)(tid);
- VG_(pp_ExeContext)(ec);
+ VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
}
}
i->fd = fd;
i->pathname = pathname;
- i->where = (tid == -1) ? NULL : VG_(get_ExeContext)(tid);
+ i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid);
}
static
VG_(message)(Vg_UserMsg,
" Use --log-fd=<number> to select an alternative log fd.");
if (VG_(clo_verbosity) > 1) {
- ExeContext *ec = VG_(get_ExeContext)(tid);
- VG_(pp_ExeContext)(ec);
+ VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
}
return False;
}
VG_(message)
(Vg_DebugMsg,"WARNING: unhandled syscall: %u", (UInt)SYSNO);
if (VG_(clo_verbosity) > 1) {
- ExeContext *ec = VG_(get_ExeContext)(tid);
- VG_(pp_ExeContext)(ec);
+ VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
}
VG_(message)
(Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
//:: if (th->state == state)
//:: return;
//::
-//:: ec = VG_(get_ExeContext)(th->tid);
+//:: ec = VG_(record_ExeContext)(th->tid);
//::
//:: switch(state) {
//:: case TS_Alive:
//::
//:: static void mutex_setstate(ThreadId tid, struct mutex *mx, enum mutex_state st)
//:: {
-//:: ExeContext *ec = VG_(get_ExeContext)(tid);
+//:: ExeContext *ec = VG_(record_ExeContext)(tid);
//::
//:: switch(st) {
//:: case MX_Init:
break;
}
- mutex->location = VG_(get_ExeContext)(tid);
+ mutex->location = VG_(record_ExeContext)(tid);
mutex->state = state;
}
hc = VG_(malloc)(sizeof(HG_Chunk));
hc->data = p;
hc->size = size;
- hc->where = VG_(get_ExeContext)(tid);
+ hc->where = VG_(record_ExeContext)(tid);
hc->tid = tid;
VG_(HT_add_node)( hg_malloc_list, (VgHashNode*)hc );
*prev_chunks_next_ptr = hc->next;
/* Record where freed */
- hc->where = VG_(get_ExeContext) ( tid );
+ hc->where = VG_(record_ExeContext) ( tid );
/* maintain a small window so that the error reporting machinery
knows about this memory */
if (hc->size == new_size) {
/* size unchanged */
- hc->where = VG_(get_ExeContext)(tid);
+ hc->where = VG_(record_ExeContext)(tid);
return p;
} else if (hc->size > new_size) {
/* new size is smaller */
hc->size = new_size;
- hc->where = VG_(get_ExeContext)(tid);
+ hc->where = VG_(record_ExeContext)(tid);
return p;
} else {
if (clo_execontext == EC_Some)
ecip = IP(VG_(get_IP)(tid), prevstate, tls);
else
- ecip = EC(VG_(get_ExeContext)(tid), prevstate, tls);
+ ecip = EC(VG_(record_ExeContext)(tid), prevstate, tls);
setExeContext(a, ecip);
}
}
if (clo_execontext == EC_Some)
ecip = IP(VG_(get_IP)(tid), prevstate, tls);
else
- ecip = EC(VG_(get_ExeContext)(tid), prevstate, tls);
+ ecip = EC(VG_(record_ExeContext)(tid), prevstate, tls);
setExeContext(a, ecip);
}
}
incincdir = $(includedir)/valgrind
incinc_HEADERS = \
- basic_types.h \
- tool.h \
- tool_asm.h \
+ basic_types.h \
+ tool.h \
+ tool_asm.h \
+ pub_tool_stacktrace.h \
+ pub_tool_execontext.h \
valgrind.h
BUILT_SOURCES = tool.h valgrind.h
#define __BASIC_TYPES_H
/* ---------------------------------------------------------------------
- Basic types
+ builtin types
------------------------------------------------------------------ */
#include "libvex_basictypes.h"
typedef Word OffT; // 32 64
+/* ---------------------------------------------------------------------
+ non-builtin types
+ ------------------------------------------------------------------ */
+
+/* ThreadIds are simply indices into the VG_(threads)[] array. */
+typedef
+ UInt
+ ThreadId;
/* ---------------------------------------------------------------------
Where to send bug reports to.
--- /dev/null
+/*--------------------------------------------------------------------*/
+/*--- ExeContexts: long-lived stack traces. pub_tool_execontext.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_EXECONTEXT_H
+#define __PUB_TOOL_EXECONTEXT_H
+
+// It's an abstract type.
+typedef
+ struct _ExeContext
+ ExeContext;
+
+// Resolution type used to decide how closely to compare two errors for
+// equality.
+typedef
+ enum { Vg_LowRes, Vg_MedRes, Vg_HighRes }
+ VgRes;
+
+// Take a snapshot of the client's stack. Search our collection of
+// ExeContexts to see if we already have it, and if not, allocate a
+// new one. Either way, return a pointer to the context. Context size
+// controlled by --num-callers option.
+//
+// This should only be used for long-lived stack traces. If you want a
+// short-lived stack trace, use VG_(get_StackTrace)().
+//
+// If called from generated code, use VG_(get_running_tid)() to get the
+// current ThreadId. If called from non-generated code, the current
+// ThreadId should be passed in by the core.
+extern ExeContext* VG_(record_ExeContext) ( ThreadId tid );
+
+// 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 );
+
+// Compare two ExeContexts. Number of callers considered depends on `res':
+// Vg_LowRes: 2
+// Vg_MedRes: 4
+// Vg_HighRes: all
+extern Bool VG_(eq_ExeContext) ( VgRes res, ExeContext* e1, ExeContext* e2 );
+
+// Print an ExeContext.
+extern void VG_(pp_ExeContext) ( ExeContext* ec );
+
+#endif // __PUB_TOOL_EXECONTEXT_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+/*--------------------------------------------------------------------*/
+/*--- Stack traces: getting, traversing, printing. ---*/
+/*--- tool_stacktrace.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_STACKTRACE_H
+#define __PUB_TOOL_STACKTRACE_H
+
+#include "basic_types.h"
+
+// 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.
+extern UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips );
+
+// Apply a function to every element in the StackTrace. 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_StackTrace)( void(*action)(UInt n, Addr ip),
+ StackTrace ips, UInt n_ips );
+
+// Print a StackTrace.
+extern void VG_(pp_StackTrace) ( StackTrace ips, UInt n_ips );
+
+// Gets and immediately prints a StackTrace. Just a bit simpler than
+// calling VG_(get_StackTrace)() then VG_(pp_StackTrace)().
+extern void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt n_ips );
+
+#endif // __PUB_TOOL_STACKTRACE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
/*-*- c -*- ----------------------------------------------------------*/
-/*--- The only header your tool will ever need to #include... ---*/
-/*--- tool.h ---*/
+/*--- Header for lots of tool stuff. tool.h ---*/
/*--------------------------------------------------------------------*/
/*
#include "tool_arch.h" /* arch-specific tool stuff */
#include "vki.h"
+#include "pub_tool_execontext.h" // needed for type 'ExeContext'
+
#include "libvex.h"
#include "libvex_ir.h"
pthread_mutex_t.__m_owner and pthread_cond_t.__c_waiting. */
#define VG_INVALID_THREADID ((ThreadId)(0))
-/* ThreadIds are simply indices into the VG_(threads)[] array. */
-typedef
- UInt
- ThreadId;
-
/* Get the TID of the thread which currently has the CPU. */
extern ThreadId VG_(get_running_tid) ( void );
UInt *eax_ret, UInt *ebx_ret,
UInt *ecx_ret, UInt *edx_ret );
-/*====================================================================*/
-/*=== Execution contexts ===*/
-/*====================================================================*/
-
-/* Generic resolution type used in a few different ways, such as deciding
- how closely to compare two errors for equality. */
-typedef
- enum { Vg_LowRes, Vg_MedRes, Vg_HighRes }
- VgRes;
-
-typedef
- struct _ExeContext
- ExeContext;
-
-/* Compare two ExeContexts. Number of callers considered depends on `res':
- Vg_LowRes: 2
- Vg_MedRes: 4
- Vg_HighRes: all */
-extern Bool VG_(eq_ExeContext) ( VgRes res,
- ExeContext* e1, ExeContext* e2 );
-
-/* Print an ExeContext. */
-extern void VG_(pp_ExeContext) ( ExeContext* );
-
-/* Take a snapshot of the client's stack. Search our collection of
- ExeContexts to see if we already have it, and if not, allocate a
- new one. Either way, return a pointer to the context. Context size
- controlled by --num-callers option.
-
- If called from generated code, use VG_(get_VCPU_tid)() to get the
- current ThreadId. If called from non-generated code, the current
- ThreadId should be passed in by the core.
-*/
-extern ExeContext* VG_(get_ExeContext) ( ThreadId tid );
-
-/* 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 );
-
-/* For tools needing more control over stack traces: 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. */
-extern UInt VG_(stack_snapshot) ( ThreadId tid, Addr* ips, UInt n_ips );
-
/*====================================================================*/
/*=== Error reporting ===*/
/*====================================================================*/
seen before. If it has, the existing error record will have its count
incremented.
- 'tid' can be found as for VG_(get_ExeContext)(). The `extra' field can
+ 'tid' can be found as for VG_(record_ExeContext)(). The `extra' field can
be stack-allocated; it will be copied by the core if needed (but it
won't be copied if it's NULL).
'n_buf' gives length of 'buf'. Returns 'buf'.
*/
-extern Char* VG_(describe_eip)(Addr eip, Char* buf, Int n_buf);
+extern Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf);
/* Returns a string containing an expression for the given
address. String is malloced with VG_(malloc)() */
// structures below for more info on how things work.
#include "tool.h"
+#include "pub_tool_stacktrace.h"
//#include "vg_profile.c"
#include "valgrind.h" // For {MALLOC,FREE}LIKE_BLOCK
typedef struct _XPt XPt;
struct _XPt {
- Addr eip; // code address
+ Addr ip; // code address
// Bottom-XPts: space for the precise context.
// Other XPts: space of all the descendent bottom-XPts.
-static XPt* new_XPt(Addr eip, XPt* parent, Bool is_bottom)
+static XPt* new_XPt(Addr ip, XPt* parent, Bool is_bottom)
{
XPt* xpt = perm_malloc(sizeof(XPt));
- xpt->eip = eip;
+ xpt->ip = ip;
xpt->curr_space = 0;
xpt->approx_ST = 0;
return xpt;
}
-static Bool is_alloc_fn(Addr eip)
+static Bool is_alloc_fn(Addr ip)
{
Int i;
- if ( VG_(get_fnname)(eip, buf, BUF_LEN) ) {
+ if ( VG_(get_fnname)(ip, buf, BUF_LEN) ) {
for (i = 0; i < n_alloc_fns; i++) {
if (VG_STREQ(buf, alloc_fns[i]))
return True;
// to ensure this in certain cases. See comments below.
static XPt* get_XCon( ThreadId tid, Bool custom_malloc )
{
- // Static to minimise stack size. +1 for added ~0 %eip.
- static Addr eips[MAX_DEPTH + MAX_ALLOC_FNS + 1];
+ // Static to minimise stack size. +1 for added ~0 IP
+ static Addr ips[MAX_DEPTH + MAX_ALLOC_FNS + 1];
XPt* xpt = alloc_xpt;
- UInt n_eips, L, A, B, nC;
+ UInt n_ips, L, A, B, nC;
UInt overestimate;
Bool reached_bottom;
// it is enough.
overestimate = 2;
while (True) {
- n_eips = VG_(stack_snapshot)( tid, eips, clo_depth + overestimate );
+ n_ips = VG_(get_StackTrace)( tid, ips, clo_depth + overestimate );
- // Now we add a dummy "unknown" %eip at the end. This is only used if we
- // run out of %eips before hitting clo_depth. It's done to ensure the
+ // Now we add a dummy "unknown" IP at the end. This is only used if we
+ // run out of IPs before hitting clo_depth. It's done to ensure the
// XPt we return is (now and forever) a bottom-XPt. If the returned XPt
// wasn't a bottom-XPt (now or later) it would cause problems later (eg.
// the parent's approx_ST wouldn't be equal [or almost equal] to the
// total of the childrens' approx_STs).
- eips[ n_eips++ ] = ~((Addr)0);
+ ips[ n_ips++ ] = ~((Addr)0);
- // Skip over alloc functions in eips[].
- for (L = 0; is_alloc_fn(eips[L]) && L < n_eips; L++) { }
+ // Skip over alloc functions in ips[].
+ for (L = 0; is_alloc_fn(ips[L]) && L < n_ips; L++) { }
// Must be at least one alloc function, unless client used
// MALLOCLIKE_BLOCK
if (!custom_malloc) tl_assert(L > 0);
// Should be at least one non-alloc function. If not, try again.
- if (L == n_eips) {
+ if (L == n_ips) {
overestimate += 2;
if (overestimate > MAX_ALLOC_FNS)
VG_(tool_panic)("No stk snapshot big enough to find non-alloc fns");
}
}
A = L;
- B = n_eips - 1;
+ B = n_ips - 1;
reached_bottom = False;
- // By this point, the eips we care about are in eips[A]..eips[B]
+ // By this point, the IPs we care about are in ips[A]..ips[B]
// Now do the search/insertion of the XCon. 'L' is the loop counter,
- // being the index into eips[].
+ // being the index into ips[].
while (True) {
- // Look for %eip in xpt's children.
+ // Look for IP in xpt's children.
// XXX: linear search, ugh -- about 10% of time for konqueror startup
// XXX: tried cacheing last result, only hit about 4% for konqueror
// Nb: this search hits about 98% of the time for konqueror
xpt->max_children * sizeof(XPt*) );
n_children_reallocs++;
}
- // Make new XPt for %eip, insert in list
+ // Make new XPt for IP, insert in list
xpt->children[ xpt->n_children++ ] =
- new_XPt(eips[L], xpt, reached_bottom);
+ new_XPt(ips[L], xpt, reached_bottom);
break;
}
- if (eips[L] == xpt->children[nC]->eip) break; // found the %eip
+ if (ips[L] == xpt->children[nC]->ip) break; // found the IP
nC++; // keep looking
}
VGP_POPCC(VgpGetXPtSearch);
for (j = 0; NULL != census->xtree_snapshots[j]; j++) {
// Grab the jth top-XPt
XTreeSnapshot xtree_snapshot = & census->xtree_snapshots[j][0];
- if ( ! VG_(get_fnname)(xtree_snapshot->xpt->eip, buf2, 16)) {
+ if ( ! VG_(get_fnname)(xtree_snapshot->xpt->ip, buf2, 16)) {
VG_(sprintf)(buf2, "???");
}
- SPRINTF(buf, "x%x:%s %d\n", xtree_snapshot->xpt->eip,
+ SPRINTF(buf, "x%x:%s %d\n", xtree_snapshot->xpt->ip,
clean_fnname(buf3, buf2), xtree_snapshot->space);
}
return mbuf;
}
-// Nb: passed in XPt is a lower-level XPt; %eips are grabbed from
+// Nb: passed in XPt is a lower-level XPt; IPs are grabbed from
// bottom-to-top of XCon, and then printed in the reverse order.
static UInt pp_XCon(Int fd, XPt* xpt)
{
- Addr rev_eips[clo_depth+1];
+ Addr rev_ips[clo_depth+1];
Int i = 0;
Int n = 0;
Bool is_HTML = ( XHTML == clo_format );
tl_assert(NULL != xpt);
while (True) {
- rev_eips[i] = xpt->eip;
+ rev_ips[i] = xpt->ip;
n++;
if (alloc_xpt == xpt->parent) break;
i++;
for (i = n-1; i >= 0; i--) {
// -1 means point to calling line
- VG_(describe_eip)(rev_eips[i]-1, buf2, BUF_LEN);
+ VG_(describe_IP)(rev_ips[i]-1, buf2, BUF_LEN);
SPRINTF(buf, " %s%s%s\n", maybe_indent, buf2, maybe_br);
}
}
// Important point: for HTML, each XPt must be identified uniquely for the
-// HTML links to all match up correctly. Using xpt->eip is not
+// HTML links to all match up correctly. Using xpt->ip is not
// sufficient, because function pointers mean that you can call more than
// one other function from a single code location. So instead we use the
// address of the xpt struct itself, which is guaranteed to be unique.
UInt c2 = 0;
ULong sum = 0;
UInt n;
- Char *eip_desc, *perc;
+ Char *ip_desc, *perc;
Bool is_HTML = ( XHTML == clo_format );
Char* maybe_br = ( is_HTML ? "<br>" : "" );
Char* maybe_p = ( is_HTML ? "<p>" : "" );
}
// Remember: exact_ST_dbld is space.time *doubled*
- perc = make_perc(child->exact_ST_dbld / 2, total_spacetime);
- eip_desc = VG_(describe_eip)(child->eip-1, buf2, BUF_LEN);
+ perc = make_perc(child->exact_ST_dbld / 2, total_spacetime);
+ ip_desc = VG_(describe_IP)(child->ip-1, buf2, BUF_LEN);
if (is_HTML) {
SPRINTF(buf, "<li><a name=\"a%x\"></a>", child );
} else {
SPRINTF(buf, "%s", perc);
}
- SPRINTF(buf, ": %s\n", eip_desc);
+ SPRINTF(buf, ": %s\n", ip_desc);
} else {
- SPRINTF(buf, " %6s: %s\n\n", perc, eip_desc);
+ SPRINTF(buf, " %6s: %s\n\n", perc, ip_desc);
}
if (child->n_children > 0) {
mc->data = p;
mc->size = size;
mc->allockind = kind;
- mc->where = VG_(get_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid);
/* Paranoia ... ensure this area is off-limits to the client, so
the mc->data field isn't visible to the leak checker. If memory
/* Put it out of harm's way for a while, if not from a client request */
if (MAC_AllocCustom != mc->allockind) {
/* Record where freed */
- mc->where = VG_(get_ExeContext) ( tid );
+ mc->where = VG_(record_ExeContext) ( tid );
add_to_freed_queue ( mc );
} else
VG_(free) ( mc );
if (mc->size == new_size) {
/* size unchanged */
- mc->where = VG_(get_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid);
VGP_POPCC(VgpCliMalloc);
return p;
/* new size is smaller */
MAC_(die_mem_heap)( mc->data+new_size, mc->size-new_size );
mc->size = new_size;
- mc->where = VG_(get_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid);
VGP_POPCC(VgpCliMalloc);
return p;
vg_cgbs[i].start = arg[1];
vg_cgbs[i].size = arg[2];
vg_cgbs[i].desc = VG_(strdup)((Char *)arg[3]);
- vg_cgbs[i].where = VG_(get_ExeContext) ( tid );
+ vg_cgbs[i].where = VG_(record_ExeContext) ( tid );
*ret = i;
} else