]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
- The option "--vgdb-stop-at=event1,event2,..." allows the user
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Sun, 20 Apr 2014 13:41:10 +0000 (13:41 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Sun, 20 Apr 2014 13:41:10 +0000 (13:41 +0000)
  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

17 files changed:
NEWS
coregrind/m_gdbserver/m_gdbserver.c
coregrind/m_gdbserver/remote-utils.c
coregrind/m_gdbserver/server.c
coregrind/m_gdbserver/target.c
coregrind/m_gdbserver/target.h
coregrind/m_libcassert.c
coregrind/m_main.c
coregrind/m_options.c
coregrind/pub_core_gdbserver.h
coregrind/pub_core_libcassert.h
coregrind/pub_core_options.h
docs/xml/manual-core-adv.xml
docs/xml/manual-core.xml
gdbserver_tests/mchelp.stdoutB.exp
none/tests/cmdline1.stdout.exp
none/tests/cmdline2.stdout.exp

diff --git a/NEWS b/NEWS
index 8f2ffa37c6ac7b268ac035efc58a169520b90815..a5be437ed1360bc472f36ab1cc611a4cfc7a2afa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -24,9 +24,16 @@ Release 3.10.0 (?? ?????? 201?)
 
 * New and modified GDB server monitor features:
 
+  - 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.info stats" that shows various valgrind core and
     tool statistics.
 
+  - A new monitor command "v.set hostvisibility" that allows GDB server
+    to provide access to Valgrind internal host status/memory.
+
 * ==================== FIXED BUGS ====================
 
 The following bugs have been fixed or resolved.  Note that "n-i-bz"
index 1da1e950b2609fb35cb0aec9a970e7f47c2f0729..95edeaf40aa811ef46eb770b541561fb169c7eaf 100644 (file)
@@ -588,11 +588,22 @@ static void invalidate_current_ip (ThreadId tid, const HChar *who)
    invalidate_if_jump_not_yet_gdbserved (VG_(get_IP) (tid), who);
 }
 
+Bool VG_(gdbserver_init_done) (void)
+{
+   return gdbserver_called > 0;
+}
+
+Bool VG_(gdbserver_stop_at) (VgdbStopAt stopat)
+{
+   return gdbserver_called > 0 && VgdbStopAtiS(stopat, VG_(clo_vgdb_stop_at));
+}
+
 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) {
+   if (VG_(dyn_vgdb_error) == 0 
+       || VgdbStopAtiS(VgdbStopAt_Startup, VG_(clo_vgdb_stop_at))) {
       /* The below call allows gdb to attach at startup
          before the first guest instruction is executed. */
       VG_(umsg)("(action at startup) vgdb me ... \n");
@@ -1457,7 +1468,8 @@ void VG_(gdbserver_status_output)(void)
        "interrupts intr_tid %d gs_non_busy %d gs_busy %d tid_non_intr %d\n"
        "gdbserved addresses %d (-1 = not initialized)\n"
        "watchpoints %d (-1 = not initialized)\n"
-       "vgdb-error %d\n",
+       "vgdb-error %d\n"
+       "hostvisibility %s\n",
        gdbserver_called,
        valgrind_single_stepping(),
        
@@ -1468,5 +1480,6 @@ void VG_(gdbserver_status_output)(void)
        
        nr_gdbserved_addresses,
        nr_watchpoints,
-       VG_(dyn_vgdb_error));
+       VG_(dyn_vgdb_error),
+       hostvisibility ? "yes" : "no");
 }
