-static void
-record_arch_list_cleanups (void *ignore)
-{
- record_list_release (record_arch_list_tail);
-}
-
-/* Before inferior step (when GDB record the running message, inferior
- only can step), GDB will call this function to record the values to
- record_list. This function will call gdbarch_process_record to
- record the running message of inferior and set them to
- record_arch_list, and add it to record_list. */
-
-static int
-record_message (struct regcache *regcache, enum target_signal signal)
-{
- int ret;
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct cleanup *old_cleanups = make_cleanup (record_arch_list_cleanups, 0);
-
- record_arch_list_head = NULL;
- record_arch_list_tail = NULL;
-
- /* Check record_insn_num. */
- record_check_insn_num (1);
-
- /* If gdb sends a signal value to target_resume,
- save it in the 'end' field of the previous instruction.
-
- Maybe process record should record what really happened,
- rather than what gdb pretends has happened.
-
- So if Linux delivered the signal to the child process during
- the record mode, we will record it and deliver it again in
- the replay mode.
-
- If user says "ignore this signal" during the record mode, then
- it will be ignored again during the replay mode (no matter if
- the user says something different, like "deliver this signal"
- during the replay mode).
-
- User should understand that nothing he does during the replay
- mode will change the behavior of the child. If he tries,
- then that is a user error.
-
- But we should still deliver the signal to gdb during the replay,
- if we delivered it during the recording. Therefore we should
- record the signal during record_wait, not record_resume. */
- if (record_list != &record_first) /* FIXME better way to check */
- {
- gdb_assert (record_list->type == record_end);
- record_list->u.end.sigval = signal;
- }
-
- if (signal == TARGET_SIGNAL_0
- || !gdbarch_process_record_signal_p (gdbarch))
- ret = gdbarch_process_record (gdbarch,
- regcache,
- regcache_read_pc (regcache));
- else
- ret = gdbarch_process_record_signal (gdbarch,
- regcache,
- signal);
-
- if (ret > 0)
- error (_("Process record: inferior program stopped."));
- if (ret < 0)
- error (_("Process record: failed to record execution log."));
-
- discard_cleanups (old_cleanups);
-
- record_list->next = record_arch_list_head;
- record_arch_list_head->prev = record_list;
- record_list = record_arch_list_tail;
-
- if (record_insn_num == record_insn_max_num && record_insn_max_num)
- record_list_release_first ();
- else
- record_insn_num++;
-
- return 1;
-}
-
-struct record_message_args {
- struct regcache *regcache;
- enum target_signal signal;
-};
-
-static int
-record_message_wrapper (void *args)
-{
- struct record_message_args *record_args = args;
-
- return record_message (record_args->regcache, record_args->signal);
-}
-
-static int
-record_message_wrapper_safe (struct regcache *regcache,
- enum target_signal signal)
-{
- struct record_message_args args;
-
- args.regcache = regcache;
- args.signal = signal;
-
- return catch_errors (record_message_wrapper, &args, NULL, RETURN_MASK_ALL);
-}
-
-/* Set to 1 if record_store_registers and record_xfer_partial
- doesn't need record. */
-
-static int record_gdb_operation_disable = 0;
-
-struct cleanup *
-record_gdb_operation_disable_set (void)
-{
- struct cleanup *old_cleanups = NULL;
-
- old_cleanups =
- make_cleanup_restore_integer (&record_gdb_operation_disable);
- record_gdb_operation_disable = 1;
-
- return old_cleanups;
-}
-
-/* Flag set to TRUE for target_stopped_by_watchpoint. */
-static int record_hw_watchpoint = 0;
-
-/* Execute one instruction from the record log. Each instruction in
- the log will be represented by an arbitrary sequence of register
- entries and memory entries, followed by an 'end' entry. */
-
-static inline void
-record_exec_insn (struct regcache *regcache, struct gdbarch *gdbarch,
- struct record_entry *entry)
-{
- switch (entry->type)
- {
- case record_reg: /* reg */
- {
- gdb_byte reg[MAX_REGISTER_SIZE];
-
- if (record_debug > 1)
- fprintf_unfiltered (gdb_stdlog,
- "Process record: record_reg %s to "
- "inferior num = %d.\n",
- host_address_to_string (entry),
- entry->u.reg.num);
-
- regcache_cooked_read (regcache, entry->u.reg.num, reg);
- regcache_cooked_write (regcache, entry->u.reg.num,
- record_get_loc (entry));
- memcpy (record_get_loc (entry), reg, entry->u.reg.len);
- }
- break;
-
- case record_mem: /* mem */
- {
- /* 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);
-
- if (record_debug > 1)
- fprintf_unfiltered (gdb_stdlog,
- "Process record: record_mem %s to "
- "inferior addr = %s len = %d.\n",
- host_address_to_string (entry),
- paddress (gdbarch, entry->u.mem.addr),
- entry->u.mem.len);
-
- if (target_read_memory (entry->u.mem.addr, mem, entry->u.mem.len))
- {
- entry->u.mem.mem_entry_not_accessible = 1;
- if (record_debug)
- warning (_("Process record: error reading memory at "
- "addr = %s len = %d."),
- paddress (gdbarch, entry->u.mem.addr),
- entry->u.mem.len);
- }
- else
- {
- if (target_write_memory (entry->u.mem.addr,
- record_get_loc (entry),
- entry->u.mem.len))
- {
- entry->u.mem.mem_entry_not_accessible = 1;
- if (record_debug)
- warning (_("Process record: error writing memory at "
- "addr = %s len = %d."),
- paddress (gdbarch, entry->u.mem.addr),
- entry->u.mem.len);
- }
- else
- {
- memcpy (record_get_loc (entry), mem, entry->u.mem.len);
-
- /* We've changed memory --- check if a hardware
- watchpoint should trap. Note that this
- presently assumes the target beneath supports
- continuable watchpoints. On non-continuable
- watchpoints target, we'll want to check this
- _before_ actually doing the memory change, and
- not doing the change at all if the watchpoint
- traps. */
- if (hardware_watchpoint_inserted_in_range
- (get_regcache_aspace (regcache),
- entry->u.mem.addr, entry->u.mem.len))
- record_hw_watchpoint = 1;
- }
- }
- }
- }
- break;
- }
-}
-
-static struct target_ops *tmp_to_resume_ops;
-static void (*tmp_to_resume) (struct target_ops *, ptid_t, int,
- enum target_signal);
-static struct target_ops *tmp_to_wait_ops;
-static ptid_t (*tmp_to_wait) (struct target_ops *, ptid_t,
- struct target_waitstatus *,
- int);
-static struct target_ops *tmp_to_store_registers_ops;
-static void (*tmp_to_store_registers) (struct target_ops *,
- struct regcache *,
- int regno);
-static struct target_ops *tmp_to_xfer_partial_ops;
-static LONGEST (*tmp_to_xfer_partial) (struct target_ops *ops,
- enum target_object object,
- const char *annex,
- gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset,
- LONGEST len);
-static int (*tmp_to_insert_breakpoint) (struct gdbarch *,
- struct bp_target_info *);
-static int (*tmp_to_remove_breakpoint) (struct gdbarch *,
- struct bp_target_info *);
-static int (*tmp_to_stopped_by_watchpoint) (void);
-static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
-static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
-static void (*tmp_to_async) (void (*) (enum inferior_event_type, void *), void *);
-
-static void record_restore (void);
-
-/* Asynchronous signal handle registered as event loop source for when
- we have pending events ready to be passed to the core. */
-
-static struct async_event_handler *record_async_inferior_event_token;
-
-static void
-record_async_inferior_event_handler (gdb_client_data data)
-{
- inferior_event_handler (INF_REG_EVENT, NULL);
-}
-
-/* Open the process record target. */
-
-static void
-record_core_open_1 (char *name, int from_tty)
-{
- struct regcache *regcache = get_current_regcache ();
- int regnum = gdbarch_num_regs (get_regcache_arch (regcache));
- int i;
-
- /* Get record_core_regbuf. */
- target_fetch_registers (regcache, -1);
- record_core_regbuf = xmalloc (MAX_REGISTER_SIZE * regnum);
- for (i = 0; i < regnum; i ++)
- regcache_raw_collect (regcache, i,
- record_core_regbuf + MAX_REGISTER_SIZE * i);
-
- /* Get record_core_start and record_core_end. */
- if (build_section_table (core_bfd, &record_core_start, &record_core_end))
- {
- xfree (record_core_regbuf);
- record_core_regbuf = NULL;
- error (_("\"%s\": Can't find sections: %s"),
- bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
- }
-
- push_target (&record_core_ops);
- record_restore ();
-}
-
-/* "to_open" target method for 'live' processes. */
-
-static void
-record_open_1 (char *name, int from_tty)
-{
- if (record_debug)
- fprintf_unfiltered (gdb_stdlog, "Process record: record_open\n");
-
- /* check exec */
- if (!target_has_execution)
- error (_("Process record: the program is not being run."));
- if (non_stop)
- error (_("Process record target can't debug inferior in non-stop mode "
- "(non-stop)."));
-
- if (!gdbarch_process_record_p (target_gdbarch))
- error (_("Process record: the current architecture doesn't support "
- "record function."));
-
- if (!tmp_to_resume)
- error (_("Could not find 'to_resume' method on the target stack."));
- 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."));
- if (!tmp_to_insert_breakpoint)
- 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."));
- if (!tmp_to_stopped_by_watchpoint)
- 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."));
-
- push_target (&record_ops);
-}
-
-/* "to_open" target method. Open the process record target. */
-
-static void
-record_open (char *name, int from_tty)