Re: [RFA] Resubmit reverse debugging [5/5]

Michael Snyder
2008-10-17T19:48:02Z

[-- Attachment #1: Type: text/plain, Size: 26 bytes --]

Committed, as attached:

[-- Attachment #2: final5.txt --]
[-- Type: text/plain, Size: 14492 bytes --]

2008-10-17 Michael Snyder <msnyder@vmware.com>

User interface for reverse execution.
* Makefile.in (reverse.c): New file.
* reverse.c: New file. User interface for reverse execution.

2008-10-17 Michael Snyder <msnyder@vmware.com>

* gdb.texinfo: Add documentation for reverse execution.

Index: reverse.c
===================================================================
RCS file: reverse.c
diff -N reverse.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ reverse.c 17 Oct 2008 19:35:12 -0000
@@ -0,0 +1,143 @@
+/* Reverse execution and reverse debugging.
+
+ Copyright (C) 2006, 2007, 2008 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"
+#include "inferior.h"
+
+/* User interface:
+ reverse-step, reverse-next etc. */
+
+static void exec_direction_default (void *notused)
+{
+ /* Return execution direction to default state. */
+ execution_direction = EXEC_FORWARD;
+}
+
+/* exec_reverse_once -- accepts an arbitrary gdb command (string),
+ and executes it with exec-direction set to 'reverse'.
+
+ Used to implement reverse-next etc. commands. */
+
+static void
+exec_reverse_once (char *cmd, char *args, int from_tty)
+{
+ char *reverse_command;
+ enum exec_direction_kind dir = execution_direction;
+ struct cleanup *old_chain;
+
+ 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_can_execute_reverse)
+ error (_("Target %s does not support this command."), target_shortname);
+
+ reverse_command = xstrprintf ("%s %s", cmd, args ? args : "");
+ old_chain = make_cleanup (exec_direction_default, NULL);
+ make_cleanup (xfree, reverse_command);
+ execution_direction = EXEC_REVERSE;
+ execute_command (reverse_command, from_tty);
+ do_cleanups (old_chain);
+}
+
+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_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 but run it 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: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.1055
diff -u -p -r1.1055 Makefile.in
--- Makefile.in 16 Oct 2008 03:53:58 -0000 1.1055
+++ Makefile.in 17 Oct 2008 19:35:12 -0000
@@ -641,7 +641,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
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 \
@@ -780,7 +780,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
findcmd.o \
std-regs.o \
signals.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 \
dwarf2read.o mipsread.o stabsread.o corefile.o \
dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.528
diff -u -p -r1.528 gdb.texinfo
--- doc/gdb.texinfo 16 Oct 2008 03:54:00 -0000 1.528
+++ doc/gdb.texinfo 17 Oct 2008 19:35:12 -0000
@@ -143,6 +143,7 @@ software in general. We will miss him.
* 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
@@ -4850,6 +4851,126 @@ When such an event happens, a system cal
prematurely, even though your program does not appear to stop.

+@node Reverse Execution
+@chapter Running programs backward
+@cindex reverse execution
+@cindex running programs backward
+
+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} can allow 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@footnote{
+Note that some side effects are easier to undo than others. For instance,
+memory and registers are relatively easy, but device I/O is hard. Some
+targets may be able undo things like device I/O, and some may not.
+
+The contract between @value{GDBN} and the reverse executing target
+requires only that the target do something reasonable when
+@value{GDBN} tells it to execute backwards, and then report the
+results back to @value{GDBN}. Whatever the target reports back to
+@value{GDBN}, @value{GDBN} will report back to the user. @value{GDBN}
+assumes that the memory and registers that the target reports are in a
+consistant state, but @value{GDBN} accepts whatever it is given.
+}.
+
+If 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 start 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 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 beginning of the previous 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,
+just as the normal @code{next} command would take you from the last
+line of a function back to its return to its caller
+@footnote{Unles the code is too heavily optimized.}.
+
+@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
@@ -24565,6 +24686,22 @@ breakpoint at @var{addr}.
Don't use this packet. Use the @samp{Z} and @samp{z} packets instead
(@pxref{insert breakpoint or watchpoint packet}).

+@item bc
+@cindex @samp{bc} packet
+Backward continue. Execute the target system in reverse. No parameter.
+@xref{Reverse Execution}, for more information.
+
+Reply:
+@xref{Stop Reply Packets}, for the reply specifications.
+
+@item bs
+@cindex @samp{bs} packet
+Backward single step. Execute one instruction in reverse. No parameter.
+@xref{Reverse Execution}, for more information.
+
+Reply:
+@xref{Stop Reply Packets}, for the reply specifications.
+
@item c @r{[}@var{addr}@r{]}
@cindex @samp{c} packet
Continue. @var{addr} is address to resume. If @var{addr} is omitted,
@@ -25182,6 +25319,16 @@ hex.
The packet indicates that the loaded libraries have changed.
@value{GDBN} should use @samp{qXfer:libraries:read} to fetch a new
list of loaded libraries. @var{r} is ignored.
+
+@cindex replay log events, remote reply
+@item replaylog
+The packet indicates that the target cannot continue replaying
+logged execution events, because it has reached the end (or the
+beginning when executing backward) of the log. The value of @var{r}
+will be either @samp{begin} or @samp{end}. @xref{Reverse Execution},
+for more information.
+
+
@end table

@item W @var{AA}