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