/* Process record and replay target for GDB, the GNU debugger.
- Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GDB.
/* This is the debug switch for process record. */
int record_debug = 0;
+/* If true, query if PREC cannot record memory
+ change of next instruction. */
+int record_memory_query = 0;
+
struct record_core_buf_entry
{
struct record_core_buf_entry *prev;
return rec->u.reg.u.buf;
case record_end:
default:
- gdb_assert (0);
+ gdb_assert_not_reached ("unexpected record_entry type");
return NULL;
}
}
"record list.\n",
paddress (target_gdbarch, addr), len);
- if (!addr) /* FIXME: Why? Some arch must permit it... */
+ if (!addr) /* FIXME: Why? Some arch must permit it... */
return 0;
rec = record_mem_alloc (addr, len);
if (!tmp_to_wait)
error (_("Could not find 'to_wait' method on the target stack."));
if (!tmp_to_store_registers)
- error (_("Could not find 'to_store_registers' method on the target stack."));
+ error (_("Could not find 'to_store_registers' "
+ "method on the target stack."));
if (!tmp_to_insert_breakpoint)
- error (_("Could not find 'to_insert_breakpoint' method on the target stack."));
+ error (_("Could not find 'to_insert_breakpoint' "
+ "method on the target stack."));
if (!tmp_to_remove_breakpoint)
- error (_("Could not find 'to_remove_breakpoint' method on the target stack."));
+ error (_("Could not find 'to_remove_breakpoint' "
+ "method on the target stack."));
if (!tmp_to_stopped_by_watchpoint)
- error (_("Could not find 'to_stopped_by_watchpoint' method on the target stack."));
+ error (_("Could not find 'to_stopped_by_watchpoint' "
+ "method on the target stack."));
if (!tmp_to_stopped_data_address)
- error (_("Could not find 'to_stopped_data_address' method on the target stack."));
+ error (_("Could not find 'to_stopped_data_address' "
+ "method on the target stack."));
push_target (&record_ops);
}
record_beneath_to_stopped_by_watchpoint = tmp_to_stopped_by_watchpoint;
record_beneath_to_stopped_data_address = tmp_to_stopped_data_address;
- if (current_target.to_stratum == core_stratum)
+ if (core_bfd)
record_core_open_1 (name, from_tty);
else
record_open_1 (name, from_tty);
if (!RECORD_IS_REPLAY)
{
+ struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
record_message (get_current_regcache (), signal);
- record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
- signal);
+
+ if (!step)
+ {
+ /* This is not hard single step. */
+ if (!gdbarch_software_single_step_p (gdbarch))
+ {
+ /* This is a normal continue. */
+ step = 1;
+ }
+ else
+ {
+ /* This arch support soft sigle step. */
+ if (single_step_breakpoints_inserted ())
+ {
+ /* This is a soft single step. */
+ record_resume_step = 1;
+ }
+ else
+ {
+ /* This is a continue.
+ Try to insert a soft single step breakpoint. */
+ if (!gdbarch_software_single_step (gdbarch,
+ get_current_frame ()))
+ {
+ /* This system don't want use soft single step.
+ Use hard sigle step. */
+ step = 1;
+ }
+ }
+ }
+ }
+
+ record_beneath_to_resume (record_beneath_to_resume_ops,
+ ptid, step, signal);
}
}
/* This is not a single step. */
ptid_t ret;
CORE_ADDR tmp_pc;
+ struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
while (1)
{
ret = record_beneath_to_wait (record_beneath_to_wait_ops,
ptid, status, options);
+ if (single_step_breakpoints_inserted ())
+ remove_single_step_breakpoints ();
+
if (record_resume_step)
return ret;
handle it. */
if (software_breakpoint_inserted_here_p (aspace, tmp_pc))
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch
+ = get_regcache_arch (regcache);
CORE_ADDR decr_pc_after_break
= gdbarch_decr_pc_after_break (gdbarch);
if (decr_pc_after_break)
}
else
{
- /* This must be a single-step trap. Record the
- insn and issue another step. */
+ /* This is a single-step trap. Record the
+ insn and issue another step.
+ FIXME: this part can be a random SIGTRAP too.
+ But GDB cannot handle it. */
+ int step = 1;
+
if (!record_message_wrapper_safe (regcache,
TARGET_SIGNAL_0))
{
break;
}
+ if (gdbarch_software_single_step_p (gdbarch))
+ {
+ /* Try to insert the software single step breakpoint.
+ If insert success, set step to 0. */
+ set_executing (inferior_ptid, 0);
+ reinit_frame_cache ();
+ if (gdbarch_software_single_step (gdbarch,
+ get_current_frame ()))
+ step = 0;
+ set_executing (inferior_ptid, 1);
+ }
+
record_beneath_to_resume (record_beneath_to_resume_ops,
- ptid, 1,
+ ptid, step,
TARGET_SIGNAL_0);
continue;
}
if (record_hw_watchpoint)
{
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
-Process record: hit hw watchpoint.\n");
+ fprintf_unfiltered (gdb_stdlog,
+ "Process record: hit hw "
+ "watchpoint.\n");
continue_flag = 0;
}
/* Check target signal */
static void
set_record_command (char *args, int from_tty)
{
- printf_unfiltered (_("\
-\"set record\" must be followed by an apporpriate subcommand.\n"));
+ printf_unfiltered (_("\"set record\" must be followed "
+ "by an apporpriate subcommand.\n"));
help_list (set_record_cmdlist, "set record ", all_commands, gdb_stdout);
}
error (_("Version mis-match or file format error in core file %s."),
bfd_get_filename (core_bfd));
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
- Reading 4-byte magic cookie RECORD_FILE_MAGIC (0x%s)\n",
+ fprintf_unfiltered (gdb_stdlog,
+ " Reading 4-byte magic cookie "
+ "RECORD_FILE_MAGIC (0x%s)\n",
phex_nz (netorder32 (magic), 4));
/* Restore the entries in recfd into record_arch_list_head and
rec->u.reg.len, &bfd_offset);
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
- Reading register %d (1 plus %lu plus %d bytes)\n",
+ fprintf_unfiltered (gdb_stdlog,
+ " Reading register %d (1 "
+ "plus %lu plus %d bytes)\n",
rec->u.reg.num,
(unsigned long) sizeof (regnum),
rec->u.reg.len);
rec->u.mem.len, &bfd_offset);
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
- Reading memory %s (1 plus %lu plus %lu plus %d bytes)\n",
+ fprintf_unfiltered (gdb_stdlog,
+ " Reading memory %s (1 plus "
+ "%lu plus %lu plus %d bytes)\n",
paddress (get_current_arch (),
rec->u.mem.addr),
(unsigned long) sizeof (addr),
rec->u.end.insn_num = count;
record_insn_count = count + 1;
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
- Reading record_end (1 + %lu + %lu bytes), offset == %s\n",
+ fprintf_unfiltered (gdb_stdlog,
+ " Reading record_end (1 + "
+ "%lu + %lu bytes), offset == %s\n",
(unsigned long) sizeof (signal),
(unsigned long) sizeof (count),
paddress (get_current_arch (),
/* Write the magic code. */
magic = RECORD_FILE_MAGIC;
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
- Writing 4-byte magic cookie RECORD_FILE_MAGIC (0x%s)\n",
+ fprintf_unfiltered (gdb_stdlog,
+ " Writing 4-byte magic cookie "
+ "RECORD_FILE_MAGIC (0x%s)\n",
phex_nz (magic, 4));
bfdcore_write (obfd, osec, &magic, sizeof (magic), &bfd_offset);
{
case record_reg: /* reg */
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
- Writing register %d (1 plus %lu plus %d bytes)\n",
+ fprintf_unfiltered (gdb_stdlog,
+ " Writing register %d (1 "
+ "plus %lu plus %d bytes)\n",
record_list->u.reg.num,
(unsigned long) sizeof (regnum),
record_list->u.reg.len);
case record_mem: /* mem */
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
- Writing memory %s (1 plus %lu plus %lu plus %d bytes)\n",
+ fprintf_unfiltered (gdb_stdlog,
+ " Writing memory %s (1 plus "
+ "%lu plus %lu plus %d bytes)\n",
paddress (gdbarch,
record_list->u.mem.addr),
(unsigned long) sizeof (addr),
case record_end:
if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "\
- Writing record_end (1 + %lu + %lu bytes)\n",
+ fprintf_unfiltered (gdb_stdlog,
+ " Writing record_end (1 + "
+ "%lu + %lu bytes)\n",
(unsigned long) sizeof (signal),
(unsigned long) sizeof (count));
/* Write signal value. */
add_setshow_boolean_cmd ("stop-at-limit", no_class,
&record_stop_at_limit, _("\
Set whether record/replay stops when record/replay buffer becomes full."), _("\
-Show whether record/replay stops when record/replay buffer becomes full."), _("\
-Default is ON.\n\
+Show whether record/replay stops when record/replay buffer becomes full."),
+ _("Default is ON.\n\
When ON, if the record/replay buffer becomes full, ask user what to do.\n\
When OFF, if the record/replay buffer becomes full,\n\
delete the oldest recorded instruction to make room for each new one."),
Restore the program to its state at instruction number N.\n\
Argument is instruction number, as shown by 'info record'."),
&record_cmdlist);
+
+ add_setshow_boolean_cmd ("memory-query", no_class,
+ &record_memory_query, _("\
+Set whether query if PREC cannot record memory change of next instruction."),
+ _("\
+Show whether query if PREC cannot record memory change of next instruction."),
+ _("\
+Default is OFF.\n\
+When ON, query if PREC cannot record memory change of next instruction."),
+ NULL, NULL,
+ &set_record_cmdlist, &show_record_cmdlist);
+
}