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]

Re: [RFA] Reverse debugging, part 3/3: user interface / docs


Hi Eli,

Please see revised patch, attached.
OK now?

Thanks,
Michael

Eli Zaretskii wrote:
Date: Fri, 31 Mar 2006 14:19:05 -0800
From: Michael Snyder <msnyder@redhat.com>

+   switch (dir) {
+   case EXEC_FORWARD:
+     fprintf_filtered (out, "Forward.\n");
+     break;
+   case EXEC_REVERSE:
+     fprintf_filtered (out, "Reverse.\n");
+     break;
+   case EXEC_ERROR:
+   default:
+     error (_("Target `%s' does not support execution-direction."),
+ 	   target_shortname);
+     break;
+   }


Did you really mean for "Forward" and "Reverse" to be untranslated (as
opposed to the error text)?  If so, please explain why.  If not,
please add _().


+ }
+ + /* User interface:
+ reverse-step, reverse-next etc.
+ (returns error unles target implements to_set_execdir method). */
+ + static void execdir_default (void *notused)
+ {
+ /* Return execution direction to default state. */
+ target_set_execution_direction (EXEC_FORWARD);
+ }
+ + static void
+ exec_reverse_once (char *cmd, char *args, int from_tty)
+ {
+ /* String buffer for command consing. */
+ char reverse_command[512];
[...]
+ sprintf (reverse_command, "%s %s", cmd, args ? args : "");


Don't we have xstrprintf and friends to avoid buffers with arbitrary
sizes?


+ void
+ _initialize_reverse (void)
+ {
+   add_setshow_enum_cmd ("exec-direction", class_run, exec_direction_names,
+ 			&exec_direction, "Set direction of execution.\n\
+ Options are 'forward' or 'reverse'.",
+ 			"Show direction of execution (forward/reverse).",
+ 			"Tells gdb whether to execute forward or backward.",
+ 			set_exec_direction_func, show_exec_direction_func,
+ 			&setlist, &showlist);


The doc strings should be wrapped in _().

Also, I think "Tell" is more consistent with the rest of doc strings
than "Tells".


+ @node Reverse Execution
+ @chapter Running programs backward


Please add "@cindex reverse execution" here.


+ If the target environment supports it, @value{GDBN} can allow you to
+ ``rewind'' the program by running it backward.


"GDB allows you to ``rewind'' the program...".  ``Can allow'' implies
that you need to do something before it allows.


+ program was executing normally. Variables, registers etc. should


"etc.@:", since the period doesn't end a sentence.


+ Behavior of + asynchronous signals depends on the target environment.


This is too vague.  Can we at least mention the possible behaviors, or
just the most common/expected ones?  The reader should get some idea
of what might happen.


+ @item reverse-step @r{[}@var{count}@r{]}
+ Run the program backward until control reaches the start of a
+ different source line


Isn't it better to say

  Run the program backwards until control reaches the first instruction
  of a different source line

? In any case, "backwards", not "backward".

; then stop it, and return control to @value{GDBN}.

+ + Like the @code{step} command, @code{reverse-step} will only stop
+ at the beginning of a source line. It ``un-executes'' the previously
+ executed source line. If the previous source line included calls to + debuggable functions, @code{reverse-step} will step (backward) into
+ the called function, stopping at the beginning of the @emph{last}
+ statement in the called function (typically a return statement).


This ``last statement'' is not entirely accurate, I think.  What
happens in a function that has several return statements? we will wind
up at the one thru which it returned on the way forward, right?


+ @item set exec-direction + Set the direction of target execution.
+ @itemx set exec-direction reverse


Please add a @kindex entry for this command.


Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.809
diff -u -r1.809 Makefile.in
--- Makefile.in	9 Apr 2006 08:22:42 -0000	1.809
+++ Makefile.in	17 Apr 2006 23:43:53 -0000
@@ -543,7 +543,7 @@
 	objfiles.c osabi.c observer.c \
 	p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
 	prologue-value.c \
-	regcache.c reggroups.c remote.c remote-fileio.c \
+	regcache.c reggroups.c remote.c remote-fileio.c reverse.c \
 	scm-exp.c scm-lang.c scm-valprint.c \
 	sentinel-frame.c \
 	serial.c ser-base.c ser-unix.c \
@@ -928,7 +928,8 @@
 	signals.o \
 	kod.o kod-cisco.o \
 	gdb-events.o \
-	exec.o bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o \
+	exec.o reverse.o \
+	bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o \
 	dbxread.o coffread.o coff-pe-read.o elfread.o \
 	dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
@@ -2495,6 +2496,8 @@
 remote-utils.o: remote-utils.c $(defs_h) $(gdb_string_h) $(gdbcmd_h) \
 	$(target_h) $(serial_h) $(gdbcore_h) $(inferior_h) $(remote_utils_h) \
 	$(regcache_h)
+reverse.o: reverse.c $(defs_h) $(gdb_string_h) $(target_h) $(cli_cmds_h) \
+	$(cli_decode_h) $(top_h)
 rom68k-rom.o: rom68k-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
 	$(serial_h) $(regcache_h) $(value_h) $(m68k_tdep_h)
 rs6000-nat.o: rs6000-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \
Index: reverse.c
===================================================================
RCS file: reverse.c
diff -N reverse.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ reverse.c	17 Apr 2006 23:43:53 -0000
@@ -0,0 +1,199 @@
+/* Reverse execution and reverse debugging.
+
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "target.h"
+#include "top.h"
+#include "cli/cli-cmds.h"
+#include "cli/cli-decode.h"
+
+/* User interface for reverse debugging:
+   Set exec-direction / show exec-direction commands
+   (returns error unles target implements to_set_execdir method).  */
+
+static const char exec_forward[] = _("forward");
+static const char exec_reverse[] = _("reverse");
+static const char *exec_direction = exec_forward;
+static const char *exec_direction_names[] = {
+  exec_forward,
+  exec_reverse,
+  NULL
+};
+
+static void
+set_exec_direction_func (char *args, int from_tty, 
+			 struct cmd_list_element *cmd)
+{
+  if (target_get_execution_direction () != EXEC_ERROR)
+    {
+      enum exec_direction_kind dir = EXEC_ERROR;
+
+      if (!strcmp (exec_direction, exec_forward))
+	dir = EXEC_FORWARD;
+      else if (!strcmp (exec_direction, exec_reverse))
+	dir = EXEC_REVERSE;
+
+      if (target_set_execution_direction (dir) != EXEC_ERROR)
+	return;
+    }
+  error (_("Target `%s' does not support execution-direction."),
+	 target_shortname);
+}
+
+static void
+show_exec_direction_func (struct ui_file *out, int from_tty, 
+			  struct cmd_list_element *cmd, const char *value)
+{
+  enum exec_direction_kind dir = target_get_execution_direction ();
+
+  switch (dir) {
+  case EXEC_FORWARD:
+    fprintf_filtered (out, _("Forward.\n"));
+    break;
+  case EXEC_REVERSE:
+    fprintf_filtered (out, _("Reverse.\n"));
+    break;
+  case EXEC_ERROR:
+  default:
+    error (_("Target `%s' does not support execution-direction."),
+	   target_shortname);
+    break;
+  }
+}
+
+/* User interface:
+   reverse-step, reverse-next etc.
+   (returns error unles target implements to_set_execdir method).  */
+
+static void execdir_default (void *notused)
+{
+  /* Return execution direction to default state.  */
+  target_set_execution_direction (EXEC_FORWARD);
+}
+
+static void
+exec_reverse_once (char *cmd, char *args, int from_tty)
+{
+  /* String buffer for command consing.  */
+  char *reverse_command;
+  enum exec_direction_kind dir = target_get_execution_direction ();
+
+  if (dir == EXEC_ERROR)
+    error (_("Target %s does not support this command."), target_shortname);
+
+  if (dir == EXEC_REVERSE)
+    error (_("Already in reverse mode.  Use '%s' or 'set exec-dir forward'."),
+	   cmd);
+
+  if (target_set_execution_direction (EXEC_REVERSE) == EXEC_ERROR)
+    error (_("Target %s does not support this command."), target_shortname);
+
+  make_cleanup (execdir_default, NULL);
+  reverse_command = xstrprintf ("%s %s", cmd, args ? args : "");
+  make_cleanup (xfree, reverse_command);
+  execute_command (reverse_command, from_tty);
+}
+
+static void
+reverse_step (char *args, int from_tty)
+{
+  exec_reverse_once ("step", args, from_tty);
+}
+
+static void
+reverse_stepi (char *args, int from_tty)
+{
+  exec_reverse_once ("stepi", args, from_tty);
+}
+
+static void
+reverse_next (char *args, int from_tty)
+{
+  exec_reverse_once ("next", args, from_tty);
+}
+
+static void
+reverse_nexti (char *args, int from_tty)
+{
+  exec_reverse_once ("nexti", args, from_tty);
+}
+
+static void
+reverse_continue (char *args, int from_tty)
+{
+  exec_reverse_once ("continue", args, from_tty);
+}
+
+static void
+reverse_finish (char *args, int from_tty)
+{
+  exec_reverse_once ("finish", args, from_tty);
+}
+
+void
+_initialize_reverse (void)
+{
+  add_setshow_enum_cmd ("exec-direction", class_run, exec_direction_names,
+			&exec_direction, _(\
+"Set direction of execution.\n\
+Options are 'forward' or 'reverse'."), _("\
+Show direction of execution (forward/reverse)."), _("\
+Tell gdb whether to execute forward or backward."),
+			set_exec_direction_func, show_exec_direction_func,
+			&setlist, &showlist);
+
+  add_com ("reverse-step", class_run, reverse_step, _("\
+Step program backward until it reaches the beginning of another source line.\n\
+Argument N means do this N times (or till program stops for another reason).")
+	   );
+  add_com_alias ("rs", "reverse-step", class_alias, 1);
+
+  add_com ("reverse-next", class_run, reverse_next, _("\
+Step program backward, proceeding through subroutine calls.\n\
+Like the \"reverse-step\" command as long as subroutine calls do not happen;\n\
+when they do, the call is treated as one instruction.\n\
+Argument N means do this N times (or till program stops for another reason).")
+	   );
+  add_com_alias ("rn", "reverse-next", class_alias, 1);
+
+  add_com ("reverse-stepi", class_run, reverse_stepi, _("\
+Step backward exactly one instruction.\n\
+Argument N means do this N times (or till program stops for another reason).")
+	   );
+  add_com_alias ("rsi", "reverse-stepi", class_alias, 0);
+
+  add_com ("reverse-nexti", class_run, reverse_nexti, _("\
+Step backward one instruction, but proceed through called subroutines.\n\
+Argument N means do this N times (or till program stops for another reason).")
+	   );
+  add_com_alias ("rni", "reverse-nexti", class_alias, 0);
+
+  add_com ("reverse-continue", class_run, reverse_continue, _("\
+Continue program being debugged, running in reverse.\n\
+If proceeding from breakpoint, a number N may be used as an argument,\n\
+which means to set the ignore count of that breakpoint to N - 1 (so that\n\
+the breakpoint won't break until the Nth time it is reached)."));
+  add_com_alias ("rc", "reverse-continue", class_alias, 0);
+
+  add_com ("reverse-finish", class_run, reverse_finish, _("\
+Execute backward until just before selected stack frame is called."));
+}
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.322
diff -u -r1.322 gdb.texinfo
--- doc/gdb.texinfo	14 Apr 2006 18:31:32 -0000	1.322
+++ doc/gdb.texinfo	17 Apr 2006 23:43:58 -0000
@@ -127,6 +127,7 @@
 * Commands::                    @value{GDBN} commands
 * Running::                     Running programs under @value{GDBN}
 * Stopping::                    Stopping and continuing
+* Reverse Execution::           Running programs backward
 * Stack::                       Examining the stack
 * Source::                      Examining source files
 * Data::                        Examining data
@@ -4312,6 +4313,111 @@
 @end table
 
 
+@node Reverse Execution
+@chapter Running programs backward
+@cindex reverse execution
+
+When you are debugging a program, it is not unusual to realize that
+you have gone too far, and some event of interest has already happened.
+If the target environment supports it, @value{GDBN} allows you to
+``rewind'' the program by running it backward.
+
+A target environment that supports reverse execution should be able
+to ``undo'' the changes in machine state that have taken place as the
+program was executing normally.  Variables, registers etc.@: should 
+revert to their previous values.  Obviously this requires a great
+deal of sophistication on the part of the target environment; not
+all target environments can support reverse execution.
+
+When a program is executed in reverse, the instructions that 
+have most recently been executed are ``un-executed'', in reverse
+order.  The program counter runs backward, following the previous
+thread of execution in reverse.  As each instruction is ``un-executed'', 
+the values of memory and/or registers that were changed by that 
+instruction are reverted to their previous states.  After executing
+a piece of source code in reverse, all side effects of that code
+should be ``undone'', and all variables should be returned to their
+prior values.
+
+Assuming you are debugging in a target environment that supports
+reverse execution, @value{GDBN} provides the following commands.
+
+@table @code
+@kindex reverse-continue
+@kindex rc @r{(@code{reverse-continue})}
+@item reverse-continue @r{[}@var{ignore-count}@r{]}
+@itemx rc @r{[}@var{ignore-count}@r{]}
+Beginning at the point where your program last stopped, start executing
+in reverse.  Reverse execution will stop for breakpoints and synchronous
+exceptions (signals), just like normal execution.  Behavior of 
+asynchronous signals depends on the target environment.
+
+@kindex reverse-step
+@kindex rs @r{(@code{step})}
+@item reverse-step @r{[}@var{count}@r{]}
+Run the program backward until control reaches the first instruction of a
+different source line; then stop it, and return control to @value{GDBN}.
+
+Like the @code{step} command, @code{reverse-step} will only stop
+at the beginning of a source line.  It ``un-executes'' the previously
+executed source line.  If the previous source line included calls to 
+debuggable functions, @code{reverse-step} will step (backward) into
+the called function, stopping at the beginning of the @emph{last}
+statement executed in the called function (typically a return statement).
+
+Also, as with the @code{step} command, if non-debuggable functions are
+called, @code{reverse-step} will run thru them backward without stopping.
+
+@kindex reverse-stepi
+@kindex rsi @r{(@code{reverse-stepi})}
+@item reverse-stepi @r{[}@var{count}@r{]}
+Reverse-execute one machine instruction.  Note that the instruction
+to be reverse-executed is @emph{not} the one pointed to by the program
+counter, but the instruction executed prior to that one.  For instance,
+if the last instruction was a jump, @code{reverse-stepi} will take you
+back from the destination of the jump to the jump instruction itself.
+
+@kindex reverse-next
+@kindex rn @r{(@code{reverse-next})}
+@item reverse-next @r{[}@var{count}@r{]}
+Run backward to the first instruction of the last line executed in
+the current (innermost) stack frame.  If the line contains function
+calls, they will be ``un-executed'' without stopping.  Starting from
+the first line of a function, @code{reverse-next} will take you back
+to the caller of that function, @emph{before} the function was called.
+
+@kindex reverse-nexti
+@kindex rni @r{(@code{reverse-nexti})}
+@item reverse-nexti @r{[}@var{count}@r{]}
+Like @code{nexti}, @code{reverse-nexti} executes a single instruction
+in reverse, except that called functions are ``un-executed'' atomically.
+That is, if the previously executed instruction was a return from 
+another instruction, @code{reverse-nexti} will continue to execute
+in reverse until the call to that function (from the current stack
+frame) is reached.
+
+@kindex reverse-finish
+@item reverse-finish
+Just as the @code{finish} command takes you to the point where the
+current function returns, @code{reverse-finish} takes you to the point
+where it was called.  Instead of ending up at the end of the current
+function invocation, you end up at the beginning.
+
+@kindex set exec-direction
+@item set exec-direction 
+Set the direction of target execution.
+@itemx set exec-direction reverse
+@cindex execute forward or backward in time
+@value{GDBN} will perform all execution commands in reverse, until the 
+exec-direction mode is changed to ``forward''.  Affected commands include
+@code{step, stepi, next, nexti, continue, and finish}.  The @code{return}
+command cannot be used in reverse mode.
+@item set exec-direction forward
+@value{GDBN} will perform all execution commands in the normal fashion.
+This is the default.
+@end table
+
+
 @node Stack
 @chapter Examining the Stack
 

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