|
From: <sv...@va...> - 2011-05-17 18:15:01
|
Author: sewardj
Date: 2011-05-17 19:14:53 +0100 (Tue, 17 May 2011)
New Revision: 11771
Log:
gdbserver: (#214909 c 82)
ensure proper cleanup of gdbsrv FIFOs/shmem files with untraced fork/exec
* syswrap-{generic|darwin|aix5}.c : in PRE(sys_execve) : terminate gdbserver
* pub_core_gdbserver.h and m_gdbserver.c : add VG_(gdbserver_prerun_action),
factorising the actions to do by gdbserver at "startup" (i.e. a traced
fork or a traced exec).
* scheduler.c : implement startup action using VG_(gdbserver_prerun_action)
(Philippe Waroquiers, phi...@sk...)
Modified:
trunk/coregrind/m_gdbserver/m_gdbserver.c
trunk/coregrind/m_scheduler/scheduler.c
trunk/coregrind/m_syswrap/syswrap-aix5.c
trunk/coregrind/m_syswrap/syswrap-darwin.c
trunk/coregrind/m_syswrap/syswrap-generic.c
trunk/coregrind/pub_core_gdbserver.h
Modified: trunk/coregrind/m_gdbserver/m_gdbserver.c
===================================================================
--- trunk/coregrind/m_gdbserver/m_gdbserver.c 2011-05-17 17:15:07 UTC (rev 11770)
+++ trunk/coregrind/m_gdbserver/m_gdbserver.c 2011-05-17 18:14:53 UTC (rev 11771)
@@ -494,6 +494,24 @@
invalidate_if_jump_not_yet_gdbserved (VG_(get_IP) (tid), who);
}
+void VG_(gdbserver_prerun_action) (ThreadId tid)
+{
+ // Using VG_(dyn_vgdb_error) allows the user to control if gdbserver
+ // stops after a fork.
+ if (VG_(dyn_vgdb_error) == 0) {
+ /* The below call allows gdb to attach at startup
+ before the first guest instruction is executed. */
+ VG_(umsg)("(action at startup) vgdb me ... \n");
+ VG_(gdbserver)(tid);
+ } else {
+ /* User has activated gdbserver => initialize now the FIFOs
+ to let vgdb/gdb contact us either via the scheduler poll
+ mechanism or via vgdb ptrace-ing valgrind. */
+ if (VG_(gdbserver_activity) (tid))
+ VG_(gdbserver) (tid);
+ }
+}
+
/* when fork is done, various cleanup is needed in the child process.
In particular, child must have its own connection to avoid stealing
data from its parent */
@@ -521,6 +539,11 @@
vg_assert (gs_addresses == NULL);
vg_assert (gs_watches == NULL);
}
+
+
+ if (VG_(clo_trace_children)) {
+ VG_(gdbserver_prerun_action) (me);
+ }
}
/* If reason is init_reason, creates the connection resources (e.g.
Modified: trunk/coregrind/m_scheduler/scheduler.c
===================================================================
--- trunk/coregrind/m_scheduler/scheduler.c 2011-05-17 17:15:07 UTC (rev 11770)
+++ trunk/coregrind/m_scheduler/scheduler.c 2011-05-17 18:14:53 UTC (rev 11771)
@@ -1042,18 +1042,7 @@
/* As we are initializing, VG_(dyn_vgdb_error) can't have been
changed yet. */
- if (VG_(dyn_vgdb_error) == 0) {
- /* The below call allows gdb to attach at startup
- before the first guest instruction is executed. */
- VG_(umsg)("(action at startup) vgdb me ... \n");
- VG_(gdbserver)(1);
- } else {
- /* User has activated gdbserver => initialize now the FIFOs
- to let vgdb/gdb contact us either via the scheduler poll
- mechanism or via vgdb ptrace-ing valgrind. */
- if (VG_(gdbserver_activity) (1))
- VG_(gdbserver) (1);
- }
+ VG_(gdbserver_prerun_action) (1);
} else {
VG_(disable_vgdb_poll) ();
}
Modified: trunk/coregrind/m_syswrap/syswrap-aix5.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-aix5.c 2011-05-17 17:15:07 UTC (rev 11770)
+++ trunk/coregrind/m_syswrap/syswrap-aix5.c 2011-05-17 18:14:53 UTC (rev 11771)
@@ -45,6 +45,7 @@
#include "pub_core_xarray.h"
#include "pub_core_clientstate.h"
#include "pub_core_debuglog.h"
+#include "pub_tool_gdbserver.h" // VG_(gdbserver)
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
#include "pub_core_libcfile.h"
@@ -892,6 +893,15 @@
/* After this point, we can't recover if the execve fails. */
VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1);
+ // Terminate gdbserver if it is active.
+ if (VG_(clo_vgdb) != Vg_VgdbNo) {
+ // If the child will not be traced, we need to terminate gdbserver
+ // to cleanup the gdbserver resources (e.g. the FIFO files).
+ // If child will be traced, we also terminate gdbserver: the new
+ // Valgrind will start a fresh gdbserver after exec.
+ VG_(gdbserver) (0);
+ }
+
/* Resistance is futile. Nuke all other threads. POSIX mandates
this. (Really, nuke them all, since the new process will make
its own new thread.) */
Modified: trunk/coregrind/m_syswrap/syswrap-darwin.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-darwin.c 2011-05-17 17:15:07 UTC (rev 11770)
+++ trunk/coregrind/m_syswrap/syswrap-darwin.c 2011-05-17 18:14:53 UTC (rev 11771)
@@ -41,6 +41,7 @@
#include "pub_core_debuglog.h"
#include "pub_core_debuginfo.h" // VG_(di_notify_*)
#include "pub_core_transtab.h" // VG_(discard_translations)
+#include "pub_tool_gdbserver.h" // VG_(gdbserver)
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
#include "pub_core_libcfile.h"
@@ -2787,6 +2788,15 @@
/* Ok. So let's give it a try. */
VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (Char*)ARG2);
+ // Terminate gdbserver if it is active.
+ if (VG_(clo_vgdb) != Vg_VgdbNo) {
+ // If the child will not be traced, we need to terminate gdbserver
+ // to cleanup the gdbserver resources (e.g. the FIFO files).
+ // If child will be traced, we also terminate gdbserver: the new
+ // Valgrind will start a fresh gdbserver after exec.
+ VG_(gdbserver) (tid);
+ }
+
// Set up the child's exe path.
//
if (trace_this_child) {
Modified: trunk/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-generic.c 2011-05-17 17:15:07 UTC (rev 11770)
+++ trunk/coregrind/m_syswrap/syswrap-generic.c 2011-05-17 18:14:53 UTC (rev 11771)
@@ -43,6 +43,7 @@
#include "pub_core_clientstate.h" // VG_(brk_base), VG_(brk_limit)
#include "pub_core_debuglog.h"
#include "pub_core_errormgr.h"
+#include "pub_tool_gdbserver.h" // VG_(gdbserver)
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
#include "pub_core_libcfile.h"
@@ -2603,6 +2604,16 @@
/* After this point, we can't recover if the execve fails. */
VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1);
+
+ // Terminate gdbserver if it is active.
+ if (VG_(clo_vgdb) != Vg_VgdbNo) {
+ // If the child will not be traced, we need to terminate gdbserver
+ // to cleanup the gdbserver resources (e.g. the FIFO files).
+ // If child will be traced, we also terminate gdbserver: the new
+ // Valgrind will start a fresh gdbserver after exec.
+ VG_(gdbserver) (0);
+ }
+
/* Resistance is futile. Nuke all other threads. POSIX mandates
this. (Really, nuke them all, since the new process will make
its own new thread.) */
Modified: trunk/coregrind/pub_core_gdbserver.h
===================================================================
--- trunk/coregrind/pub_core_gdbserver.h 2011-05-17 17:15:07 UTC (rev 11770)
+++ trunk/coregrind/pub_core_gdbserver.h 2011-05-17 18:14:53 UTC (rev 11771)
@@ -32,6 +32,14 @@
#include "pub_tool_gdbserver.h"
+
+// After a fork or after an exec, call the below to (possibly) terminate
+// the previous gdbserver and then activate a new gdbserver
+// before any guest code execution, to e.g. allow the user to set
+// breakpoints before execution.
+// If VG_(clo_vgdb) == No, the below has no effect.
+void VG_(gdbserver_prerun_action) (ThreadId tid);
+
// True if there is some activity from vgdb
// If it returns True, then extern void VG_(gdbserver) can be called
// to handle this incoming vgdb request.
|