- The option "--vgdb-stop-at=event1,event2,..." allows the user
to ask GDB server to stop before program execution, at the end
of the program execution and on Valgrind internal errors.
- A new monitor command "v.set hostvisibility" that allows GDB server
to provide access to Valgrind internal host status/memory.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13900 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
index e88afb0..f8a957b 100644
--- a/coregrind/m_libcassert.c
+++ b/coregrind/m_libcassert.c
@@ -33,6 +33,7 @@
#include "pub_core_vkiscnums.h"
#include "pub_core_libcsetjmp.h" // to keep threadstate.h happy
#include "pub_core_threadstate.h"
+#include "pub_core_gdbserver.h"
#include "pub_core_aspacemgr.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
@@ -228,9 +229,33 @@
#define BACKTRACE_DEPTH 100 // nice and deep!
-/* Pull down the entire world */
-void VG_(exit)( Int status )
+__attribute__ ((__noreturn__))
+static void exit_wrk( Int status, Bool gdbserver_call_allowed)
{
+ static Bool exit_called = False;
+ // avoid recursive exit during gdbserver call.
+
+ if (gdbserver_call_allowed && !exit_called) {
+ const ThreadId atid = 1; // Arbitrary tid used to call/terminate gdbsrv.
+ exit_called = True;
+ if (status != 0 && VG_(gdbserver_stop_at) (VgdbStopAt_ValgrindAbExit)) {
+ if (VG_(gdbserver_init_done)()) {
+ VG_(umsg)("(action at valgrind abnormal exit) vgdb me ... \n");
+ VG_(gdbserver) (atid);
+ } else {
+ VG_(umsg)("(action at valgrind abnormal exit) "
+ "Early valgrind exit : vgdb not yet usable\n");
+ }
+ }
+ if (VG_(gdbserver_init_done)()) {
+ // Always terminate the gdbserver when Valgrind exits, so as
+ // to e.g. cleanup the FIFOs.
+ VG_(gdbserver_exit) (atid,
+ status == 0 ? VgSrc_ExitProcess : VgSrc_FatalSig);
+ }
+ }
+ exit_called = True;
+
#if defined(VGO_linux)
(void)VG_(do_syscall1)(__NR_exit_group, status );
#elif defined(VGO_darwin)
@@ -245,6 +270,19 @@
*(volatile Int*)0 = 'x';
}
+/* Pull down the entire world */
+void VG_(exit)( Int status )
+{
+ exit_wrk (status, True);
+}
+
+/* Pull down the entire world */
+void VG_(client_exit)( Int status )
+{
+ exit_wrk (status, False);
+}
+
+
// Print the scheduler status.
static void show_sched_status_wrk ( Bool host_stacktrace,
Bool valgrind_stack_usage,
@@ -305,7 +343,8 @@
if (valgrind_stack_usage && stack != 0)
VG_(printf)("valgrind stack top usage: %ld of %ld\n",
VG_STACK_ACTIVE_SZB
- - VG_(am_get_VgStack_unused_szB)(stack, VG_STACK_ACTIVE_SZB),
+ - VG_(am_get_VgStack_unused_szB)(stack,
+ VG_STACK_ACTIVE_SZB),
(SizeT) VG_STACK_ACTIVE_SZB);
}
VG_(printf)("\n");