index 6916fc0cb666ae7ed05a94a44cca918f1b09af52..9de8d99b8e3aab1926a8cb1d9ce5f1b126ec83f0 100644 (file)
@@ -407,21 +407,23 @@ void remote_close (void)
 {
    const int pid = VG_(getpid)();
    remote_finish(orderly_finish);
-   if (pid == pid_from_to_creator) {
-      dlog(1, "unlinking\n    %s\n    %s\n    %s\n", 
-           from_gdb, to_gdb, shared_mem);
-      if (VG_(unlink) (from_gdb) == -1)
-         warning ("could not unlink %s\n", from_gdb);
-      if (VG_(unlink) (to_gdb) == -1)
-         warning ("could not unlink %s\n", to_gdb);
-      if (VG_(unlink) (shared_mem) == -1)
-         warning ("could not unlink %s\n", shared_mem);
-   }
-   else {
-      dlog(1, "not creator => not unlinking %s and %s\n", from_gdb, to_gdb);
-   }
+   dlog(1, "%d (creator %d) maybe unlinking \n    %s\n    %s\n    %s\n", 
+        pid, pid_from_to_creator,
+        from_gdb ? from_gdb : "NULL",
+        to_gdb ? to_gdb : "NULL",
+        shared_mem ? shared_mem : "NULL");
+   if (pid == pid_from_to_creator && from_gdb && VG_(unlink) (from_gdb) == -1)
+      warning ("could not unlink %s\n", from_gdb);
+   if (pid == pid_from_to_creator && to_gdb && VG_(unlink) (to_gdb) == -1)
+      warning ("could not unlink %s\n", to_gdb);
+   if (pid == pid_from_to_creator && shared_mem && VG_(unlink) (shared_mem) == -1)
+      warning ("could not unlink %s\n", shared_mem);
    free (from_gdb);
+   from_gdb = NULL;
    free (to_gdb);
+   to_gdb = NULL;
+   free (shared_mem);
+   shared_mem = NULL;
 }
 
 Bool remote_connected(void)
index 3027a8caf51fd4f540a4f4371cf0adf4e20d9842..45498d6e2371f6d4d1b0947b70febfe3a2727ce6 100644 (file)
@@ -119,7 +119,6 @@ static
 void kill_request (const char *msg)
 {
    VG_(umsg) ("%s", msg);
-   remote_close();
    VG_(exit) (0);
 }
 
@@ -243,6 +242,8 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
 "  v.info scheduler        : show valgrind thread state and stacktrace\n"
 "  v.info stats            : show various valgrind and tool stats\n"
 "  v.set debuglog <level>  : set valgrind debug log level to <level>\n"
+"  v.set hostvisibility [yes*|no] : (en/dis)ables access by gdb/gdbserver to\n"
+"    Valgrind internal host status/memory\n"
 "  v.translate <addr> [<traceflags>]  : debug translation of <addr> with <traceflags>\n"
 "    (default traceflags 0b00100000 : show after instrumentation)\n"
 "   An additional flag  0b100000000 allows to show gdbserver instrumentation\n");
@@ -253,7 +254,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
       wcmd = strtok_r (NULL, " ", &ssaveptr);
       switch (kwdid = VG_(keyword_id) 
               ("vgdb-error debuglog merge-recursive-frames"
-               " gdb_output log_output mixed_output",
+               " gdb_output log_output mixed_output hostvisibility ",
                wcmd, kwd_report_all)) {
       case -2:
       case -1: 
@@ -305,6 +306,32 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
          VG_(gdb_printf)
             ("valgrind output will go to log, interactive output will go to gdb\n");
          break;
+      case 6: /* hostvisibility */
+         wcmd = strtok_r (NULL, " ", &ssaveptr);
+         if (wcmd != NULL) {
+            switch (VG_(keyword_id) ("yes no", wcmd, kwd_report_all)) {
+            case -2:
+            case -1: break;
+            case  0: 
+               hostvisibility = True;
+               break;
+            case 1:
+               hostvisibility = False;
+               break;
+            default: tl_assert (0);
+            }
+         } else {
+            hostvisibility = True;
+         }
+         if (hostvisibility)
+            VG_(gdb_printf) 
+               ("Enabled access to Valgrind memory/status by GDB\n"
+                "If not yet done, tell GDB which valgrind file(s) to use:\n"
+                "add-symbol-file <tool or preloaded file> <loadaddr>\n");
+         else
+            VG_(gdb_printf)
+               ("Disabled access to Valgrind memory/status by GDB\n");
+         break;
       default:
          vg_assert (0);
       }
index ef459042c3afba2719b8295ca0d7ce56629362e5..faad83c207c1e95a0915a81b9b6b02199070efbd 100644 (file)
@@ -446,46 +446,55 @@ void valgrind_store_registers (int regno)
    usr_store_inferior_registers (regno);
 }
 
