From: Julian Seward Date: Fri, 21 Dec 2007 01:24:59 +0000 (+0000) Subject: Add a new method VG_(record_depth_1_ExeContext), a trivial derivative X-Git-Tag: svn/VALGRIND_3_4_0~1124 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=da0726854c72d53dfc56bda33d81e7595237322f;p=thirdparty%2Fvalgrind.git 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. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7304 --- diff --git a/coregrind/m_execontext.c b/coregrind/m_execontext.c index 0f203793b1..eae88a000a 100644 --- a/coregrind/m_execontext.c +++ b/coregrind/m_execontext.c @@ -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 @@ static void resize_ec_htab ( void ) 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 @@ ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta ) 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 @@ ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta ) 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; diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index de2b49b912..9745d2c721 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -1275,7 +1275,7 @@ static void default_action(const vki_siginfo_t *info, ThreadId tid) case VKI_BUS_OBJERR: event = "Hardware error"; break; } break; - } + } /* switch (sigNo) */ if (event != NULL) { if (haveaddr) @@ -1285,11 +1285,17 @@ static void default_action(const vki_siginfo_t *info, ThreadId tid) 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) { diff --git a/include/pub_tool_execontext.h b/include/pub_tool_execontext.h index 917281c62f..000d225a40 100644 --- a/include/pub_tool_execontext.h +++ b/include/pub_tool_execontext.h @@ -57,6 +57,15 @@ typedef 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.