diff options
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/Makefile.in | 7 | ||||
-rw-r--r-- | gdb/reverse.c | 197 |
3 files changed, 208 insertions, 2 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cb7b636..6a22035 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -34,6 +34,12 @@ * infrun.c: Make sure to check for EXEC_REVERSE not EXEC_FORWARD, since targets that don't implement execdir will return EXEC_ERROR. +2006-03-31 Michael Snyder <msnyder@redhat.com> + + User interface for reverse execution. + * Makefile.in (reverse.c): New file. + * reverse.c: New file. User interface for reverse execution. + 2006-03-31 Andrew Stubbs <andrew.stubbs@st.com> * value.h (struct internalvar): Add field 'endian'. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 644e9d9..769f558 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -543,7 +543,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c \ 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 \ @@ -927,7 +927,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ 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 \ @@ -2493,6 +2494,8 @@ remote-st.o: remote-st.c $(defs_h) $(gdbcore_h) $(target_h) $(gdb_string_h) \ 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) \ diff --git a/gdb/reverse.c b/gdb/reverse.c new file mode 100644 index 0000000..0c0d8ac --- /dev/null +++ b/gdb/reverse.c @@ -0,0 +1,197 @@ +/* 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[512]; + 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); + sprintf (reverse_command, "%s %s", cmd, args ? args : ""); + 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).", + "Tells 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.")); +} |