/* Process record and replay target for GDB, the GNU debugger.
- Copyright (C) 2013-2015 Free Software Foundation, Inc.
+ Copyright (C) 2013-2016 Free Software Foundation, Inc.
This file is part of GDB.
static int
record_full_message_wrapper (void *args)
{
- struct record_full_message_args *record_full_args = args;
+ struct record_full_message_args *record_full_args
+ = (struct record_full_message_args *) args;
return record_full_message (record_full_args->regcache,
record_full_args->signal);
args.regcache = regcache;
args.signal = signal;
- return catch_errors (record_full_message_wrapper, &args, NULL,
+ return catch_errors (record_full_message_wrapper, &args, "",
RETURN_MASK_ALL);
}
/* Nothing to do if the entry is flagged not_accessible. */
if (!entry->u.mem.mem_entry_not_accessible)
{
- gdb_byte *mem = alloca (entry->u.mem.len);
+ gdb_byte *mem = (gdb_byte *) xmalloc (entry->u.mem.len);
+ struct cleanup *cleanup = make_cleanup (xfree, mem);
if (record_debug > 1)
fprintf_unfiltered (gdb_stdlog,
record_full_stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
}
}
+
+ do_cleanups (cleanup);
}
}
break;
/* Get record_full_core_regbuf. */
target_fetch_registers (regcache, -1);
- record_full_core_regbuf = xmalloc (MAX_REGISTER_SIZE * regnum);
+ record_full_core_regbuf = (gdb_byte *) xmalloc (MAX_REGISTER_SIZE * regnum);
for (i = 0; i < regnum; i ++)
regcache_raw_collect (regcache, i,
record_full_core_regbuf + MAX_REGISTER_SIZE * i);
{
struct record_full_breakpoint *bp;
int in_target_beneath = 0;
+ int ix;
if (!RECORD_FULL_IS_REPLAY)
{
in_target_beneath = 1;
}
+ else
+ {
+ CORE_ADDR addr = bp_tgt->reqstd_address;
+ int bplen;
+
+ gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);
+
+ bp_tgt->placed_address = addr;
+ bp_tgt->placed_size = bplen;
+ }
+
+ /* Use the existing entries if found in order to avoid duplication
+ in record_full_breakpoints. */
+
+ for (ix = 0;
+ VEC_iterate (record_full_breakpoint_p,
+ record_full_breakpoints, ix, bp);
+ ++ix)
+ {
+ if (bp->addr == bp_tgt->placed_address
+ && bp->address_space == bp_tgt->placed_address_space)
+ {
+ gdb_assert (bp->in_target_beneath == in_target_beneath);
+ return 0;
+ }
+ }
bp = XNEW (struct record_full_breakpoint);
bp->addr = bp_tgt->placed_address;
return RECORD_FULL_IS_REPLAY;
}
+/* The "to_record_will_replay" target method. */
+
+static int
+record_full_will_replay (struct target_ops *self, ptid_t ptid, int dir)
+{
+ /* We can currently only record when executing forwards. Should we be able
+ to record when executing backwards on targets that support reverse
+ execution, this needs to be changed. */
+
+ return RECORD_FULL_IS_REPLAY || dir == EXEC_REVERSE;
+}
+
/* Go to a specific entry. */
static void
record_full_ops.to_save_record = record_full_save;
record_full_ops.to_delete_record = record_full_delete;
record_full_ops.to_record_is_replaying = record_full_is_replaying;
+ record_full_ops.to_record_will_replay = record_full_will_replay;
record_full_ops.to_record_stop_replaying = record_full_stop_replaying;
record_full_ops.to_goto_record_begin = record_full_goto_begin;
record_full_ops.to_goto_record_end = record_full_goto_end;
record_full_core_ops.to_info_record = record_full_info;
record_full_core_ops.to_delete_record = record_full_delete;
record_full_core_ops.to_record_is_replaying = record_full_is_replaying;
+ record_full_core_ops.to_record_will_replay = record_full_will_replay;
record_full_core_ops.to_goto_record_begin = record_full_goto_begin;
record_full_core_ops.to_goto_record_end = record_full_goto_end;
record_full_core_ops.to_goto_record = record_full_goto;
static void
record_full_save_cleanups (void *data)
{
- bfd *obfd = data;
+ bfd *obfd = (bfd *) data;
char *pathname = xstrdup (bfd_get_filename (obfd));
gdb_bfd_unref (obfd);