A modularisation + refactoring commit. vg_execontext.c has been split into
two halves: stacktrace.c, which deals with getting, traversing and printing
stack traces; and execontext.c, which deals with storing stack traces
permanently in a way that avoids duplicates, and comparing them.
One nice outcome: previously we were often creating ExeContexts, which live
forever, even when they were only needed temporarily. Ie. this was a memory
leak, which has been removed.
As part of this, new headers have been created, carved off core.h and
tool.h. Lots of function names have changed, too.
In Massif, I also changed a lot of "eip" names to "ip" to make them less
x86-specific.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3429 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index be3d5da..df822ac 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -27,6 +27,8 @@
noinst_HEADERS = \
core.h \
core_asm.h \
+ pub_core_execontext.h \
+ pub_core_stacktrace.h \
ume.h \
vg_symtab2.h \
vg_symtypes.h \
@@ -50,13 +52,14 @@
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 \
diff --git a/coregrind/core.h b/coregrind/core.h
index 25be871..481d4f7 100644
--- a/coregrind/core.h
+++ b/coregrind/core.h
@@ -93,6 +93,8 @@
// 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_
@@ -809,7 +811,7 @@
__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);
@@ -867,31 +869,6 @@
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.
------------------------------------------------------------------ */
diff --git a/coregrind/execontext.c b/coregrind/execontext.c
new file mode 100644
index 0000000..5de1dbe
--- /dev/null
+++ b/coregrind/execontext.c
@@ -0,0 +1,256 @@
+/*--------------------------------------------------------------------*/
+/*--- execontext.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_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 */
+
+/* The idea is only to ever store any one context once, so as to save
+ space and make exact comparisons faster. */
+
+static ExeContext* ec_list[N_EC_LISTS];
+
+/* Stats only: the number of times the system was searched to locate a
+ context. */
+static UInt ec_searchreqs;
+
+/* Stats only: the number of full context comparisons done. */
+static UInt ec_searchcmps;
+
+/* Stats only: total number of stored contexts. */
+static UInt ec_totstored;
+
+/* Number of 2, 4 and (fast) full cmps done. */
+static UInt ec_cmp2s;
+static UInt ec_cmp4s;
+static UInt ec_cmpAlls;
+
+
+/*------------------------------------------------------------*/
+/*--- Exported functions. ---*/
+/*------------------------------------------------------------*/
+
+
+/* Initialise this subsystem. */
+static void init_ExeContext_storage ( void )
+{
+ Int i;
+ static Bool init_done = False;
+ if (init_done)
+ return;
+ ec_searchreqs = 0;
+ ec_searchcmps = 0;
+ ec_totstored = 0;
+ ec_cmp2s = 0;
+ ec_cmp4s = 0;
+ ec_cmpAlls = 0;
+ for (i = 0; i < N_EC_LISTS; i++)
+ ec_list[i] = NULL;
+ init_done = True;
+}
+
+
+/* Print stats. */
+void VG_(print_ExeContext_stats) ( void )
+{
+ init_ExeContext_storage();
+ VG_(message)(Vg_DebugMsg,
+ " exectx: %d lists, %d contexts (avg %d per list)",
+ N_EC_LISTS, ec_totstored,
+ ec_totstored / N_EC_LISTS
+ );
+ VG_(message)(Vg_DebugMsg,
+ " exectx: %d searches, %d full compares (%d per 1000)",
+ ec_searchreqs, ec_searchcmps,
+ ec_searchreqs == 0
+ ? 0
+ : (UInt)( (((ULong)ec_searchcmps) * 1000)
+ / ((ULong)ec_searchreqs ))
+ );
+ VG_(message)(Vg_DebugMsg,
+ " exectx: %d cmp2, %d cmp4, %d cmpAll",
+ ec_cmp2s, ec_cmp4s, ec_cmpAlls
+ );
+}
+
+
+/* Print an ExeContext. */
+void VG_(pp_ExeContext) ( ExeContext* ec )
+{
+ VG_(pp_StackTrace)( ec->ips, VG_(clo_backtrace_size) );
+}
+
+
+/* Compare two ExeContexts, comparing all callers. */
+Bool VG_(eq_ExeContext) ( VgRes res, ExeContext* e1, ExeContext* e2 )
+{
+ if (e1 == NULL || e2 == NULL)
+ return False;
+ switch (res) {
+ case Vg_LowRes:
+ /* Just compare the top two callers. */
+ ec_cmp2s++;
+ 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:
+ /* Just compare the top four callers. */
+ ec_cmp4s++;
+ 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;
+
+ if (VG_(clo_backtrace_size) < 3) return True;
+ if (e1->ips[2] != e2->ips[2]) return False;
+
+ if (VG_(clo_backtrace_size) < 4) return True;
+ if (e1->ips[3] != e2->ips[3]) return False;
+ return True;
+
+ case Vg_HighRes:
+ ec_cmpAlls++;
+ /* Compare them all -- just do pointer comparison. */
+ if (e1 != e2) return False;
+ return True;
+
+ default:
+ VG_(core_panic)("VG_(eq_ExeContext): unrecognised VgRes");
+ }
+}
+
+/* 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
+ pointer to the context. If there is a matching context we
+ guarantee to not allocate a new one. Thus we never store
+ duplicates, and so exact equality can be quickly done as equality
+ on the returned ExeContext* values themselves. Inspired by Hugs's
+ Text type.
+*/
+ExeContext* VG_(record_ExeContext) ( ThreadId tid )
+{
+ Int i;
+ Addr ips[VG_DEEPEST_BACKTRACE];
+ Bool same;
+ UWord hash;
+ ExeContext* new_ec;
+ ExeContext* list;
+
+ VGP_PUSHCC(VgpExeContext);
+
+ init_ExeContext_storage();
+ vg_assert(VG_(clo_backtrace_size) >= 1
+ && VG_(clo_backtrace_size) <= VG_DEEPEST_BACKTRACE);
+
+ 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. */
+
+ hash = 0;
+ for (i = 0; i < VG_(clo_backtrace_size); i++) {
+ hash ^= ips[i];
+ hash = (hash << 29) | (hash >> 3);
+ }
+ hash = hash % N_EC_LISTS;
+
+ /* And (the expensive bit) look a matching entry in the list. */
+
+ ec_searchreqs++;
+
+ list = ec_list[hash];
+
+ while (True) {
+ if (list == NULL) break;
+ ec_searchcmps++;
+ same = True;
+ for (i = 0; i < VG_(clo_backtrace_size); i++) {
+ if (list->ips[i] != ips[i]) {
+ same = False;
+ break;
+ }
+ }
+ if (same) break;
+ list = list->next;
+ }
+
+ if (list != NULL) {
+ /* Yay! We found it. */
+ VGP_POPCC(VgpExeContext);
+ return list;
+ }
+
+ /* Bummer. We have to allocate a new context record. */
+ ec_totstored++;
+
+ new_ec = VG_(arena_malloc)( VG_AR_EXECTXT,
+ sizeof(struct _ExeContext *)
+ + VG_(clo_backtrace_size) * sizeof(Addr) );
+
+ for (i = 0; i < VG_(clo_backtrace_size); i++)
+ new_ec->ips[i] = ips[i];
+
+ new_ec->next = ec_list[hash];
+ ec_list[hash] = new_ec;
+
+ VGP_POPCC(VgpExeContext);
+ return new_ec;
+}
+
+StackTrace VG_(extract_StackTrace) ( ExeContext* e )
+{
+ return e->ips;
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/pub_core_execontext.h b/coregrind/pub_core_execontext.h
new file mode 100644
index 0000000..119adb4
--- /dev/null
+++ b/coregrind/pub_core_execontext.h
@@ -0,0 +1,54 @@
+/*--------------------------------------------------------------------*/
+/*--- 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 ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/pub_core_stacktrace.h b/coregrind/pub_core_stacktrace.h
new file mode 100644
index 0000000..61c6e63
--- /dev/null
+++ b/coregrind/pub_core_stacktrace.h
@@ -0,0 +1,49 @@
+/*--------------------------------------------------------------------*/
+/*--- 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 ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/stacktrace.c b/coregrind/stacktrace.c
new file mode 100644
index 0000000..692a035
--- /dev/null
+++ b/coregrind/stacktrace.c
@@ -0,0 +1,204 @@
+/*--------------------------------------------------------------------*/
+/*--- 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 ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/vg_errcontext.c b/coregrind/vg_errcontext.c
index ce55550..a28e34e 100644
--- a/coregrind/vg_errcontext.c
+++ b/coregrind/vg_errcontext.c
@@ -29,6 +29,7 @@
*/
#include "core.h"
+#include "pub_core_execontext.h"
/*------------------------------------------------------------*/
/*--- Globals ---*/
@@ -326,7 +327,7 @@
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;
@@ -381,7 +382,7 @@
}
// Print stack trace elements
- VG_(apply_ExeContext)(printSuppForIp, ec, stop_at);
+ VG_(apply_StackTrace)(printSuppForIp, VG_(extract_StackTrace)(ec), stop_at);
VG_(printf)("}\n");
}
@@ -675,9 +676,9 @@
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;
@@ -982,9 +983,10 @@
{
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:
diff --git a/coregrind/vg_execontext.c b/coregrind/vg_execontext.c
deleted file mode 100644
index 8683055..0000000
--- a/coregrind/vg_execontext.c
+++ /dev/null
@@ -1,411 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Storage, and equality on, execution contexts (backtraces). ---*/
-/*--- vg_execontext.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"
-
-
-/*------------------------------------------------------------*/
-/*--- Low-level ExeContext storage. ---*/
-/*------------------------------------------------------------*/
-
-/* Number of lists in which we keep track of ExeContexts. Should be
- prime. */
-#define N_EC_LISTS 4999 /* a prime number */
-
-/* The idea is only to ever store any one context once, so as to save
- space and make exact comparisons faster. */
-
-static ExeContext* ec_list[N_EC_LISTS];
-
-/* Stats only: the number of times the system was searched to locate a
- context. */
-static UInt ec_searchreqs;
-
-/* Stats only: the number of full context comparisons done. */
-static UInt ec_searchcmps;
-
-/* Stats only: total number of stored contexts. */
-static UInt ec_totstored;
-
-/* Number of 2, 4 and (fast) full cmps done. */
-static UInt ec_cmp2s;
-static UInt ec_cmp4s;
-static UInt ec_cmpAlls;
-
-
-/*------------------------------------------------------------*/
-/*--- Exported functions. ---*/
-/*------------------------------------------------------------*/
-
-
-/* Initialise this subsystem. */
-static void init_ExeContext_storage ( void )
-{
- Int i;
- static Bool init_done = False;
- if (init_done)
- return;
- ec_searchreqs = 0;
- ec_searchcmps = 0;
- ec_totstored = 0;
- ec_cmp2s = 0;
- ec_cmp4s = 0;
- ec_cmpAlls = 0;
- for (i = 0; i < N_EC_LISTS; i++)
- ec_list[i] = NULL;
- init_done = True;
-}
-
-
-/* Print stats. */
-void VG_(print_ExeContext_stats) ( void )
-{
- init_ExeContext_storage();
- VG_(message)(Vg_DebugMsg,
- " exectx: %d lists, %d contexts (avg %d per list)",
- N_EC_LISTS, ec_totstored,
- ec_totstored / N_EC_LISTS
- );
- VG_(message)(Vg_DebugMsg,
- " exectx: %d searches, %d full compares (%d per 1000)",
- ec_searchreqs, ec_searchcmps,
- ec_searchreqs == 0
- ? 0
- : (UInt)( (((ULong)ec_searchcmps) * 1000)
- / ((ULong)ec_searchreqs ))
- );
- VG_(message)(Vg_DebugMsg,
- " exectx: %d cmp2, %d cmp4, %d cmpAll",
- ec_cmp2s, ec_cmp4s, ec_cmpAlls
- );
-}
-
-
-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) );
-}
-
-
-/* Compare two ExeContexts, comparing all callers. */
-Bool VG_(eq_ExeContext) ( VgRes res, ExeContext* e1, ExeContext* e2 )
-{
- if (e1 == NULL || e2 == NULL)
- return False;
- switch (res) {
- 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;
- return True;
-
- case Vg_MedRes:
- /* Just compare the top four callers. */
- ec_cmp4s++;
- 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;
-
- if (VG_(clo_backtrace_size) < 3) return True;
- if (e1->ips[2] != e2->ips[2]) return False;
-
- if (VG_(clo_backtrace_size) < 4) return True;
- if (e1->ips[3] != e2->ips[3]) return False;
- return True;
-
- case Vg_HighRes:
- ec_cmpAlls++;
- /* Compare them all -- just do pointer comparison. */
- if (e1 != e2) return False;
- return True;
-
- default:
- VG_(core_panic)("VG_(eq_ExeContext): unrecognised VgRes");
- }
-}
-
-
-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
- pointer to the context. If there is a matching context we
- guarantee to not allocate a new one. Thus we never store
- duplicates, and so exact equality can be quickly done as equality
- 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 )
-{
- Int i;
- Addr ips[VG_DEEPEST_BACKTRACE];
- Bool same;
- UWord hash;
- ExeContext* new_ec;
- ExeContext* list;
-
- VGP_PUSHCC(VgpExeContext);
-
- init_ExeContext_storage();
- 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 );
-
- /* Now figure out if we've seen this one before. First hash it so
- as to determine the list number. */
-
- hash = 0;
- for (i = 0; i < VG_(clo_backtrace_size); i++) {
- hash ^= ips[i];
- hash = (hash << 29) | (hash >> 3);
- }
- hash = hash % N_EC_LISTS;
-
- /* And (the expensive bit) look a matching entry in the list. */
-
- ec_searchreqs++;
-
- list = ec_list[hash];
-
- while (True) {
- if (list == NULL) break;
- ec_searchcmps++;
- same = True;
- for (i = 0; i < VG_(clo_backtrace_size); i++) {
- if (list->ips[i] != ips[i]) {
- same = False;
- break;
- }
- }
- if (same) break;
- list = list->next;
- }
-
- if (list != NULL) {
- /* Yay! We found it. */
- VGP_POPCC(VgpExeContext);
- return list;
- }
-
- /* Bummer. We have to allocate a new context record. */
- ec_totstored++;
-
- new_ec = VG_(arena_malloc)( VG_AR_EXECTXT,
- sizeof(struct _ExeContext *)
- + VG_(clo_backtrace_size) * sizeof(Addr) );
-
- for (i = 0; i < VG_(clo_backtrace_size); i++)
- new_ec->ips[i] = ips[i];
-
- new_ec->next = ec_list[hash];
- ec_list[hash] = new_ec;
-
- VGP_POPCC(VgpExeContext);
- 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);
-}
-
-/*--------------------------------------------------------------------*/
-/*--- end ---*/
-/*--------------------------------------------------------------------*/
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index eaef6d2..15962ce 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -32,6 +32,7 @@
#include "core.h"
#include "ume.h"
+#include "pub_core_execontext.h"
#include <dirent.h>
#include <dlfcn.h>
diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c
index 4cd55f9..3f261fd 100644
--- a/coregrind/vg_mylibc.c
+++ b/coregrind/vg_mylibc.c
@@ -31,6 +31,7 @@
*/
#include "core.h"
+#include "pub_core_stacktrace.h"
/* ---------------------------------------------------------------------
Wrappers around system calls, and other stuff, to do with signals.
@@ -1128,9 +1129,9 @@
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)());
@@ -1141,18 +1142,18 @@
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");
@@ -1191,11 +1192,11 @@
}
__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 )
@@ -1203,9 +1204,9 @@
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 )
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index e316eb4..66eba36 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -60,6 +60,8 @@
VG_USERREQ__DISCARD_TRANSLATIONS, and others */
#include "core.h"
+#include "pub_core_stacktrace.h"
+
/* ---------------------------------------------------------------------
Types and globals for the scheduler.
@@ -168,7 +170,7 @@
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");
}
@@ -844,7 +846,7 @@
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;
}
@@ -1047,10 +1049,9 @@
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; }
diff --git a/coregrind/vg_signals.c b/coregrind/vg_signals.c
index 6774b39..8e814d7 100644
--- a/coregrind/vg_signals.c
+++ b/coregrind/vg_signals.c
@@ -1373,8 +1373,7 @@
}
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));
}
}
@@ -1879,6 +1878,7 @@
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)()));
@@ -1936,11 +1936,12 @@
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);
}
}
diff --git a/coregrind/vg_symtab2.c b/coregrind/vg_symtab2.c
index 9cb2a12..1ec15ae 100644
--- a/coregrind/vg_symtab2.c
+++ b/coregrind/vg_symtab2.c
@@ -2170,7 +2170,7 @@
#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; \
diff --git a/coregrind/vg_syscalls.c b/coregrind/vg_syscalls.c
index 14e4c97..b0b1c75 100644
--- a/coregrind/vg_syscalls.c
+++ b/coregrind/vg_syscalls.c
@@ -29,6 +29,7 @@
*/
#include "core.h"
+#include "pub_core_stacktrace.h"
/* All system calls are channelled through here, doing two things:
@@ -134,8 +135,7 @@
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));
}
}
@@ -479,7 +479,7 @@
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
@@ -954,8 +954,7 @@
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;
}
@@ -5907,8 +5906,7 @@
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.");
diff --git a/coregrind/vg_threadmodel.c b/coregrind/vg_threadmodel.c
index 37209b0..a1bec5d 100644
--- a/coregrind/vg_threadmodel.c
+++ b/coregrind/vg_threadmodel.c
@@ -180,7 +180,7 @@
//:: if (th->state == state)
//:: return;
//::
-//:: ec = VG_(get_ExeContext)(th->tid);
+//:: ec = VG_(record_ExeContext)(th->tid);
//::
//:: switch(state) {
//:: case TS_Alive:
@@ -607,7 +607,7 @@
//::
//:: 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:
diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
index bf9a9d4..3013aeb 100644
--- a/helgrind/hg_main.c
+++ b/helgrind/hg_main.c
@@ -1571,7 +1571,7 @@
break;
}
- mutex->location = VG_(get_ExeContext)(tid);
+ mutex->location = VG_(record_ExeContext)(tid);
mutex->state = state;
}
@@ -1818,7 +1818,7 @@
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 );
@@ -1894,7 +1894,7 @@
*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 */
@@ -1961,13 +1961,13 @@
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 {
@@ -3035,7 +3035,7 @@
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);
}
}
@@ -3140,7 +3140,7 @@
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);
}
}
diff --git a/include/Makefile.am b/include/Makefile.am
index e9bafff..d41672a 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -10,9 +10,11 @@
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
diff --git a/include/basic_types.h b/include/basic_types.h
index cbf1594..728c367 100644
--- a/include/basic_types.h
+++ b/include/basic_types.h
@@ -32,7 +32,7 @@
#define __BASIC_TYPES_H
/* ---------------------------------------------------------------------
- Basic types
+ builtin types
------------------------------------------------------------------ */
#include "libvex_basictypes.h"
@@ -57,6 +57,14 @@
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.
diff --git a/include/pub_tool_execontext.h b/include/pub_tool_execontext.h
new file mode 100644
index 0000000..9e33869
--- /dev/null
+++ b/include/pub_tool_execontext.h
@@ -0,0 +1,76 @@
+/*--------------------------------------------------------------------*/
+/*--- 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 ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/pub_tool_stacktrace.h b/include/pub_tool_stacktrace.h
new file mode 100644
index 0000000..f74a1b1
--- /dev/null
+++ b/include/pub_tool_stacktrace.h
@@ -0,0 +1,61 @@
+/*--------------------------------------------------------------------*/
+/*--- 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 ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/tool.h.base b/include/tool.h.base
index 2ef0f8e..14d9fe6 100644
--- a/include/tool.h.base
+++ b/include/tool.h.base
@@ -1,6 +1,5 @@
/*-*- c -*- ----------------------------------------------------------*/
-/*--- The only header your tool will ever need to #include... ---*/
-/*--- tool.h ---*/
+/*--- Header for lots of tool stuff. tool.h ---*/
/*--------------------------------------------------------------------*/
/*
@@ -38,6 +37,8 @@
#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"
@@ -282,11 +283,6 @@
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 );
@@ -571,53 +567,6 @@
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 ===*/
/*====================================================================*/
@@ -686,7 +635,7 @@
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).
@@ -755,7 +704,7 @@
'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)() */
diff --git a/massif/ms_main.c b/massif/ms_main.c
index 1576b5f..019f4ae 100644
--- a/massif/ms_main.c
+++ b/massif/ms_main.c
@@ -35,6 +35,7 @@
// 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
@@ -90,7 +91,7 @@
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.
@@ -362,10 +363,10 @@
-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;
@@ -396,11 +397,11 @@
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;
@@ -414,11 +415,11 @@
// 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;
@@ -431,25 +432,25 @@
// 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");
@@ -458,15 +459,15 @@
}
}
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
@@ -490,12 +491,12 @@
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);
@@ -1430,10 +1431,10 @@
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);
}
@@ -1512,11 +1513,11 @@
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 );
@@ -1526,7 +1527,7 @@
tl_assert(NULL != xpt);
while (True) {
- rev_eips[i] = xpt->eip;
+ rev_ips[i] = xpt->ip;
n++;
if (alloc_xpt == xpt->parent) break;
i++;
@@ -1535,7 +1536,7 @@
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);
}
@@ -1543,7 +1544,7 @@
}
// 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.
@@ -1558,7 +1559,7 @@
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>" : "" );
@@ -1642,8 +1643,8 @@
}
// 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 );
@@ -1652,9 +1653,9 @@
} 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) {
diff --git a/memcheck/mac_malloc_wrappers.c b/memcheck/mac_malloc_wrappers.c
index 7250353..5510a06 100644
--- a/memcheck/mac_malloc_wrappers.c
+++ b/memcheck/mac_malloc_wrappers.c
@@ -141,7 +141,7 @@
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
@@ -290,7 +290,7 @@
/* 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 );
@@ -376,7 +376,7 @@
if (mc->size == new_size) {
/* size unchanged */
- mc->where = VG_(get_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid);
VGP_POPCC(VgpCliMalloc);
return p;
@@ -384,7 +384,7 @@
/* 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;
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c
index f5d6c32..4654251 100644
--- a/memcheck/mc_main.c
+++ b/memcheck/mc_main.c
@@ -1808,7 +1808,7 @@
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