+Bool hostvisibility = False;
+
 int valgrind_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
 {
    const void *sourceaddr = C2v (memaddr);
    dlog(2, "reading memory %p size %d\n", sourceaddr, len);
-   if (!VG_(am_is_valid_for_client_or_free_or_resvn) ((Addr) sourceaddr, 
-                                                      len, VKI_PROT_READ)) {
+   if (VG_(am_is_valid_for_client_or_free_or_resvn) ((Addr) sourceaddr, 
+                                                      len, VKI_PROT_READ)
+       || (hostvisibility /* TBD: && check valgrind read accessibility */)) {
+      VG_(memcpy) (myaddr, sourceaddr, len);
+      return 0;
+   } else {
       dlog(1, "error reading memory %p size %d\n", sourceaddr, len);
       return -1;
    }
-   VG_(memcpy) (myaddr, sourceaddr, len);
-   return 0;
 }
 
 int valgrind_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
 {
+   Bool is_valid_client_memory;
    void *targetaddr = C2v (memaddr);
    dlog(2, "writing memory %p size %d\n", targetaddr, len);
-   if (!VG_(am_is_valid_for_client_or_free_or_resvn) ((Addr)targetaddr, 
-                                                      len, VKI_PROT_WRITE)) {
+   is_valid_client_memory 
+      = VG_(am_is_valid_for_client_or_free_or_resvn) ((Addr)targetaddr, 
+                                                      len, VKI_PROT_WRITE);
+   if (is_valid_client_memory
+       || (hostvisibility /* TBD: && check valgrind write accessibility */)) {
+      if (len > 0) {
+         VG_(memcpy) (targetaddr, myaddr, len);
+         if (is_valid_client_memory && VG_(tdict).track_post_mem_write) {
+            /* Inform the tool of the post memwrite.  Note that we do the
+               minimum necessary to avoid complains from e.g.
+               memcheck. The idea is that the debugger is as least
+               intrusive as possible.  So, we do not inform of the pre
+               mem write (and in any case, this would cause problems with
+               memcheck that does not like our CorePart in
+               pre_mem_write. */
+            ThreadState *tst = 
+               (ThreadState *) inferior_target_data (current_inferior);
+            ThreadId tid = tst->tid;
+            VG_(tdict).track_post_mem_write( Vg_CoreClientReq, tid,
+                                             (Addr) targetaddr, len );
+         }
+      }
+      return 0;
+   } else {
       dlog(1, "error writing memory %p size %d\n", targetaddr, len);
       return -1;
    }
-   if (len > 0) {
-      VG_(memcpy) (targetaddr, myaddr, len);
-      if (VG_(tdict).track_post_mem_write) {
-         /* Inform the tool of the post memwrite.  Note that we do the
-            minimum necessary to avoid complains from e.g.
-            memcheck. The idea is that the debugger is as least
-            intrusive as possible.  So, we do not inform of the pre
-            mem write (and in any case, this would cause problems with
-            memcheck that does not like our CorePart in
-            pre_mem_write. */
-         ThreadState *tst = 
-            (ThreadState *) inferior_target_data (current_inferior);
-         ThreadId tid = tst->tid;
-         VG_(tdict).track_post_mem_write( Vg_CoreClientReq, tid,
-                                          (Addr) targetaddr, len );
-      }
-   }
-   return 0;
 }
 
 /* insert or remove a breakpoint */
index 2b783ed3191775f4c807c76b3c8776949032c789..c98b976be53c016402fa61219df2a7a5aeeaad1c 100644 (file)
@@ -233,5 +233,8 @@ extern void  VG_(transfer) (void *valgrind,
                             Bool *mod);
 
 
+// True means gdbserver can access (internal) Valgrind memory.
+// Otherwise, only the client memory can be accessed.
+extern Bool hostvisibility;
 
 #endif /* TARGET_H */
index e88afb018873a200ef07a953487dc162f5e5fdd3..f8a957bab3cac67f28bfbebac7918af09bb117fb 100644 (file)
@@ -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"
 
 #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 @@ void VG_(exit)( Int status )
    *(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 @@ static void show_sched_status_wrk ( Bool host_stacktrace,
       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");
index 98192de8a5db5eec2e94d4bbf002e2c6dfb9fafa..51ff326fc52d43896d662fcbf996b6095902e75d 100644 (file)
@@ -108,6 +108,8 @@ static void usage_NORETURN ( Bool debug_help )
 "    --vgdb-error=<number>     invoke gdbserver after <number> errors [%d]\n"
 "                              to get started quickly, use --vgdb-error=0\n"
 "                              and follow the on-screen directions\n"
+"    --vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none]\n"
+"         where event is one of startup exit valgrindabexit all none\n"
 "    --track-fds=no|yes        track open file descriptors? [no]\n"
 "    --time-stamp=no|yes       add timestamps to log messages? [no]\n"
 "    --log-fd=<number>         log messages to file descriptor [2=stderr]\n"
@@ -537,6 +539,11 @@ void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd,
       }
       else if VG_INT_CLO (arg, "--vgdb-poll",      VG_(clo_vgdb_poll)) {}
       else if VG_INT_CLO (arg, "--vgdb-error",     VG_(clo_vgdb_error)) {}
+      else if VG_STR_CLO (arg, "--vgdb-stop-at", tmp_str) {
+         if (!VG_(parse_enum_set)("startup,exit,valgrindabexit", tmp_str,
+                                  &VG_(clo_vgdb_stop_at)))
+            VG_(fmsg_bad_option)(arg, "");
+      }
       else if VG_STR_CLO (arg, "--vgdb-prefix",    VG_(clo_vgdb_prefix)) {
          VG_(arg_vgdb_prefix) = arg;
       }
@@ -2414,7 +2421,13 @@ void shutdown_actions_NORETURN( ThreadId tid,
       vg_assert(VG_(count_living_threads)() >= 1);
    }
 
+   /* Final call to gdbserver, if requested. */
+   if (VG_(gdbserver_stop_at) (VgdbStopAt_Exit)) {
+      VG_(umsg)("(action at exit) vgdb me ... \n");
+      VG_(gdbserver) (tid);
+   }
    VG_(threads)[tid].status = VgTs_Empty;
+
    //--------------------------------------------------------------
    // Finalisation: cleanup, messages, etc.  Order not so important, only
    // affects what order the messages come.
@@ -2489,7 +2502,7 @@ void shutdown_actions_NORETURN( ThreadId tid,
    /* Flush any output cached by previous calls to VG_(message). */
    VG_(message_flush)();
 
-   /* terminate gdbserver if ever it was started. We terminate it here
+   /* Terminate gdbserver if ever it was started. We terminate it here
       so that it get the output above if output was redirected to
       gdb */
    VG_(gdbserver_exit) (tid, tids_schedretcode);
@@ -2508,11 +2521,11 @@ void shutdown_actions_NORETURN( ThreadId tid,
          if an error was found */
       if (VG_(clo_error_exitcode) > 0 
           && VG_(get_n_errs_found)() > 0) {
-         VG_(exit)( VG_(clo_error_exitcode) );
+         VG_(client_exit)( VG_(clo_error_exitcode) );
       } else {
          /* otherwise, return the client's exit code, in the normal
             way. */
-         VG_(exit)( VG_(threads)[tid].os_state.exitcode );
+         VG_(client_exit)( VG_(threads)[tid].os_state.exitcode );
       }
       /* NOT ALIVE HERE! */
       VG_(core_panic)("entered the afterlife in main() -- ExitT/P");
index 78ffe9d6ad7c0918aa25c76bb66c6f7a52f9bf24..7b8b141560f735ce2a656bb85323368c8353b246 100644 (file)
@@ -56,6 +56,7 @@ VgVgdb VG_(clo_vgdb)           = Vg_VgdbYes;
 #endif
 Int    VG_(clo_vgdb_poll)      = 5000; 
 Int    VG_(clo_vgdb_error)     = 999999999;
+UInt   VG_(clo_vgdb_stop_at)   = 0;
 const HChar *VG_(clo_vgdb_prefix)    = NULL;
 const HChar *VG_(arg_vgdb_prefix)    = NULL;
 Bool   VG_(clo_vgdb_shadow_registers) = False;
index 8059420ee2f38d3f733fa41663317df4a144702c..bfa306fc13f5bf0d82989224db880ca6950a7c3e 100644 (file)
@@ -31,6 +31,7 @@
 #define __PUB_CORE_GDBSERVER_H
 
 #include "pub_tool_gdbserver.h"
+#include "pub_core_options.h"
 #include "pub_core_threadstate.h"   // VgSchedReturnCode
 
 /* Return the default path prefix for the named pipes (FIFOs) used by vgdb/gdb
@@ -44,6 +45,13 @@ HChar* VG_(vgdb_prefix_default)(void);
 // If VG_(clo_vgdb) == No, the below has no effect.
 void VG_(gdbserver_prerun_action) (ThreadId tid);
 
+// True if the initialisation of gdbserver was done,
+// i.e. VG_(gdbserver_prerun_action) was called.
+Bool VG_(gdbserver_init_done) (void);
+
+// True if gdbserver should stop execution for the specified stop at reason
+Bool VG_(gdbserver_stop_at) (VgdbStopAt stopat);
+
 // 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.                                
index 0ca4e1f5dbeb08806e8a60836a287f0b2af37b9e..e9326a46104f957d407d52688eaa019accb68f18 100644 (file)
@@ -66,6 +66,9 @@ extern void  VG_(core_panic)      ( const HChar* str );
 __attribute__ ((__noreturn__))
 extern void  VG_(core_panic_at)   ( const HChar* str, UnwindStartRegs* );
 
+/* Exits with status as client exit code. */
+extern void VG_(client_exit)( Int status );
+
 /* Called when some unhandleable client behaviour is detected.
    Prints a msg and aborts. */
 extern void VG_(unimplemented) ( const HChar* msg )
index fb178fc19acd6304fbd1610e51e9e9fb761eafc0..83eef250ddceb8e3e526ad7522acf39e3525b961 100644 (file)
@@ -69,6 +69,26 @@ extern VgVgdb VG_(clo_vgdb);
 /* if > 0, checks every VG_(clo_vgdb_poll) BBS if vgdb wants to be served. */
 extern Int VG_(clo_vgdb_poll);
 
+/* Specify when Valgrind gdbserver stops the execution and wait
+   for a GDB to connect. */
+typedef
+   enum {                       // Stop :
+      VgdbStopAt_Startup,       // just before the client starts to execute.
+      VgdbStopAt_Exit,          // just before the client exits.
+      VgdbStopAt_ValgrindAbExit // on abnormal valgrind exit.
+   }
+   VgdbStopAt;
+// Build mask to check or set VgdbStop_At a membership
+#define VgdbStopAt2S(a) (1 << (a))
+// VgdbStopAt a is member of the Set s ?
+#define VgdbStopAtiS(a,s) ((s) & VgdbStopAt2S(a))
+// A set with all VgdbStopAt:
+#define VgdbStopAtallS \
+     (VgdbStopAt2S(VgdbStopAt_Startup) \
+    | VgdbStopAt2S(VgdbStopAt_Exit)    \
+    | VgdbStopAt2S(VgdbStopAt_ValgrindAbExit)
+extern UInt VG_(clo_vgdb_stop_at); // A set of VgdbStopAt reasons.
+
 /* prefix for the named pipes (FIFOs) used by vgdb/gdb to communicate with valgrind */
 extern const HChar *VG_(clo_vgdb_prefix);
 
index 1e6e22eb99e7e2f7a33bf834793877c8834c0f78..53f8b40149085a981feda0419739a4f0801a2810 100644 (file)
@@ -1455,6 +1455,40 @@ problems or bugs.</para>
     is detected.</para>
   </listitem>
 
+  <listitem>
+    <para><varname>v.set hostvisibility [yes*|no]</varname> The value
+    "yes" indicates to gdbserver that GDB can look at the Valgrind
+    'host' (internal) status/memory. "no" disables this access.
+    When hostvisibility is activated, GDB can e.g. look at Valgrind
+    global variables. As an example, to examine a Valgrind global
+    variable of the memcheck tool on an x86, do the following setup:</para>
+
+<screen><![CDATA[
+(gdb) monitor v.set hostvisibility yes
+(gdb) add-symbol-file /path/to/tool/executable/file/memcheck-x86-linux 0x38000000
+add symbol table from file "/path/to/tool/executable/file/memcheck-x86-linux" at
+       .text_addr = 0x38000000
+(y or n) y
+Reading symbols from /path/to/tool/executable/file/memcheck-x86-linux...done.
+(gdb) 
+]]></screen>
+
+  <para>After that, variables defined in memcheck-x86-linux can be accessed, e.g.</para>
+
+<screen><![CDATA[
+(gdb) p /x vgPlain_threads[1].os_state
+$3 = {lwpid = 0x4688, threadgroup = 0x4688, parent = 0x0, 
+  valgrind_stack_base = 0x62e78000, valgrind_stack_init_SP = 0x62f79fe0, 
+  exitcode = 0x0, fatalsig = 0x0}
+(gdb) p vex_control
+$5 = {iropt_verbosity = 0, iropt_level = 2, 
+  iropt_register_updates = VexRegUpdUnwindregsAtMemAccess, 
+  iropt_unroll_thresh = 120, guest_max_insns = 60, guest_chase_thresh = 10, 
+  guest_chase_cond = 0 '\000'}
+(gdb) 
+]]></screen>
+  </listitem>
+
   <listitem>
     <para><varname>v.translate &lt;address&gt;
     [&lt;traceflags&gt;]</varname> shows the translation of the block
index a69ca5898243b086b0a175de0e0c3a85473e93f4..dda3cfa9f4120fbd7c843079a872b36bf0faf32b 100644 (file)
@@ -777,6 +777,46 @@ in most cases.  We group the available options by rough categories.</para>
     </listitem>
   </varlistentry>
 
+  <varlistentry id="opt.vgdb-stop-at" xreflabel="--vgdb-stop-at">
+    <term>
+      <option><![CDATA[--vgdb-stop-at=<set> [default: none] ]]></option>
+    </term>
+    <listitem>
+      <para> Use this option when the Valgrind gdbserver is enabled with
+      <option>--vgdb=yes</option> or <option>--vgdb=full</option>.
+      The Valgrind gdbserver will be invoked for each error after
+      <option>--vgdb-error</option> have been reported.
+      You can additionally ask the Valgrind gdbserver to be invoked
+      for other events, specified in one of the following ways:  </para>
+      <itemizedlist>
+        <listitem><para>a comma separated list of one or more of
+            <option>startup exit valgrindabexit</option>.</para>
+
+          <para>The values <option>startup</option> <option>exit</option>
+          <option>valgrindabexit</option> respectively indicate to
+          invoke gdbserver before your program is executed, after the
+          last instruction of your program, on Valgrind abnormal exit
+          (e.g. internal error, out of memory, ...).</para>
+
+          <para>Note: <option>startup</option> and
+          <option>--vgdb-error=0</option> will both cause Valgrind
+          gdbserver to be invoked before your program is executed. The
+          <option>--vgdb-error=0</option> will in addition cause your 
+          program to stop on all subsequent errors.</para>
+
+        </listitem>
+        
+        <listitem><para><option>all</option> to specify the complete set.
+            It is equivalent to
+            <option>--vgdb-stop-at=startup,exit,valgrindabexit</option>.</para>
+        </listitem>
+        
+        <listitem><para><option>none</option> for the empty set.</para>
+        </listitem>
+      </itemizedlist>
+    </listitem>
+  </varlistentry>
+
   <varlistentry id="opt.track-fds" xreflabel="--track-fds">
     <term>
       <option><![CDATA[--track-fds=<yes|no> [default: no] ]]></option>
index 7dfd0c326b740570973e250e7bdf5c4e88f15778..765def38481da2308bb766e1e7c2bc589180988a 100644 (file)
@@ -64,6 +64,8 @@ debugging valgrind internals monitor commands:
   v.info scheduler        : show valgrind thread state and stacktrace
   v.info stats            : show various valgrind and tool stats
   v.set debuglog <level>  : set valgrind debug log level to <level>
+  v.set hostvisibility [yes*|no] : (en/dis)ables access by gdb/gdbserver to
+    Valgrind internal host status/memory
   v.translate <addr> [<traceflags>]  : debug translation of <addr> with <traceflags>
     (default traceflags 0b00100000 : show after instrumentation)
    An additional flag  0b100000000 allows to show gdbserver instrumentation
index 0216879f2b29e7e4c4e67bdace7bddb7675ee672..0bdd5e6ab1ba7bee2d95ca47a7eee4ceaa81c124 100644 (file)
@@ -21,6 +21,8 @@ usage: valgrind [options] prog-and-args
     --vgdb-error=<number>     invoke gdbserver after <number> errors [999999999]
                               to get started quickly, use --vgdb-error=0
                               and follow the on-screen directions
+    --vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none]
+         where event is one of startup exit valgrindabexit all none
     --track-fds=no|yes        track open file descriptors? [no]
     --time-stamp=no|yes       add timestamps to log messages? [no]
     --log-fd=<number>         log messages to file descriptor [2=stderr]
index 5c4e8c0cac9e3885ea62c9146732ea91c0504fc7..bc47f1ee87b2f8d11f5a4be0f9257fc68d650ebf 100644 (file)
@@ -21,6 +21,8 @@ usage: valgrind [options] prog-and-args
     --vgdb-error=<number>     invoke gdbserver after <number> errors [999999999]
                               to get started quickly, use --vgdb-error=0
                               and follow the on-screen directions
+    --vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none]
+         where event is one of startup exit valgrindabexit all none
     --track-fds=no|yes        track open file descriptors? [no]
     --time-stamp=no|yes       add timestamps to log messages? [no]
     --log-fd=<number>         log messages to file descriptor [2=stderr]