This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Switch out and in of tfind mode, when handling an event, in non-stop mode.


When debugging in non-stop mode, we can be inspecting the
trace buffer (so called tfind mode), while the live
target is running (as opposed to stopped, not as opposed to dead).
As such, threads can still hit breakpoints, signals,
etc., while in tfind mode.  At least internal breakpoints
(such as thread event or shared library event breakpoint)
should be resolved as quickly as possible, and transparently.
GDB is indeed still able to handle those, since in non-stop
mode the target reports stop events asynchronously to
infrun, but, whatever reads/writes of memory, registers, etc. need
to be done while handling the event up until the thread is
resumed, _must_ be done on the live target, not on the
trace buffer.  Since to tfind or not tfind mode is global
state (all the way through to the target side as well),
we need to swap out and in of such mode.  Hence, this patch
below.  I've applied it.

-- 
Pedro Alves

2010-02-24  Pedro Alves  <pedro@codesourcery.com>
	    Stan Shebs  <stan@codesourcery.com>

	gdb/
	* tracepoint.h (set_traceframe_number)
	(cleanup_restore_current_traceframe): Declare.
	* tracepoint.c (set_traceframe_number): New.
	(struct current_traceframe_cleanup): New.
	(do_restore_current_traceframe_cleanup)
	(restore_current_traceframe_cleanup_dtor)
	(make_cleanup_restore_current_traceframe): New.
	* infrun.c: Include tracepoint.h.
	(fetch_inferior_event): Switch out and in of tfind mode.

---
 gdb/infrun.c     |   11 +++++++++
 gdb/tracepoint.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/tracepoint.h |    3 ++
 3 files changed, 75 insertions(+)

Index: src/gdb/tracepoint.c
===================================================================
--- src.orig/gdb/tracepoint.c	2010-02-17 16:37:23.000000000 +0000
+++ src/gdb/tracepoint.c	2010-02-24 00:55:00.000000000 +0000
@@ -2538,6 +2538,67 @@ get_traceframe_number (void)
   return traceframe_number;
 }
 
+/* Make the traceframe NUM be the current trace frame.  Does nothing
+   if NUM is already current.  */
+
+void
+set_traceframe_number (int num)
+{
+  int newnum;
+
+  if (traceframe_number == num)
+    {
+      /* Nothing to do.  */
+      return;
+    }
+
+  newnum = target_trace_find (tfind_number, num, 0, 0, NULL);
+
+  if (newnum != num)
+    warning (_("could not change traceframe"));
+
+  traceframe_number = newnum;
+
+  /* Changing the traceframe changes our view of registers and of the
+     frame chain.  */
+  registers_changed ();
+}
+
+/* A cleanup used when switching away and back from tfind mode.  */
+
+struct current_traceframe_cleanup
+{
+  /* The traceframe we were inspecting.  */
+  int traceframe_number;
+};
+
+static void
+do_restore_current_traceframe_cleanup (void *arg)
+{
+  struct current_traceframe_cleanup *old = arg;
+
+  set_traceframe_number (old->traceframe_number);
+}
+
+static void
+restore_current_traceframe_cleanup_dtor (void *arg)
+{
+  struct current_traceframe_cleanup *old = arg;
+
+  xfree (old);
+}
+
+struct cleanup *
+make_cleanup_restore_current_traceframe (void)
+{
+  struct current_traceframe_cleanup *old;
+
+  old = xmalloc (sizeof (struct current_traceframe_cleanup));
+  old->traceframe_number = traceframe_number;
+
+  return make_cleanup_dtor (do_restore_current_traceframe_cleanup, old,
+			    restore_current_traceframe_cleanup_dtor);
+}
 
 /* Given a number and address, return an uploaded tracepoint with that
    number, creating if necessary.  */
Index: src/gdb/tracepoint.h
===================================================================
--- src.orig/gdb/tracepoint.h	2010-01-17 15:51:54.000000000 +0000
+++ src/gdb/tracepoint.h	2010-02-24 00:44:25.000000000 +0000
@@ -140,6 +140,9 @@ extern void (*deprecated_trace_find_hook
 extern void (*deprecated_trace_start_stop_hook) (int start, int from_tty);
 
 int get_traceframe_number (void);
+void set_traceframe_number (int);
+struct cleanup *make_cleanup_restore_current_traceframe (void);
+
 void free_actions (struct breakpoint *);
 enum actionline_type validate_actionline (char **, struct breakpoint *);
 
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2010-02-17 01:22:10.000000000 +0000
+++ src/gdb/infrun.c	2010-02-24 00:55:37.000000000 +0000
@@ -51,6 +51,7 @@
 #include "record.h"
 #include "inline-frame.h"
 #include "jit.h"
+#include "tracepoint.h"
 
 /* Prototypes for local functions */
 
@@ -1761,6 +1762,16 @@ proceed (CORE_ADDR addr, enum target_sig
 			"infrun: proceed (addr=%s, signal=%d, step=%d)\n",
 			paddress (gdbarch, addr), siggnal, step);
 
+  /* We're handling a live event, so make sure we're doing live
+     debugging.  If we're looking at traceframes while the target is
+     running, we're going to need to get back to that mode after
+     handling the event.  */
+  if (non_stop)
+    {
+      make_cleanup_restore_current_traceframe ();
+      set_traceframe_number (-1);
+    }
+
   if (non_stop)
     /* In non-stop, each thread is handled individually.  The context
        must already be set to the right thread here.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]