/* Process record and replay target for GDB, the GNU debugger.
- Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
This file is part of GDB.
static unsigned int record_call_history_size_setshow_var;
struct cmd_list_element *record_cmdlist = NULL;
+struct cmd_list_element *record_goto_cmdlist = NULL;
struct cmd_list_element *set_record_cmdlist = NULL;
struct cmd_list_element *show_record_cmdlist = NULL;
struct cmd_list_element *info_record_cmdlist = NULL;
if (record_debug) \
fprintf_unfiltered (gdb_stdlog, "record: " msg "\n", ##args)
-/* Find the record target in the target stack. */
+/* See record.h. */
-static struct target_ops *
+struct target_ops *
find_record_target (void)
{
- struct target_ops *t;
-
- for (t = current_target.beneath; t != NULL; t = t->beneath)
- if (t->to_stratum == record_stratum)
- return t;
-
- return NULL;
+ return find_target_at (record_stratum);
}
/* Check that recording is active. Throw an error, if it isn't. */
/* See record.h. */
+void
+record_preopen (void)
+{
+ /* Check if a record target is already running. */
+ if (find_record_target () != NULL)
+ error (_("The process is already being recorded. Use \"record stop\" to "
+ "stop recording first."));
+}
+
+/* See record.h. */
+
int
record_read_memory (struct gdbarch *gdbarch,
CORE_ADDR memaddr, gdb_byte *myaddr,
{
DEBUG ("stop %s", t->to_shortname);
- if (t->to_stop_recording != NULL)
- t->to_stop_recording ();
+ t->to_stop_recording (t);
}
/* Unpush the record target. */
/* See record.h. */
void
-record_disconnect (struct target_ops *t, char *args, int from_tty)
+record_disconnect (struct target_ops *t, const char *args, int from_tty)
{
gdb_assert (t->to_stratum == record_stratum);
/* See record.h. */
void
-record_detach (struct target_ops *t, char *args, int from_tty)
+record_detach (struct target_ops *t, const char *args, int from_tty)
{
gdb_assert (t->to_stratum == record_stratum);
target_kill ();
}
+/* See record.h. */
+
+int
+record_check_stopped_by_breakpoint (struct address_space *aspace, CORE_ADDR pc,
+ enum target_stop_reason *reason)
+{
+ if (breakpoint_inserted_here_p (aspace, pc))
+ {
+ if (hardware_breakpoint_inserted_here_p (aspace, pc))
+ *reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
+ else
+ *reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
+ return 1;
+ }
+
+ *reason = TARGET_STOPPED_BY_NO_REASON;
+ return 0;
+}
+
/* Implement "show record debug" command. */
static void
}
printf_filtered (_("Active record target: %s\n"), t->to_shortname);
- if (t->to_info_record != NULL)
- t->to_info_record ();
+ t->to_info_record (t);
}
/* The "record save" command. */
{
/* Default recfile name is "gdb_record.PID". */
xsnprintf (recfilename_buffer, sizeof (recfilename_buffer),
- "gdb_record.%d", PIDGET (inferior_ptid));
+ "gdb_record.%d", ptid_get_pid (inferior_ptid));
recfilename = recfilename_buffer;
}
target_save_record (recfilename);
}
+/* See record.h. */
+
+void
+record_goto (const char *arg)
+{
+ ULONGEST insn;
+
+ if (arg == NULL || *arg == '\0')
+ error (_("Command requires an argument (insn number to go to)."));
+
+ insn = parse_and_eval_long (arg);
+
+ require_record_target ();
+ target_goto_record (insn);
+}
+
/* "record goto" command. Argument is an instruction number,
as given by "info record".
Rewinds the recording (forward or backward) to the given instruction. */
-void
+static void
cmd_record_goto (char *arg, int from_tty)
{
+ record_goto (arg);
+}
+
+/* The "record goto begin" command. */
+
+static void
+cmd_record_goto_begin (char *arg, int from_tty)
+{
+ if (arg != NULL && *arg != '\0')
+ error (_("Junk after argument: %s."), arg);
+
require_record_target ();
+ target_goto_record_begin ();
+}
- if (arg == NULL || *arg == '\0')
- error (_("Command requires an argument (insn number to go to)."));
+/* The "record goto end" command. */
- if (strncmp (arg, "start", strlen ("start")) == 0
- || strncmp (arg, "begin", strlen ("begin")) == 0)
- target_goto_record_begin ();
- else if (strncmp (arg, "end", strlen ("end")) == 0)
- target_goto_record_end ();
- else
- {
- ULONGEST insn;
+static void
+cmd_record_goto_end (char *arg, int from_tty)
+{
+ if (arg != NULL && *arg != '\0')
+ error (_("Junk after argument: %s."), arg);
- insn = parse_and_eval_long (arg);
- target_goto_record (insn);
- }
+ require_record_target ();
+ target_goto_record_end ();
}
/* Read an instruction number from an argument string. */
switch (*args)
{
case 'm':
- modifiers |= DISASSEMBLY_SOURCE;
+ modifiers |= DISASSEMBLY_SOURCE_DEPRECATED;
modifiers |= DISASSEMBLY_FILENAME;
break;
case 'r':
switch (*args)
{
case 'l':
- modifiers |= record_print_src_line;
+ modifiers |= RECORD_PRINT_SRC_LINE;
break;
case 'i':
- modifiers |= record_print_insn_range;
+ modifiers |= RECORD_PRINT_INSN_RANGE;
+ break;
+ case 'c':
+ modifiers |= RECORD_PRINT_INDENT_CALLS;
break;
default:
error (_("Invalid modifier: %c."), *args);
&record_cmdlist);
add_alias_cmd ("s", "stop", class_obscure, 1, &record_cmdlist);
- add_cmd ("goto", class_obscure, cmd_record_goto, _("\
+ add_prefix_cmd ("goto", class_obscure, cmd_record_goto, _("\
Restore the program to its state at instruction number N.\n\
Argument is instruction number, as shown by 'info record'."),
- &record_cmdlist);
+ &record_goto_cmdlist, "record goto ", 1, &record_cmdlist);
+
+ add_cmd ("begin", class_obscure, cmd_record_goto_begin,
+ _("Go to the beginning of the execution log."),
+ &record_goto_cmdlist);
+ add_alias_cmd ("start", "begin", class_obscure, 1, &record_goto_cmdlist);
+
+ add_cmd ("end", class_obscure, cmd_record_goto_end,
+ _("Go to the end of the execution log."),
+ &record_goto_cmdlist);
add_cmd ("instruction-history", class_obscure, cmd_record_insn_history, _("\
Print disassembled instructions stored in the execution log.\n\
Without modifiers, it prints the function name.\n\
With a /l modifier, the source file and line number range is included.\n\
With a /i modifier, the instruction number range is included.\n\
+With a /c modifier, the output is indented based on the call stack depth.\n\
With no argument, prints ten more lines after the previous ten-line print.\n\
\"record function-call-history -\" prints ten lines before a previous ten-line \
print.\n\