|
From: <sv...@va...> - 2007-12-21 01:24:58
|
Author: sewardj
Date: 2007-12-21 01:24:59 +0000 (Fri, 21 Dec 2007)
New Revision: 7304
Log:
Add a new method VG_(record_depth_1_ExeContext), a trivial derivative
of VG_(record_ExeContext), which just records the first stack frame
but does not attempt to unwind the (guest) stack. This is useful in
situations where we suspect unwinding the stack might cause a
segfault.
Use this in m_signals, when getting a backtrace following a guest
segfault.
Modified:
trunk/coregrind/m_execontext.c
trunk/coregrind/m_signals.c
trunk/include/pub_tool_execontext.h
Modified: trunk/coregrind/m_execontext.c
===================================================================
--- trunk/coregrind/m_execontext.c 2007-12-19 11:01:13 UTC (rev 7303)
+++ trunk/coregrind/m_execontext.c 2007-12-21 01:24:59 UTC (rev 7304)
@@ -30,12 +30,15 @@
#include "pub_core_basics.h"
#include "pub_core_debuglog.h"
-#include "pub_core_execontext.h" // self
#include "pub_core_libcassert.h"
#include "pub_core_libcprint.h" // For VG_(message)()
#include "pub_core_mallocfree.h"
#include "pub_core_options.h"
#include "pub_core_stacktrace.h"
+#include "pub_core_machine.h" // VG_(get_IP)
+#include "pub_core_vki.h" // To keep pub_core_threadstate.h happy
+#include "pub_core_threadstate.h" // VG_(is_valid_tid)
+#include "pub_core_execontext.h" // self
/*------------------------------------------------------------*/
/*--- Low-level ExeContext storage. ---*/
@@ -277,7 +280,8 @@
ec_htab_size_idx++;
}
-ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta )
+static ExeContext* record_ExeContext_wrk ( ThreadId tid, Word first_ip_delta,
+ Bool first_ip_only )
{
Int i;
Addr ips[VG_DEEPEST_BACKTRACE];
@@ -297,8 +301,15 @@
vg_assert(VG_(clo_backtrace_size) >= 1 &&
VG_(clo_backtrace_size) <= VG_DEEPEST_BACKTRACE);
- n_ips = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size),
- first_ip_delta );
+ if (first_ip_only) {
+ vg_assert(VG_(is_valid_tid)(tid));
+ n_ips = 1;
+ ips[0] = VG_(get_IP)(tid);
+ } else {
+ n_ips = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size),
+ first_ip_delta );
+ }
+
tl_assert(n_ips >= 1 && n_ips <= VG_(clo_backtrace_size));
/* Now figure out if we've seen this one before. First hash it so
@@ -378,6 +389,17 @@
return new_ec;
}
+ExeContext* VG_(record_ExeContext)( ThreadId tid, Word first_ip_delta ) {
+ return record_ExeContext_wrk( tid, first_ip_delta,
+ False/*!first_ip_only*/ );
+}
+
+ExeContext* VG_(record_depth_1_ExeContext)( ThreadId tid ) {
+ return record_ExeContext_wrk( tid, 0/*first_ip_delta*/,
+ True/*first_ip_only*/ );
+}
+
+
StackTrace VG_(extract_StackTrace) ( ExeContext* e )
{
return e->ips;
Modified: trunk/coregrind/m_signals.c
===================================================================
--- trunk/coregrind/m_signals.c 2007-12-19 11:01:13 UTC (rev 7303)
+++ trunk/coregrind/m_signals.c 2007-12-21 01:24:59 UTC (rev 7304)
@@ -1275,7 +1275,7 @@
case VKI_BUS_OBJERR: event = "Hardware error"; break;
}
break;
- }
+ } /* switch (sigNo) */
if (event != NULL) {
if (haveaddr)
@@ -1285,11 +1285,17 @@
VG_(message)(Vg_UserMsg, " %s", event);
}
}
-
- if (tid != VG_INVALID_THREADID) {
- VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
+ /* Print a stack trace. Be cautious if the thread's SP is in an
+ obviously stupid place (not mapped readable) that would
+ likely cause a segfault. */
+ if (VG_(is_valid_tid)(tid)) {
+ ExeContext* ec = VG_(am_is_valid_for_client)
+ (VG_(get_SP)(tid), sizeof(Addr), VKI_PROT_READ)
+ ? VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ )
+ : VG_(record_depth_1_ExeContext)( tid );
+ vg_assert(ec);
+ VG_(pp_ExeContext)( ec );
}
-
if (sigNo == VKI_SIGSEGV
&& info && info->si_code > VKI_SI_USER
&& info->si_code == VKI_SEGV_MAPERR) {
Modified: trunk/include/pub_tool_execontext.h
===================================================================
--- trunk/include/pub_tool_execontext.h 2007-12-19 11:01:13 UTC (rev 7303)
+++ trunk/include/pub_tool_execontext.h 2007-12-21 01:24:59 UTC (rev 7304)
@@ -57,6 +57,15 @@
extern
ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta );
+// Trivial version of VG_(record_ExeContext), which just records the
+// thread's current program counter but does not do any stack
+// unwinding. This is useful in some rare cases when we suspect the
+// stack might be outside mapped storage, and so unwinding
+// might cause a segfault. In this case we can at least safely
+// produce a one-element stack trace, which is better than nothing.
+extern
+ExeContext* VG_(record_depth_1_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.
|