]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
gdbserver: (#214909 c 82)
authorJulian Seward <jseward@acm.org>
Tue, 17 May 2011 18:14:53 +0000 (18:14 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 17 May 2011 18:14:53 +0000 (18:14 +0000)
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, philippe.waroquiers@skynet.be)

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11771

coregrind/m_gdbserver/m_gdbserver.c
coregrind/m_scheduler/scheduler.c
coregrind/m_syswrap/syswrap-aix5.c
coregrind/m_syswrap/syswrap-darwin.c
coregrind/m_syswrap/syswrap-generic.c
coregrind/pub_core_gdbserver.h

index cfde922eff3bd349e26dbceddf757d2dc816c397..e3b0ffb71a864459a71969b5895e16715341a90e 100644 (file)
@@ -494,6 +494,24 @@ static void invalidate_current_ip (ThreadId tid, char *who)
    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 @@ static void gdbserver_cleanup_in_child_after_fork(ThreadId me)
       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.
index 6d06947238bbd45c9f83b03951d9134d00d21223..a5d1cfb14c5f7025a4376e6987c25528dbb596ca 100644 (file)
@@ -1042,18 +1042,7 @@ VgSchedReturnCode VG_(scheduler) ( ThreadId tid )
          /* 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) ();
       }
index 8c4560682cde559f2b92c255c9b7e57a5939518a..c765a3bdb10c8dd5574b33b36103723643271b8c 100644 (file)
@@ -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 @@ PRE(sys_execve)
    /* 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.) */
index c1884dfa92c1e8c44fb36542888792fedfcefc6d..463b33fbdb3c583c7daa99926e3f2ea1577cbe78 100644 (file)
@@ -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 @@ PRE(posix_spawn)
    /* 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) {
index 436214093385c1bd87e9eaff6f8e2c756b71c4e8..fd6927fd015fc1a2551ec7ea3c160e684ea416be 100644 (file)
@@ -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 @@ PRE(sys_execve)
    /* 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.) */
index 27ed10e582b307b8cde14462380a13efe5ef3699..202d89bc84f0ad0a5ec6761b050032c8adab5d98 100644 (file)
 
 #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.