gdb/tui: fairer distribution of excess space during apply
[binutils-gdb.git] / gdb / record-full.c
index de96574baf2ea36945a598b356cc6bfc97921698..38e021529c7bea19a8bd90c6919476650f153d61 100644 (file)
@@ -1,6 +1,6 @@
 /* Process record and replay target for GDB, the GNU debugger.
 
-   Copyright (C) 2013-2018 Free Software Foundation, Inc.
+   Copyright (C) 2013-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -21,6 +21,7 @@
 #include "gdbcmd.h"
 #include "regcache.h"
 #include "gdbthread.h"
+#include "inferior.h"
 #include "event-top.h"
 #include "completer.h"
 #include "arch-utils.h"
 #include "record-full.h"
 #include "elf-bfd.h"
 #include "gcore.h"
-#include "event-loop.h"
+#include "gdbsupport/event-loop.h"
 #include "inf-loop.h"
 #include "gdb_bfd.h"
 #include "observable.h"
 #include "infrun.h"
-#include "common/gdb_unlinker.h"
-#include "common/byte-vector.h"
+#include "gdbsupport/gdb_unlinker.h"
+#include "gdbsupport/byte-vector.h"
+#include "async-event.h"
 
 #include <signal.h>
 
@@ -52,7 +54,7 @@
    mode, and we build up an execution log in which, for each executed
    instruction, we record all changes in memory and register state.
    This is invisible to the user, to whom it just looks like an
-   ordinary debugging session (except for performance degredation).
+   ordinary debugging session (except for performance degradation).
 
    In replay mode, instead of actually letting the inferior run as a
    process, we simulate its execution by playing back the recorded
@@ -158,7 +160,7 @@ struct record_full_entry
 
 /* If true, query if PREC cannot record memory
    change of next instruction.  */
-int record_full_memory_query = 0;
+bool record_full_memory_query = false;
 
 struct record_full_core_buf_entry
 {
@@ -169,8 +171,7 @@ struct record_full_core_buf_entry
 
 /* Record buf with core target.  */
 static detached_regcache *record_full_core_regbuf = NULL;
-static struct target_section *record_full_core_start;
-static struct target_section *record_full_core_end;
+static target_section_table record_full_core_sections;
 static struct record_full_core_buf_entry *record_full_core_buf_list = NULL;
 
 /* The following variables are used for managing the linked list that
@@ -182,7 +183,7 @@ static struct record_full_core_buf_entry *record_full_core_buf_list = NULL;
    record_full_list serves two functions:
      1) In record mode, it anchors the end of the list.
      2) In replay mode, it traverses the list and points to
-        the next instruction that must be emulated.
+       the next instruction that must be emulated.
 
    record_full_arch_list_head and record_full_arch_list_tail are used
    to manage a separate list, which is used to build up the change
@@ -195,8 +196,8 @@ static struct record_full_entry *record_full_list = &record_full_first;
 static struct record_full_entry *record_full_arch_list_head = NULL;
 static struct record_full_entry *record_full_arch_list_tail = NULL;
 
-/* 1 ask user. 0 auto delete the last struct record_full_entry.  */
-static int record_full_stop_at_limit = 1;
+/* true ask user. false auto delete the last struct record_full_entry.  */
+static bool record_full_stop_at_limit = true;
 /* Maximum allowed number of insns in execution log.  */
 static unsigned int record_full_insn_max_num
        = DEFAULT_RECORD_FULL_INSN_MAX_NUM;
@@ -206,37 +207,34 @@ static unsigned int record_full_insn_num = 0;
    than count of insns presently in execution log).  */
 static ULONGEST record_full_insn_count;
 
+static const char record_longname[]
+  = N_("Process record and replay target");
+static const char record_doc[]
+  = N_("Log program while executing and replay execution from log.");
+
 /* Base class implementing functionality common to both the
    "record-full" and "record-core" targets.  */
 
 class record_full_base_target : public target_ops
 {
 public:
-  record_full_base_target ()
-  { to_stratum = record_stratum; }
-
-  const char *shortname () override = 0;
+  const target_info &info () const override = 0;
 
-  const char *longname () override
-  { return _("Process record and replay target"); }
+  strata stratum () const override { return record_stratum; }
 
-  const char *doc () override
-  { return _("Log program while executing and replay execution from log."); }
-
-  void open (const char *, int) override;
   void close () override;
   void async (int) override;
-  ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
-  int stopped_by_watchpoint () override;
-  int stopped_data_address (CORE_ADDR *) override;
+  ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
+  bool stopped_by_watchpoint () override;
+  bool stopped_data_address (CORE_ADDR *) override;
 
-  int stopped_by_sw_breakpoint () override;
-  int supports_stopped_by_sw_breakpoint () override;
+  bool stopped_by_sw_breakpoint () override;
+  bool supports_stopped_by_sw_breakpoint () override;
 
-  int stopped_by_hw_breakpoint () override;
-  int supports_stopped_by_hw_breakpoint () override;
+  bool stopped_by_hw_breakpoint () override;
+  bool supports_stopped_by_hw_breakpoint () override;
 
-  int can_execute_reverse () override;
+  bool can_execute_reverse () override;
 
   /* Add bookmark target methods.  */
   gdb_byte *get_bookmark (const char *, int) override;
@@ -247,8 +245,8 @@ public:
   void save_record (const char *filename) override;
   bool supports_delete_record () override;
   void delete_record () override;
-  int record_is_replaying (ptid_t ptid) override;
-  int record_will_replay (ptid_t ptid, int dir) override;
+  bool record_is_replaying (ptid_t ptid) override;
+  bool record_will_replay (ptid_t ptid, int dir) override;
   void record_stop_replaying () override;
   void goto_record_begin () override;
   void goto_record_end () override;
@@ -257,13 +255,18 @@ public:
 
 /* The "record-full" target.  */
 
+static const target_info record_full_target_info = {
+  "record-full",
+  record_longname,
+  record_doc,
+};
+
 class record_full_target final : public record_full_base_target
 {
 public:
-  const char *shortname () override
-  { return "record-full"; }
+  const target_info &info () const override
+  { return record_full_target_info; }
 
-  void commit_resume () override;
   void resume (ptid_t, int, enum gdb_signal) override;
   void disconnect (const char *, int) override;
   void detach (inferior *, int) override;
@@ -285,11 +288,17 @@ public:
 
 /* The "record-core" target.  */
 
+static const target_info record_full_core_target_info = {
+  "record-core",
+  record_longname,
+  record_doc,
+};
+
 class record_full_core_target final : public record_full_base_target
 {
 public:
-  const char *shortname () override
-  { return "record-core"; }
+  const target_info &info () const override
+  { return record_full_core_target_info; }
 
   void resume (ptid_t, int, enum gdb_signal) override;
   void disconnect (const char *, int) override;
@@ -309,7 +318,7 @@ public:
                         struct bp_target_info *,
                         enum remove_bp_reason) override;
 
-  int has_execution (ptid_t) override;
+  bool has_execution (inferior *inf) override;
 };
 
 static record_full_target record_full_ops;
@@ -556,9 +565,9 @@ static void
 record_full_arch_list_add (struct record_full_entry *rec)
 {
   if (record_debug > 1)
-    fprintf_unfiltered (gdb_stdlog,
-                       "Process record: record_full_arch_list_add %s.\n",
-                       host_address_to_string (rec));
+    gdb_printf (gdb_stdlog,
+               "Process record: record_full_arch_list_add %s.\n",
+               host_address_to_string (rec));
 
   if (record_full_arch_list_tail)
     {
@@ -603,14 +612,14 @@ record_full_arch_list_add_reg (struct regcache *regcache, int regnum)
   struct record_full_entry *rec;
 
   if (record_debug > 1)
-    fprintf_unfiltered (gdb_stdlog,
-                       "Process record: add register num = %d to "
-                       "record list.\n",
-                       regnum);
+    gdb_printf (gdb_stdlog,
+               "Process record: add register num = %d to "
+               "record list.\n",
+               regnum);
 
   rec = record_full_reg_alloc (regcache, regnum);
 
-  regcache_raw_read (regcache, regnum, record_full_get_loc (rec));
+  regcache->raw_read (regnum, record_full_get_loc (rec));
 
   record_full_arch_list_add (rec);
 
@@ -626,10 +635,10 @@ record_full_arch_list_add_mem (CORE_ADDR addr, int len)
   struct record_full_entry *rec;
 
   if (record_debug > 1)
-    fprintf_unfiltered (gdb_stdlog,
-                       "Process record: add mem addr = %s len = %d to "
-                       "record list.\n",
-                       paddress (target_gdbarch (), addr), len);
+    gdb_printf (gdb_stdlog,
+               "Process record: add mem addr = %s len = %d to "
+               "record list.\n",
+               paddress (target_gdbarch (), addr), len);
 
   if (!addr)   /* FIXME: Why?  Some arch must permit it...  */
     return 0;
@@ -657,8 +666,8 @@ record_full_arch_list_add_end (void)
   struct record_full_entry *rec;
 
   if (record_debug > 1)
-    fprintf_unfiltered (gdb_stdlog,
-                       "Process record: add end to arch list.\n");
+    gdb_printf (gdb_stdlog,
+               "Process record: add end to arch list.\n");
 
   rec = record_full_end_alloc ();
   rec->u.end.sigval = GDB_SIGNAL_0;
@@ -686,12 +695,6 @@ record_full_check_insn_num (void)
     }
 }
 
-static void
-record_full_arch_list_cleanups (void *ignore)
-{
-  record_full_list_release (record_full_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_full_list.  This function will call gdbarch_process_record to
@@ -703,61 +706,66 @@ record_full_message (struct regcache *regcache, enum gdb_signal signal)
 {
   int ret;
   struct gdbarch *gdbarch = regcache->arch ();
-  struct cleanup *old_cleanups
-    = make_cleanup (record_full_arch_list_cleanups, 0);
 
-  record_full_arch_list_head = NULL;
-  record_full_arch_list_tail = NULL;
+  try
+    {
+      record_full_arch_list_head = NULL;
+      record_full_arch_list_tail = NULL;
 
-  /* Check record_full_insn_num.  */
-  record_full_check_insn_num ();
+      /* Check record_full_insn_num.  */
+      record_full_check_insn_num ();
 
-  /* If gdb sends a signal value to target_resume,
-     save it in the 'end' field of the previous instruction.
+      /* 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.
+        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.
+        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).
+        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.
+        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_full_wait, not
-     record_full_resume.  */
-  if (record_full_list != &record_full_first)  /* FIXME better way to check */
+        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_full_wait, not
+        record_full_resume.  */
+      if (record_full_list != &record_full_first)  /* FIXME better way
+                                                     to check */
+       {
+         gdb_assert (record_full_list->type == record_full_end);
+         record_full_list->u.end.sigval = signal;
+       }
+
+      if (signal == GDB_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."));
+    }
+  catch (const gdb_exception &ex)
     {
-      gdb_assert (record_full_list->type == record_full_end);
-      record_full_list->u.end.sigval = signal;
+      record_full_list_release (record_full_arch_list_tail);
+      throw;
     }
 
-  if (signal == GDB_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_full_list->next = record_full_arch_list_head;
   record_full_arch_list_head->prev = record_full_list;
   record_full_list = record_full_arch_list_tail;
@@ -772,16 +780,15 @@ static bool
 record_full_message_wrapper_safe (struct regcache *regcache,
                                  enum gdb_signal signal)
 {
-  TRY
+  try
     {
       record_full_message (regcache, signal);
     }
-  CATCH (ex, RETURN_MASK_ALL)
+  catch (const gdb_exception &ex)
     {
       exception_print (gdb_stderr, ex);
       return false;
     }
-  END_CATCH
 
   return true;
 }
@@ -816,53 +823,52 @@ record_full_exec_insn (struct regcache *regcache,
       {
        gdb::byte_vector reg (entry->u.reg.len);
 
-        if (record_debug > 1)
-          fprintf_unfiltered (gdb_stdlog,
-                              "Process record: record_full_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.data ());
-        regcache_cooked_write (regcache, entry->u.reg.num, 
-                              record_full_get_loc (entry));
-        memcpy (record_full_get_loc (entry), reg.data (), entry->u.reg.len);
+       if (record_debug > 1)
+         gdb_printf (gdb_stdlog,
+                     "Process record: record_full_reg %s to "
+                     "inferior num = %d.\n",
+                     host_address_to_string (entry),
+                     entry->u.reg.num);
+
+       regcache->cooked_read (entry->u.reg.num, reg.data ());
+       regcache->cooked_write (entry->u.reg.num, record_full_get_loc (entry));
+       memcpy (record_full_get_loc (entry), reg.data (), entry->u.reg.len);
       }
       break;
 
     case record_full_mem: /* mem */
       {
        /* Nothing to do if the entry is flagged not_accessible.  */
-        if (!entry->u.mem.mem_entry_not_accessible)
-          {
+       if (!entry->u.mem.mem_entry_not_accessible)
+         {
            gdb::byte_vector mem (entry->u.mem.len);
 
-            if (record_debug > 1)
-              fprintf_unfiltered (gdb_stdlog,
-                                  "Process record: record_full_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 (record_debug > 1)
+             gdb_printf (gdb_stdlog,
+                         "Process record: record_full_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 (record_read_memory (gdbarch,
+           if (record_read_memory (gdbarch,
                                    entry->u.mem.addr, mem.data (),
                                    entry->u.mem.len))
              entry->u.mem.mem_entry_not_accessible = 1;
-            else
-              {
-                if (target_write_memory (entry->u.mem.addr, 
+           else
+             {
+               if (target_write_memory (entry->u.mem.addr, 
                                         record_full_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 "
+                 {
+                   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
+                              paddress (gdbarch, entry->u.mem.addr),
+                              entry->u.mem.len);
+                 }
+               else
                  {
                    memcpy (record_full_get_loc (entry), mem.data (),
                            entry->u.mem.len);
@@ -880,8 +886,8 @@ record_full_exec_insn (struct regcache *regcache,
                         entry->u.mem.addr, entry->u.mem.len))
                      record_full_stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
                  }
-              }
-          }
+             }
+         }
       }
       break;
     }
@@ -897,10 +903,10 @@ static struct async_event_handler *record_full_async_inferior_event_token;
 static void
 record_full_async_inferior_event_handler (gdb_client_data data)
 {
-  inferior_event_handler (INF_REG_EVENT, NULL);
+  inferior_event_handler (INF_REG_EVENT);
 }
 
-/* Open the process record target.  */
+/* Open the process record target for 'core' files.  */
 
 static void
 record_full_core_open_1 (const char *name, int from_tty)
@@ -916,30 +922,22 @@ record_full_core_open_1 (const char *name, int from_tty)
   for (i = 0; i < regnum; i ++)
     record_full_core_regbuf->raw_supply (i, *regcache);
 
-  /* Get record_full_core_start and record_full_core_end.  */
-  if (build_section_table (core_bfd, &record_full_core_start,
-                          &record_full_core_end))
-    {
-      delete record_full_core_regbuf;
-      record_full_core_regbuf = NULL;
-      error (_("\"%s\": Can't find sections: %s"),
-            bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
-    }
+  record_full_core_sections = build_section_table (core_bfd);
 
-  push_target (&record_full_core_ops);
+  current_inferior ()->push_target (&record_full_core_ops);
   record_full_restore ();
 }
 
-/* "open" target method for 'live' processes.  */
+/* Open the process record target for 'live' processes.  */
 
 static void
 record_full_open_1 (const char *name, int from_tty)
 {
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open_1\n");
+    gdb_printf (gdb_stdlog, "Process record: record_full_open_1\n");
 
   /* check exec */
-  if (!target_has_execution)
+  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 "
@@ -949,18 +947,18 @@ record_full_open_1 (const char *name, int from_tty)
     error (_("Process record: the current architecture doesn't support "
             "record function."));
 
-  push_target (&record_full_ops);
+  current_inferior ()->push_target (&record_full_ops);
 }
 
 static void record_full_init_record_breakpoints (void);
 
-/* "open" target method.  Open the process record target.  */
+/* Open the process record target.  */
 
-void
-record_full_base_target::open (const char *name, int from_tty)
+static void
+record_full_open (const char *name, int from_tty)
 {
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open\n");
+    gdb_printf (gdb_stdlog, "Process record: record_full_open\n");
 
   record_preopen ();
 
@@ -978,7 +976,7 @@ record_full_base_target::open (const char *name, int from_tty)
   /* Register extra event sources in the event loop.  */
   record_full_async_inferior_event_token
     = create_async_event_handler (record_full_async_inferior_event_handler,
-                                 NULL);
+                                 NULL, "record-full");
 
   record_full_init_record_breakpoints ();
 
@@ -993,7 +991,7 @@ record_full_base_target::close ()
   struct record_full_core_buf_entry *entry;
 
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "Process record: record_full_close\n");
+    gdb_printf (gdb_stdlog, "Process record: record_full_close\n");
 
   record_full_list_release (record_full_list);
 
@@ -1005,15 +1003,11 @@ record_full_base_target::close ()
     }
 
   /* Release record_full_core_buf_list.  */
-  if (record_full_core_buf_list)
+  while (record_full_core_buf_list)
     {
-      for (entry = record_full_core_buf_list->prev; entry;
-          entry = entry->prev)
-       {
-         xfree (record_full_core_buf_list);
-         record_full_core_buf_list = entry;
-       }
-      record_full_core_buf_list = NULL;
+      entry = record_full_core_buf_list;
+      record_full_core_buf_list = record_full_core_buf_list->prev;
+      xfree (entry);
     }
 
   if (record_full_async_inferior_event_token)
@@ -1030,9 +1024,12 @@ record_full_base_target::async (int enable)
   else
     clear_async_event_handler (record_full_async_inferior_event_token);
 
-  beneath->async (enable);
+  beneath ()->async (enable);
 }
 
+/* The PTID and STEP arguments last passed to
+   record_full_target::resume.  */
+static ptid_t record_full_resume_ptid = null_ptid;
 static int record_full_resume_step = 0;
 
 /* True if we've been resumed, and so each record_full_wait call should
@@ -1061,6 +1058,7 @@ static enum exec_direction_kind record_full_execution_dir = EXEC_FORWARD;
 void
 record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
+  record_full_resume_ptid = inferior_ptid;
   record_full_resume_step = step;
   record_full_resumed = 1;
   record_full_execution_dir = ::execution_direction;
@@ -1072,45 +1070,31 @@ record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
       record_full_message (get_current_regcache (), 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 supports soft single step.  */
-              if (thread_has_single_step_breakpoints_set (inferior_thread ()))
-                {
-                  /* This is a soft single step.  */
-                  record_full_resume_step = 1;
-                }
-              else
+       {
+         /* This is not hard single step.  */
+         if (!gdbarch_software_single_step_p (gdbarch))
+           {
+             /* This is a normal continue.  */
+             step = 1;
+           }
+         else
+           {
+             /* This arch supports soft single step.  */
+             if (thread_has_single_step_breakpoints_set (inferior_thread ()))
+               {
+                 /* This is a soft single step.  */
+                 record_full_resume_step = 1;
+               }
+             else
                step = !insert_single_step_breakpoints (gdbarch);
-            }
-        }
+           }
+       }
 
       /* Make sure the target beneath reports all signals.  */
-      target_pass_signals (0, NULL);
+      target_pass_signals ({});
 
-      this->beneath->resume (ptid, step, signal);
+      this->beneath ()->resume (ptid, step, signal);
     }
-
-  /* We are about to start executing the inferior (or simulate it),
-     let's register it with the event loop.  */
-  if (target_can_async_p ())
-    target_async (1);
-}
-
-/* "commit_resume" method for process record target.  */
-
-void
-record_full_target::commit_resume ()
-{
-  if (!RECORD_FULL_IS_REPLAY)
-    beneath->commit_resume ();
 }
 
 static int record_full_get_sig = 0;
@@ -1121,7 +1105,7 @@ static void
 record_full_sig_handler (int signo)
 {
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "Process record: get a signal\n");
+    gdb_printf (gdb_stdlog, "Process record: get a signal\n");
 
   /* It will break the running inferior in replay mode.  */
   record_full_resume_step = 1;
@@ -1131,18 +1115,6 @@ record_full_sig_handler (int signo)
   record_full_get_sig = 1;
 }
 
-static void
-record_full_wait_cleanups (void *ignore)
-{
-  if (execution_direction == EXEC_REVERSE)
-    {
-      if (record_full_list->next)
-       record_full_list = record_full_list->next;
-    }
-  else
-    record_full_list = record_full_list->prev;
-}
-
 /* "wait" target method for process record target.
 
    In record mode, the target is always run in singlestep mode
@@ -1159,26 +1131,26 @@ record_full_wait_cleanups (void *ignore)
 static ptid_t
 record_full_wait_1 (struct target_ops *ops,
                    ptid_t ptid, struct target_waitstatus *status,
-                   int options)
+                   target_wait_flags options)
 {
   scoped_restore restore_operation_disable
     = record_full_gdb_operation_disable_set ();
 
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "Process record: record_full_wait "
-                       "record_full_resume_step = %d, "
-                       "record_full_resumed = %d, direction=%s\n",
-                       record_full_resume_step, record_full_resumed,
-                       record_full_execution_dir == EXEC_FORWARD
-                       ? "forward" : "reverse");
+    gdb_printf (gdb_stdlog,
+               "Process record: record_full_wait "
+               "record_full_resume_step = %d, "
+               "record_full_resumed = %d, direction=%s\n",
+               record_full_resume_step, record_full_resumed,
+               record_full_execution_dir == EXEC_FORWARD
+               ? "forward" : "reverse");
 
   if (!record_full_resumed)
     {
       gdb_assert ((options & TARGET_WNOHANG) != 0);
 
       /* No interesting event.  */
-      status->kind = TARGET_WAITKIND_IGNORE;
+      status->set_ignore ();
       return minus_one_ptid;
     }
 
@@ -1192,38 +1164,37 @@ record_full_wait_1 (struct target_ops *ops,
       if (record_full_resume_step)
        {
          /* This is a single step.  */
-         return ops->beneath->wait (ptid, status, options);
+         return ops->beneath ()->wait (ptid, status, options);
        }
       else
        {
          /* This is not a single step.  */
          ptid_t ret;
          CORE_ADDR tmp_pc;
-         struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
+         struct gdbarch *gdbarch
+           = target_thread_architecture (record_full_resume_ptid);
 
          while (1)
            {
-             struct thread_info *tp;
-
-             ret = ops->beneath->wait (ptid, status, options);
-             if (status->kind == TARGET_WAITKIND_IGNORE)
+             ret = ops->beneath ()->wait (ptid, status, options);
+             if (status->kind () == TARGET_WAITKIND_IGNORE)
                {
                  if (record_debug)
-                   fprintf_unfiltered (gdb_stdlog,
-                                       "Process record: record_full_wait "
-                                       "target beneath not done yet\n");
+                   gdb_printf (gdb_stdlog,
+                               "Process record: record_full_wait "
+                               "target beneath not done yet\n");
                  return ret;
                }
 
-             ALL_NON_EXITED_THREADS (tp)
-                delete_single_step_breakpoints (tp);
+             for (thread_info *tp : all_non_exited_threads ())
+               delete_single_step_breakpoints (tp);
 
              if (record_full_resume_step)
                return ret;
 
              /* Is this a SIGTRAP?  */
-             if (status->kind == TARGET_WAITKIND_STOPPED
-                 && status->value.sig == GDB_SIGNAL_TRAP)
+             if (status->kind () == TARGET_WAITKIND_STOPPED
+                 && status->sig () == GDB_SIGNAL_TRAP)
                {
                  struct regcache *regcache;
                  enum target_stop_reason *stop_reason_p
@@ -1234,6 +1205,8 @@ record_full_wait_1 (struct target_ops *ops,
                     interested in the event.  */
 
                  registers_changed ();
+                 switch_to_thread (current_inferior ()->process_target (),
+                                   ret);
                  regcache = get_current_regcache ();
                  tmp_pc = regcache_read_pc (regcache);
                  const struct address_space *aspace = regcache->aspace ();
@@ -1251,38 +1224,44 @@ record_full_wait_1 (struct target_ops *ops,
                  else
                    {
                      /* 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;
+                        insn and issue another step.
+                        FIXME: this part can be a random SIGTRAP too.
+                        But GDB cannot handle it.  */
+                     int step = 1;
 
                      if (!record_full_message_wrapper_safe (regcache,
                                                             GDB_SIGNAL_0))
-                       {
-                           status->kind = TARGET_WAITKIND_STOPPED;
-                           status->value.sig = GDB_SIGNAL_0;
-                           break;
-                       }
+                       {
+                          status->set_stopped (GDB_SIGNAL_0);
+                          break;
+                       }
 
-                      if (gdbarch_software_single_step_p (gdbarch))
+                     process_stratum_target *proc_target
+                       = current_inferior ()->process_target ();
+
+                     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 ();
+                         set_executing (proc_target, inferior_ptid, false);
+                         SCOPE_EXIT
+                           {
+                             set_executing (proc_target, inferior_ptid, true);
+                           };
 
+                         reinit_frame_cache ();
                          step = !insert_single_step_breakpoints (gdbarch);
-
-                         set_executing (inferior_ptid, 1);
                        }
 
                      if (record_debug)
-                       fprintf_unfiltered (gdb_stdlog,
-                                           "Process record: record_full_wait "
-                                           "issuing one more step in the "
-                                           "target beneath\n");
-                     ops->beneath->resume (ptid, step, GDB_SIGNAL_0);
-                     ops->beneath->commit_resume ();
+                       gdb_printf (gdb_stdlog,
+                                   "Process record: record_full_wait "
+                                   "issuing one more step in the "
+                                   "target beneath\n");
+                     ops->beneath ()->resume (ptid, step, GDB_SIGNAL_0);
+                     proc_target->commit_resumed_state = true;
+                     proc_target->commit_resumed ();
+                     proc_target->commit_resumed_state = false;
                      continue;
                    }
                }
@@ -1296,149 +1275,172 @@ record_full_wait_1 (struct target_ops *ops,
     }
   else
     {
+      switch_to_thread (current_inferior ()->process_target (),
+                       record_full_resume_ptid);
       struct regcache *regcache = get_current_regcache ();
       struct gdbarch *gdbarch = regcache->arch ();
       const struct address_space *aspace = regcache->aspace ();
       int continue_flag = 1;
       int first_record_full_end = 1;
-      struct cleanup *old_cleanups
-       = make_cleanup (record_full_wait_cleanups, 0);
-      CORE_ADDR tmp_pc;
 
-      record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON;
-      status->kind = TARGET_WAITKIND_STOPPED;
-
-      /* Check breakpoint when forward execute.  */
-      if (execution_direction == EXEC_FORWARD)
+      try
        {
-         tmp_pc = regcache_read_pc (regcache);
-         if (record_check_stopped_by_breakpoint (aspace, tmp_pc,
-                                                 &record_full_stop_reason))
-           {
-             if (record_debug)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "Process record: break at %s.\n",
-                                   paddress (gdbarch, tmp_pc));
-             goto replay_out;
-           }
-       }
-
-      /* If GDB is in terminal_inferior mode, it will not get the signal.
-         And in GDB replay mode, GDB doesn't need to be in terminal_inferior
-         mode, because inferior will not executed.
-         Then set it to terminal_ours to make GDB get the signal.  */
-      target_terminal::ours ();
+         CORE_ADDR tmp_pc;
 
-      /* In EXEC_FORWARD mode, record_full_list points to the tail of prev
-         instruction.  */
-      if (execution_direction == EXEC_FORWARD && record_full_list->next)
-       record_full_list = record_full_list->next;
+         record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON;
+         status->set_stopped (GDB_SIGNAL_0);
 
-      /* Loop over the record_full_list, looking for the next place to
-        stop.  */
-      do
-       {
-         /* Check for beginning and end of log.  */
-         if (execution_direction == EXEC_REVERSE
-             && record_full_list == &record_full_first)
+         /* Check breakpoint when forward execute.  */
+         if (execution_direction == EXEC_FORWARD)
            {
-             /* Hit beginning of record log in reverse.  */
-             status->kind = TARGET_WAITKIND_NO_HISTORY;
-             break;
-           }
-         if (execution_direction != EXEC_REVERSE && !record_full_list->next)
-           {
-             /* Hit end of record log going forward.  */
-             status->kind = TARGET_WAITKIND_NO_HISTORY;
-             break;
+             tmp_pc = regcache_read_pc (regcache);
+             if (record_check_stopped_by_breakpoint (aspace, tmp_pc,
+                                                     &record_full_stop_reason))
+               {
+                 if (record_debug)
+                   gdb_printf (gdb_stdlog,
+                               "Process record: break at %s.\n",
+                               paddress (gdbarch, tmp_pc));
+                 goto replay_out;
+               }
            }
 
-          record_full_exec_insn (regcache, gdbarch, record_full_list);
-
-         if (record_full_list->type == record_full_end)
+         /* If GDB is in terminal_inferior mode, it will not get the
+            signal.  And in GDB replay mode, GDB doesn't need to be
+            in terminal_inferior mode, because inferior will not
+            executed.  Then set it to terminal_ours to make GDB get
+            the signal.  */
+         target_terminal::ours ();
+
+         /* In EXEC_FORWARD mode, record_full_list points to the tail of prev
+            instruction.  */
+         if (execution_direction == EXEC_FORWARD && record_full_list->next)
+           record_full_list = record_full_list->next;
+
+         /* Loop over the record_full_list, looking for the next place to
+            stop.  */
+         do
            {
-             if (record_debug > 1)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "Process record: record_full_end %s to "
-                                   "inferior.\n",
-                                   host_address_to_string (record_full_list));
-
-             if (first_record_full_end && execution_direction == EXEC_REVERSE)
+             /* Check for beginning and end of log.  */
+             if (execution_direction == EXEC_REVERSE
+                 && record_full_list == &record_full_first)
                {
-                 /* When reverse excute, the first record_full_end is the
-                    part of current instruction.  */
-                 first_record_full_end = 0;
+                 /* Hit beginning of record log in reverse.  */
+                 status->set_no_history ();
+                 break;
                }
-             else
+             if (execution_direction != EXEC_REVERSE
+                 && !record_full_list->next)
                {
-                 /* In EXEC_REVERSE mode, this is the record_full_end of prev
-                    instruction.
-                    In EXEC_FORWARD mode, this is the record_full_end of
-                    current instruction.  */
-                 /* step */
-                 if (record_full_resume_step)
+                 /* Hit end of record log going forward.  */
+                 status->set_no_history ();
+                 break;
+               }
+
+             record_full_exec_insn (regcache, gdbarch, record_full_list);
+
+             if (record_full_list->type == record_full_end)
+               {
+                 if (record_debug > 1)
+                   gdb_printf
+                     (gdb_stdlog,
+                      "Process record: record_full_end %s to "
+                      "inferior.\n",
+                      host_address_to_string (record_full_list));
+
+                 if (first_record_full_end
+                     && execution_direction == EXEC_REVERSE)
                    {
-                     if (record_debug > 1)
-                       fprintf_unfiltered (gdb_stdlog,
-                                           "Process record: step.\n");
-                     continue_flag = 0;
+                     /* When reverse execute, the first
+                        record_full_end is the part of current
+                        instruction.  */
+                     first_record_full_end = 0;
                    }
-
-                 /* check breakpoint */
-                 tmp_pc = regcache_read_pc (regcache);
-                 if (record_check_stopped_by_breakpoint (aspace, tmp_pc,
-                                                         &record_full_stop_reason))
+                 else
                    {
-                     if (record_debug)
-                       fprintf_unfiltered (gdb_stdlog,
-                                           "Process record: break "
-                                           "at %s.\n",
-                                           paddress (gdbarch, tmp_pc));
+                     /* In EXEC_REVERSE mode, this is the
+                        record_full_end of prev instruction.  In
+                        EXEC_FORWARD mode, this is the
+                        record_full_end of current instruction.  */
+                     /* step */
+                     if (record_full_resume_step)
+                       {
+                         if (record_debug > 1)
+                           gdb_printf (gdb_stdlog,
+                                       "Process record: step.\n");
+                         continue_flag = 0;
+                       }
+
+                     /* check breakpoint */
+                     tmp_pc = regcache_read_pc (regcache);
+                     if (record_check_stopped_by_breakpoint
+                         (aspace, tmp_pc, &record_full_stop_reason))
+                       {
+                         if (record_debug)
+                           gdb_printf (gdb_stdlog,
+                                       "Process record: break "
+                                       "at %s.\n",
+                                       paddress (gdbarch, tmp_pc));
 
-                     continue_flag = 0;
+                         continue_flag = 0;
+                       }
+
+                     if (record_full_stop_reason
+                         == TARGET_STOPPED_BY_WATCHPOINT)
+                       {
+                         if (record_debug)
+                           gdb_printf (gdb_stdlog,
+                                       "Process record: hit hw "
+                                       "watchpoint.\n");
+                         continue_flag = 0;
+                       }
+                     /* Check target signal */
+                     if (record_full_list->u.end.sigval != GDB_SIGNAL_0)
+                       /* FIXME: better way to check */
+                       continue_flag = 0;
                    }
+               }
 
-                 if (record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT)
+             if (continue_flag)
+               {
+                 if (execution_direction == EXEC_REVERSE)
                    {
-                     if (record_debug)
-                       fprintf_unfiltered (gdb_stdlog,
-                                           "Process record: hit hw "
-                                           "watchpoint.\n");
-                     continue_flag = 0;
+                     if (record_full_list->prev)
+                       record_full_list = record_full_list->prev;
+                   }
+                 else
+                   {
+                     if (record_full_list->next)
+                       record_full_list = record_full_list->next;
                    }
-                 /* Check target signal */
-                 if (record_full_list->u.end.sigval != GDB_SIGNAL_0)
-                   /* FIXME: better way to check */
-                   continue_flag = 0;
                }
            }
+         while (continue_flag);
 
-         if (continue_flag)
+       replay_out:
+         if (status->kind () == TARGET_WAITKIND_STOPPED)
            {
-             if (execution_direction == EXEC_REVERSE)
-               {
-                 if (record_full_list->prev)
-                   record_full_list = record_full_list->prev;
-               }
+             if (record_full_get_sig)
+               status->set_stopped (GDB_SIGNAL_INT);
+             else if (record_full_list->u.end.sigval != GDB_SIGNAL_0)
+               /* FIXME: better way to check */
+               status->set_stopped (record_full_list->u.end.sigval);
              else
-               {
-                 if (record_full_list->next)
-                   record_full_list = record_full_list->next;
-               }
+               status->set_stopped (GDB_SIGNAL_TRAP);
            }
        }
-      while (continue_flag);
-
-replay_out:
-      if (record_full_get_sig)
-       status->value.sig = GDB_SIGNAL_INT;
-      else if (record_full_list->u.end.sigval != GDB_SIGNAL_0)
-       /* FIXME: better way to check */
-       status->value.sig = record_full_list->u.end.sigval;
-      else
-       status->value.sig = GDB_SIGNAL_TRAP;
+      catch (const gdb_exception &ex)
+       {
+         if (execution_direction == EXEC_REVERSE)
+           {
+             if (record_full_list->next)
+               record_full_list = record_full_list->next;
+           }
+         else
+           record_full_list = record_full_list->prev;
 
-      discard_cleanups (old_cleanups);
+         throw;
+       }
     }
 
   signal (SIGINT, handle_sigint);
@@ -1448,12 +1450,14 @@ replay_out:
 
 ptid_t
 record_full_base_target::wait (ptid_t ptid, struct target_waitstatus *status,
-                              int options)
+                              target_wait_flags options)
 {
   ptid_t return_ptid;
 
+  clear_async_event_handler (record_full_async_inferior_event_token);
+
   return_ptid = record_full_wait_1 (this, ptid, status, options);
-  if (status->kind != TARGET_WAITKIND_IGNORE)
+  if (status->kind () != TARGET_WAITKIND_IGNORE)
     {
       /* We're reporting a stop.  Make sure any spurious
         target_wait(WNOHANG) doesn't advance the target until the
@@ -1463,27 +1467,27 @@ record_full_base_target::wait (ptid_t ptid, struct target_waitstatus *status,
   return return_ptid;
 }
 
-int
+bool
 record_full_base_target::stopped_by_watchpoint ()
 {
   if (RECORD_FULL_IS_REPLAY)
     return record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
   else
-    return beneath->stopped_by_watchpoint ();
+    return beneath ()->stopped_by_watchpoint ();
 }
 
-int
+bool
 record_full_base_target::stopped_data_address (CORE_ADDR *addr_p)
 {
   if (RECORD_FULL_IS_REPLAY)
-    return 0;
+    return false;
   else
-    return this->beneath->stopped_data_address (addr_p);
+    return this->beneath ()->stopped_data_address (addr_p);
 }
 
 /* The stopped_by_sw_breakpoint method of target record-full.  */
 
-int
+bool
 record_full_base_target::stopped_by_sw_breakpoint ()
 {
   return record_full_stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
@@ -1492,15 +1496,15 @@ record_full_base_target::stopped_by_sw_breakpoint ()
 /* The supports_stopped_by_sw_breakpoint method of target
    record-full.  */
 
-int
+bool
 record_full_base_target::supports_stopped_by_sw_breakpoint ()
 {
-  return 1;
+  return true;
 }
 
 /* The stopped_by_hw_breakpoint method of target record-full.  */
 
-int
+bool
 record_full_base_target::stopped_by_hw_breakpoint ()
 {
   return record_full_stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
@@ -1509,10 +1513,10 @@ record_full_base_target::stopped_by_hw_breakpoint ()
 /* The supports_stopped_by_sw_breakpoint method of target
    record-full.  */
 
-int
+bool
 record_full_base_target::supports_stopped_by_hw_breakpoint ()
 {
-  return 1;
+  return true;
 }
 
 /* Record registers change (by user or by GDB) to list as an instruction.  */
@@ -1591,7 +1595,7 @@ record_full_target::store_registers (struct regcache *regcache, int regno)
          if (!n)
            {
              /* Invalidate the value of regcache that was set in function
-                "regcache_raw_write".  */
+                "regcache_raw_write".  */
              if (regno < 0)
                {
                  int i;
@@ -1599,10 +1603,10 @@ record_full_target::store_registers (struct regcache *regcache, int regno)
                  for (i = 0;
                       i < gdbarch_num_regs (regcache->arch ());
                       i++)
-                   regcache_invalidate (regcache, i);
+                   regcache->invalidate (i);
                }
              else
-               regcache_invalidate (regcache, regno);
+               regcache->invalidate (regno);
 
              error (_("Process record canceled the operation."));
            }
@@ -1613,7 +1617,7 @@ record_full_target::store_registers (struct regcache *regcache, int regno)
 
       record_full_registers_change (regcache, regno);
     }
-  this->beneath->store_registers (regcache, regno);
+  this->beneath ()->store_registers (regcache, regno);
 }
 
 /* "xfer_partial" method.  Behavior is conditional on
@@ -1635,8 +1639,8 @@ record_full_target::xfer_partial (enum target_object object,
        {
          /* Let user choose if he wants to write memory or not.  */
          if (!query (_("Because GDB is in replay mode, writing to memory "
-                       "will make the execution log unusable from this "
-                       "point onward.  Write memory at address %s?"),
+                       "will make the execution log unusable from this "
+                       "point onward.  Write memory at address %s?"),
                       paddress (target_gdbarch (), offset)))
            error (_("Process record canceled the operation."));
 
@@ -1654,18 +1658,18 @@ record_full_target::xfer_partial (enum target_object object,
        {
          record_full_list_release (record_full_arch_list_tail);
          if (record_debug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "Process record: failed to record "
-                               "execution log.");
+           gdb_printf (gdb_stdlog,
+                       "Process record: failed to record "
+                       "execution log.");
          return TARGET_XFER_E_IO;
        }
       if (record_full_arch_list_add_end ())
        {
          record_full_list_release (record_full_arch_list_tail);
          if (record_debug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "Process record: failed to record "
-                               "execution log.");
+           gdb_printf (gdb_stdlog,
+                       "Process record: failed to record "
+                       "execution log.");
          return TARGET_XFER_E_IO;
        }
       record_full_list->next = record_full_arch_list_head;
@@ -1678,8 +1682,8 @@ record_full_target::xfer_partial (enum target_object object,
        record_full_insn_num++;
     }
 
-  return this->beneath->xfer_partial (object, annex, readbuf, writebuf, offset,
-                                     len, xfered_len);
+  return this->beneath ()->xfer_partial (object, annex, readbuf, writebuf,
+                                        offset, len, xfered_len);
 }
 
 /* This structure represents a breakpoint inserted while the record
@@ -1691,6 +1695,15 @@ record_full_target::xfer_partial (enum target_object object,
 
 struct record_full_breakpoint
 {
+  record_full_breakpoint (struct address_space *address_space_,
+                         CORE_ADDR addr_,
+                         bool in_target_beneath_)
+    : address_space (address_space_),
+      addr (addr_),
+      in_target_beneath (in_target_beneath_)
+  {
+  }
+
   /* The address and address space the breakpoint was set at.  */
   struct address_space *address_space;
   CORE_ADDR addr;
@@ -1698,43 +1711,30 @@ struct record_full_breakpoint
   /* True when the breakpoint has been also installed in the target
      beneath.  This will be false for breakpoints set during replay or
      when recording.  */
-  int in_target_beneath;
+  bool in_target_beneath;
 };
 
-typedef struct record_full_breakpoint *record_full_breakpoint_p;
-DEF_VEC_P(record_full_breakpoint_p);
-
 /* The list of breakpoints inserted while the record target is
    active.  */
-VEC(record_full_breakpoint_p) *record_full_breakpoints = NULL;
-
-static void
-record_full_sync_record_breakpoints (struct bp_location *loc, void *data)
-{
-  if (loc->loc_type != bp_loc_software_breakpoint)
-      return;
-
-  if (loc->inserted)
-    {
-      struct record_full_breakpoint *bp = XNEW (struct record_full_breakpoint);
-
-      bp->addr = loc->target_info.placed_address;
-      bp->address_space = loc->target_info.placed_address_space;
-
-      bp->in_target_beneath = 1;
-
-      VEC_safe_push (record_full_breakpoint_p, record_full_breakpoints, bp);
-    }
-}
+static std::vector<record_full_breakpoint> record_full_breakpoints;
 
 /* Sync existing breakpoints to record_full_breakpoints.  */
 
 static void
 record_full_init_record_breakpoints (void)
 {
-  VEC_free (record_full_breakpoint_p, record_full_breakpoints);
+  record_full_breakpoints.clear ();
+
+  for (bp_location *loc : all_bp_locations ())
+    {
+      if (loc->loc_type != bp_loc_software_breakpoint)
+       continue;
 
-  iterate_over_bp_locations (record_full_sync_record_breakpoints);
+      if (loc->inserted)
+       record_full_breakpoints.emplace_back
+         (loc->target_info.placed_address_space,
+          loc->target_info.placed_address, 1);
+    }
 }
 
 /* Behavior is conditional on RECORD_FULL_IS_REPLAY.  We will not actually
@@ -1745,9 +1745,7 @@ int
 record_full_target::insert_breakpoint (struct gdbarch *gdbarch,
                                       struct bp_target_info *bp_tgt)
 {
-  struct record_full_breakpoint *bp;
-  int in_target_beneath = 0;
-  int ix;
+  bool in_target_beneath = false;
 
   if (!RECORD_FULL_IS_REPLAY)
     {
@@ -1760,34 +1758,29 @@ record_full_target::insert_breakpoint (struct gdbarch *gdbarch,
       scoped_restore restore_operation_disable
        = record_full_gdb_operation_disable_set ();
 
-      int ret = this->beneath->insert_breakpoint (gdbarch, bp_tgt);
+      int ret = this->beneath ()->insert_breakpoint (gdbarch, bp_tgt);
       if (ret != 0)
        return ret;
 
-      in_target_beneath = 1;
+      in_target_beneath = true;
     }
 
   /* 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)
+  for (const record_full_breakpoint &bp : record_full_breakpoints)
     {
-      if (bp->addr == bp_tgt->placed_address
-         && bp->address_space == bp_tgt->placed_address_space)
+      if (bp.addr == bp_tgt->placed_address
+         && bp.address_space == bp_tgt->placed_address_space)
        {
-         gdb_assert (bp->in_target_beneath == in_target_beneath);
+         gdb_assert (bp.in_target_beneath == in_target_beneath);
          return 0;
        }
     }
 
-  bp = XNEW (struct record_full_breakpoint);
-  bp->addr = bp_tgt->placed_address;
-  bp->address_space = bp_tgt->placed_address_space;
-  bp->in_target_beneath = in_target_beneath;
-  VEC_safe_push (record_full_breakpoint_p, record_full_breakpoints, bp);
+  record_full_breakpoints.emplace_back (bp_tgt->placed_address_space,
+                                       bp_tgt->placed_address,
+                                       in_target_beneath);
   return 0;
 }
 
@@ -1798,33 +1791,28 @@ record_full_target::remove_breakpoint (struct gdbarch *gdbarch,
                                       struct bp_target_info *bp_tgt,
                                       enum remove_bp_reason reason)
 {
-  struct record_full_breakpoint *bp;
-  int ix;
-
-  for (ix = 0;
-       VEC_iterate (record_full_breakpoint_p,
-                   record_full_breakpoints, ix, bp);
-       ++ix)
+  for (auto iter = record_full_breakpoints.begin ();
+       iter != record_full_breakpoints.end ();
+       ++iter)
     {
-      if (bp->addr == bp_tgt->placed_address
-         && bp->address_space == bp_tgt->placed_address_space)
+      struct record_full_breakpoint &bp = *iter;
+
+      if (bp.addr == bp_tgt->placed_address
+         && bp.address_space == bp_tgt->placed_address_space)
        {
-         if (bp->in_target_beneath)
+         if (bp.in_target_beneath)
            {
              scoped_restore restore_operation_disable
                = record_full_gdb_operation_disable_set ();
 
-             int ret = this->beneath->remove_breakpoint (gdbarch, bp_tgt,
-                                                         reason);
+             int ret = this->beneath ()->remove_breakpoint (gdbarch, bp_tgt,
+                                                            reason);
              if (ret != 0)
                return ret;
            }
 
          if (reason == REMOVE_BREAKPOINT)
-           {
-             VEC_unordered_remove (record_full_breakpoint_p,
-                                   record_full_breakpoints, ix);
-           }
+           unordered_remove (record_full_breakpoints, iter);
          return 0;
        }
     }
@@ -1834,10 +1822,10 @@ record_full_target::remove_breakpoint (struct gdbarch *gdbarch,
 
 /* "can_execute_reverse" method for process record target.  */
 
-int
+bool
 record_full_base_target::can_execute_reverse ()
 {
-  return 1;
+  return true;
 }
 
 /* "get_bookmark" method for process record and prec over core.  */
@@ -1854,11 +1842,11 @@ record_full_base_target::get_bookmark (const char *args, int from_tty)
   if (record_debug)
     {
       if (ret)
-       fprintf_unfiltered (gdb_stdlog,
-                           "record_full_get_bookmark returns %s\n", ret);
+       gdb_printf (gdb_stdlog,
+                   "record_full_get_bookmark returns %s\n", ret);
       else
-       fprintf_unfiltered (gdb_stdlog,
-                           "record_full_get_bookmark returns NULL\n");
+       gdb_printf (gdb_stdlog,
+                   "record_full_get_bookmark returns NULL\n");
     }
   return (gdb_byte *) ret;
 }
@@ -1872,8 +1860,8 @@ record_full_base_target::goto_bookmark (const gdb_byte *raw_bookmark,
   const char *bookmark = (const char *) raw_bookmark;
 
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "record_full_goto_bookmark receives %s\n", bookmark);
+    gdb_printf (gdb_stdlog,
+               "record_full_goto_bookmark receives %s\n", bookmark);
 
   std::string name_holder;
   if (bookmark[0] == '\'' || bookmark[0] == '\"')
@@ -1908,9 +1896,9 @@ record_full_base_target::info_record ()
   struct record_full_entry *p;
 
   if (RECORD_FULL_IS_REPLAY)
-    printf_filtered (_("Replay mode:\n"));
+    gdb_printf (_("Replay mode:\n"));
   else
-    printf_filtered (_("Record mode:\n"));
+    gdb_printf (_("Record mode:\n"));
 
   /* Find entry for first actual instruction in the log.  */
   for (p = record_full_first.next;
@@ -1922,28 +1910,28 @@ record_full_base_target::info_record ()
   if (p != NULL && p->type == record_full_end)
     {
       /* Display instruction number for first instruction in the log.  */
-      printf_filtered (_("Lowest recorded instruction number is %s.\n"),
-                      pulongest (p->u.end.insn_num));
+      gdb_printf (_("Lowest recorded instruction number is %s.\n"),
+                 pulongest (p->u.end.insn_num));
 
       /* If in replay mode, display where we are in the log.  */
       if (RECORD_FULL_IS_REPLAY)
-       printf_filtered (_("Current instruction number is %s.\n"),
-                        pulongest (record_full_list->u.end.insn_num));
+       gdb_printf (_("Current instruction number is %s.\n"),
+                   pulongest (record_full_list->u.end.insn_num));
 
       /* Display instruction number for last instruction in the log.  */
-      printf_filtered (_("Highest recorded instruction number is %s.\n"),
-                      pulongest (record_full_insn_count));
+      gdb_printf (_("Highest recorded instruction number is %s.\n"),
+                 pulongest (record_full_insn_count));
 
       /* Display log count.  */
-      printf_filtered (_("Log contains %u instructions.\n"),
-                      record_full_insn_num);
+      gdb_printf (_("Log contains %u instructions.\n"),
+                 record_full_insn_num);
     }
   else
-    printf_filtered (_("No instructions have been logged.\n"));
+    gdb_printf (_("No instructions have been logged.\n"));
 
   /* Display max log size.  */
-  printf_filtered (_("Max logged instructions is %u.\n"),
-                  record_full_insn_max_num);
+  gdb_printf (_("Max logged instructions is %u.\n"),
+             record_full_insn_max_num);
 }
 
 bool
@@ -1962,7 +1950,7 @@ record_full_base_target::delete_record ()
 
 /* The "record_is_replaying" target method.  */
 
-int
+bool
 record_full_base_target::record_is_replaying (ptid_t ptid)
 {
   return RECORD_FULL_IS_REPLAY;
@@ -1970,7 +1958,7 @@ record_full_base_target::record_is_replaying (ptid_t ptid)
 
 /* The "record_will_replay" target method.  */
 
-int
+bool
 record_full_base_target::record_will_replay (ptid_t ptid, int dir)
 {
   /* We can currently only record when executing forwards.  Should we be able
@@ -1991,20 +1979,20 @@ record_full_goto_entry (struct record_full_entry *p)
     error (_("Already at target insn."));
   else if (p->u.end.insn_num > record_full_list->u.end.insn_num)
     {
-      printf_filtered (_("Go forward to insn number %s\n"),
-                      pulongest (p->u.end.insn_num));
+      gdb_printf (_("Go forward to insn number %s\n"),
+                 pulongest (p->u.end.insn_num));
       record_full_goto_insn (p, EXEC_FORWARD);
     }
   else
     {
-      printf_filtered (_("Go backward to insn number %s\n"),
-                      pulongest (p->u.end.insn_num));
+      gdb_printf (_("Go backward to insn number %s\n"),
+                 pulongest (p->u.end.insn_num));
       record_full_goto_insn (p, EXEC_REVERSE);
     }
 
   registers_changed ();
   reinit_frame_cache ();
-  stop_pc = regcache_read_pc (get_current_regcache ());
+  inferior_thread ()->set_stop_pc (regcache_read_pc (get_current_regcache ()));
   print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
 }
 
@@ -2069,11 +2057,6 @@ record_full_core_target::resume (ptid_t ptid, int step,
   record_full_resume_step = step;
   record_full_resumed = 1;
   record_full_execution_dir = ::execution_direction;
-
-  /* We are about to start executing the inferior (or simulate it),
-     let's register it with the event loop.  */
-  if (target_can_async_p ())
-    target_async (1);
 }
 
 /* "kill" method for prec over corefile.  */
@@ -2082,9 +2065,9 @@ void
 record_full_core_target::kill ()
 {
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "Process record: record_full_core_kill\n");
+    gdb_printf (gdb_stdlog, "Process record: record_full_core_kill\n");
 
-  unpush_target (this);
+  current_inferior ()->unpush_target (this);
 }
 
 /* "fetch_registers" method for prec over corefile.  */
@@ -2136,27 +2119,25 @@ record_full_core_target::xfer_partial (enum target_object object,
     {
       if (record_full_gdb_operation_disable || !writebuf)
        {
-         struct target_section *p;
-
-         for (p = record_full_core_start; p < record_full_core_end; p++)
+         for (target_section &p : record_full_core_sections)
            {
-             if (offset >= p->addr)
+             if (offset >= p.addr)
                {
                  struct record_full_core_buf_entry *entry;
                  ULONGEST sec_offset;
 
-                 if (offset >= p->endaddr)
+                 if (offset >= p.endaddr)
                    continue;
 
-                 if (offset + len > p->endaddr)
-                   len = p->endaddr - offset;
+                 if (offset + len > p.endaddr)
+                   len = p.endaddr - offset;
 
-                 sec_offset = offset - p->addr;
+                 sec_offset = offset - p.addr;
 
                  /* Read readbuf or write writebuf p, offset, len.  */
                  /* Check flags.  */
-                 if (p->the_bfd_section->flags & SEC_CONSTRUCTOR
-                     || (p->the_bfd_section->flags & SEC_HAS_CONTENTS) == 0)
+                 if (p.the_bfd_section->flags & SEC_CONSTRUCTOR
+                     || (p.the_bfd_section->flags & SEC_HAS_CONTENTS) == 0)
                    {
                      if (readbuf)
                        memset (readbuf, 0, len);
@@ -2167,7 +2148,7 @@ record_full_core_target::xfer_partial (enum target_object object,
                  /* Get record_full_core_buf_entry.  */
                  for (entry = record_full_core_buf_list; entry;
                       entry = entry->prev)
-                   if (entry->p == p)
+                   if (entry->p == &p)
                      break;
                  if (writebuf)
                    {
@@ -2175,10 +2156,10 @@ record_full_core_target::xfer_partial (enum target_object object,
                        {
                          /* Add a new entry.  */
                          entry = XNEW (struct record_full_core_buf_entry);
-                         entry->p = p;
+                         entry->p = &p;
                          if (!bfd_malloc_and_get_section
-                               (p->the_bfd_section->owner,
-                                p->the_bfd_section,
+                               (p.the_bfd_section->owner,
+                                p.the_bfd_section,
                                 &entry->buf))
                            {
                              xfree (entry);
@@ -2194,10 +2175,10 @@ record_full_core_target::xfer_partial (enum target_object object,
                  else
                    {
                      if (!entry)
-                       return this->beneath->xfer_partial (object, annex,
-                                                           readbuf, writebuf,
-                                                           offset, len,
-                                                           xfered_len);
+                       return this->beneath ()->xfer_partial (object, annex,
+                                                              readbuf, writebuf,
+                                                              offset, len,
+                                                              xfered_len);
 
                      memcpy (readbuf, entry->buf + sec_offset,
                              (size_t) len);
@@ -2214,9 +2195,9 @@ record_full_core_target::xfer_partial (enum target_object object,
        error (_("You can't do that without a process to debug."));
     }
 
-  return this->beneath->xfer_partial (object, annex,
-                                     readbuf, writebuf, offset, len,
-                                     xfered_len);
+  return this->beneath ()->xfer_partial (object, annex,
+                                        readbuf, writebuf, offset, len,
+                                        xfered_len);
 }
 
 /* "insert_breakpoint" method for prec over corefile.  */
@@ -2240,10 +2221,10 @@ record_full_core_target::remove_breakpoint (struct gdbarch *gdbarch,
 
 /* "has_execution" method for prec over corefile.  */
 
-int
-record_full_core_target::has_execution (ptid_t the_ptid)
+bool
+record_full_core_target::has_execution (inferior *inf)
 {
-  return 1;
+  return true;
 }
 
 /* Record log save-file format
@@ -2279,7 +2260,7 @@ record_full_core_target::has_execution (ptid_t the_ptid)
        1 byte:  record type (record_full_reg, see enum record_full_type).
        4 bytes: register id (network byte order).
        n bytes: register value (n == actual register size).
-                (eg. 4 bytes for x86 general registers).
+               (eg. 4 bytes for x86 general registers).
      record_full_mem:
        1 byte:  record type (record_full_mem, see enum record_full_type).
        4 bytes: memory length (network byte order).
@@ -2328,7 +2309,6 @@ static void
 record_full_restore (void)
 {
   uint32_t magic;
-  struct cleanup *old_cleanups;
   struct record_full_entry *rec;
   asection *osec;
   uint32_t osec_size;
@@ -2344,18 +2324,18 @@ record_full_restore (void)
   gdb_assert (record_full_first.next == NULL);
  
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "Restoring recording from core file.\n");
+    gdb_printf (gdb_stdlog, "Restoring recording from core file.\n");
 
   /* Now need to find our special note section.  */
   osec = bfd_get_section_by_name (core_bfd, "null0");
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "Find precord section %s.\n",
-                       osec ? "succeeded" : "failed");
+    gdb_printf (gdb_stdlog, "Find precord section %s.\n",
+               osec ? "succeeded" : "failed");
   if (osec == NULL)
     return;
-  osec_size = bfd_section_size (core_bfd, osec);
+  osec_size = bfd_section_size (osec);
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "%s", bfd_section_name (core_bfd, osec));
+    gdb_printf (gdb_stdlog, "%s", bfd_section_name (osec));
 
   /* Check the magic code.  */
   bfdcore_read (core_bfd, osec, &magic, sizeof (magic), &bfd_offset);
@@ -2363,118 +2343,124 @@ record_full_restore (void)
     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_FULL_FILE_MAGIC (0x%s)\n",
-                       phex_nz (netorder32 (magic), 4));
+    gdb_printf (gdb_stdlog,
+               "  Reading 4-byte magic cookie "
+               "RECORD_FULL_FILE_MAGIC (0x%s)\n",
+               phex_nz (netorder32 (magic), 4));
 
   /* Restore the entries in recfd into record_full_arch_list_head and
      record_full_arch_list_tail.  */
   record_full_arch_list_head = NULL;
   record_full_arch_list_tail = NULL;
   record_full_insn_num = 0;
-  old_cleanups = make_cleanup (record_full_arch_list_cleanups, 0);
-  regcache = get_current_regcache ();
 
-  while (1)
+  try
     {
-      uint8_t rectype;
-      uint32_t regnum, len, signal, count;
-      uint64_t addr;
+      regcache = get_current_regcache ();
 
-      /* We are finished when offset reaches osec_size.  */
-      if (bfd_offset >= osec_size)
-       break;
-      bfdcore_read (core_bfd, osec, &rectype, sizeof (rectype), &bfd_offset);
+      while (1)
+       {
+         uint8_t rectype;
+         uint32_t regnum, len, signal, count;
+         uint64_t addr;
 
-      switch (rectype)
-        {
-        case record_full_reg: /* reg */
-          /* Get register number to regnum.  */
-          bfdcore_read (core_bfd, osec, &regnum,
-                       sizeof (regnum), &bfd_offset);
-         regnum = netorder32 (regnum);
+         /* We are finished when offset reaches osec_size.  */
+         if (bfd_offset >= osec_size)
+           break;
+         bfdcore_read (core_bfd, osec, &rectype, sizeof (rectype), &bfd_offset);
 
-          rec = record_full_reg_alloc (regcache, regnum);
+         switch (rectype)
+           {
+           case record_full_reg: /* reg */
+             /* Get register number to regnum.  */
+             bfdcore_read (core_bfd, osec, &regnum,
+                           sizeof (regnum), &bfd_offset);
+             regnum = netorder32 (regnum);
 
-          /* Get val.  */
-          bfdcore_read (core_bfd, osec, record_full_get_loc (rec),
-                       rec->u.reg.len, &bfd_offset);
+             rec = record_full_reg_alloc (regcache, regnum);
 
-         if (record_debug)
-           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);
-          break;
-
-        case record_full_mem: /* mem */
-          /* Get len.  */
-          bfdcore_read (core_bfd, osec, &len, 
-                       sizeof (len), &bfd_offset);
-         len = netorder32 (len);
-
-          /* Get addr.  */
-          bfdcore_read (core_bfd, osec, &addr,
-                       sizeof (addr), &bfd_offset);
-         addr = netorder64 (addr);
-
-          rec = record_full_mem_alloc (addr, len);
-
-          /* Get val.  */
-          bfdcore_read (core_bfd, osec, record_full_get_loc (rec),
-                       rec->u.mem.len, &bfd_offset);
+             /* Get val.  */
+             bfdcore_read (core_bfd, osec, record_full_get_loc (rec),
+                           rec->u.reg.len, &bfd_offset);
 
-         if (record_debug)
-           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),
-                               (unsigned long) sizeof (len),
-                               rec->u.mem.len);
-          break;
-
-        case record_full_end: /* end */
-          rec = record_full_end_alloc ();
-          record_full_insn_num ++;
-
-         /* Get signal value.  */
-         bfdcore_read (core_bfd, osec, &signal, 
-                       sizeof (signal), &bfd_offset);
-         signal = netorder32 (signal);
-         rec->u.end.sigval = (enum gdb_signal) signal;
-
-         /* Get insn count.  */
-         bfdcore_read (core_bfd, osec, &count, 
-                       sizeof (count), &bfd_offset);
-         count = netorder32 (count);
-         rec->u.end.insn_num = count;
-         record_full_insn_count = count + 1;
-         if (record_debug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "  Reading record_full_end (1 + "
-                               "%lu + %lu bytes), offset == %s\n",
-                               (unsigned long) sizeof (signal),
-                               (unsigned long) sizeof (count),
-                               paddress (get_current_arch (),
-                                         bfd_offset));
-          break;
-
-        default:
-          error (_("Bad entry type in core file %s."),
-                bfd_get_filename (core_bfd));
-          break;
-        }
-
-      /* Add rec to record arch list.  */
-      record_full_arch_list_add (rec);
-    }
+             if (record_debug)
+               gdb_printf (gdb_stdlog,
+                           "  Reading register %d (1 "
+                           "plus %lu plus %d bytes)\n",
+                           rec->u.reg.num,
+                           (unsigned long) sizeof (regnum),
+                           rec->u.reg.len);
+             break;
+
+           case record_full_mem: /* mem */
+             /* Get len.  */
+             bfdcore_read (core_bfd, osec, &len,
+                           sizeof (len), &bfd_offset);
+             len = netorder32 (len);
+
+             /* Get addr.  */
+             bfdcore_read (core_bfd, osec, &addr,
+                           sizeof (addr), &bfd_offset);
+             addr = netorder64 (addr);
+
+             rec = record_full_mem_alloc (addr, len);
+
+             /* Get val.  */
+             bfdcore_read (core_bfd, osec, record_full_get_loc (rec),
+                           rec->u.mem.len, &bfd_offset);
 
-  discard_cleanups (old_cleanups);
+             if (record_debug)
+               gdb_printf (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),
+                           (unsigned long) sizeof (len),
+                           rec->u.mem.len);
+             break;
+
+           case record_full_end: /* end */
+             rec = record_full_end_alloc ();
+             record_full_insn_num ++;
+
+             /* Get signal value.  */
+             bfdcore_read (core_bfd, osec, &signal,
+                           sizeof (signal), &bfd_offset);
+             signal = netorder32 (signal);
+             rec->u.end.sigval = (enum gdb_signal) signal;
+
+             /* Get insn count.  */
+             bfdcore_read (core_bfd, osec, &count,
+                           sizeof (count), &bfd_offset);
+             count = netorder32 (count);
+             rec->u.end.insn_num = count;
+             record_full_insn_count = count + 1;
+             if (record_debug)
+               gdb_printf (gdb_stdlog,
+                           "  Reading record_full_end (1 + "
+                           "%lu + %lu bytes), offset == %s\n",
+                           (unsigned long) sizeof (signal),
+                           (unsigned long) sizeof (count),
+                           paddress (get_current_arch (),
+                                     bfd_offset));
+             break;
+
+           default:
+             error (_("Bad entry type in core file %s."),
+                    bfd_get_filename (core_bfd));
+             break;
+           }
+
+         /* Add rec to record arch list.  */
+         record_full_arch_list_add (rec);
+       }
+    }
+  catch (const gdb_exception &ex)
+    {
+      record_full_list_release (record_full_arch_list_tail);
+      throw;
+    }
 
   /* Add record_full_arch_list_head to the end of record list.  */
   record_full_first.next = record_full_arch_list_head;
@@ -2487,12 +2473,12 @@ record_full_restore (void)
     {
       record_full_insn_max_num = record_full_insn_num;
       warning (_("Auto increase record/replay buffer limit to %u."),
-               record_full_insn_max_num);
+              record_full_insn_max_num);
     }
 
   /* Succeeded.  */
-  printf_filtered (_("Restored records from core file %s.\n"),
-                  bfd_get_filename (core_bfd));
+  gdb_printf (_("Restored records from core file %s.\n"),
+             bfd_get_filename (core_bfd));
 
   print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
 }
@@ -2519,7 +2505,7 @@ static void
 cmd_record_full_restore (const char *args, int from_tty)
 {
   core_file_command (args, from_tty);
-  record_full_ops.open (args, from_tty);
+  record_full_open (args, from_tty);
 }
 
 /* Save the execution log to a file.  We use a modified elf corefile
@@ -2538,8 +2524,8 @@ record_full_base_target::save_record (const char *recfilename)
 
   /* Open the save file.  */
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog, "Saving execution log to core file '%s'\n",
-                       recfilename);
+    gdb_printf (gdb_stdlog, "Saving execution log to core file '%s'\n",
+               recfilename);
 
   /* Open the output file.  */
   gdb_bfd_ref_ptr obfd (create_gcore_bfd (recfilename));
@@ -2563,12 +2549,12 @@ record_full_base_target::save_record (const char *recfilename)
     {
       /* Check for beginning and end of log.  */
       if (record_full_list == &record_full_first)
-        break;
+       break;
 
       record_full_exec_insn (regcache, gdbarch, record_full_list);
 
       if (record_full_list->prev)
-        record_full_list = record_full_list->prev;
+       record_full_list = record_full_list->prev;
     }
 
   /* Compute the size needed for the extra bfd section.  */
@@ -2590,16 +2576,15 @@ record_full_base_target::save_record (const char *recfilename)
 
   /* Make the new bfd section.  */
   osec = bfd_make_section_anyway_with_flags (obfd.get (), "precord",
-                                             SEC_HAS_CONTENTS
-                                             | SEC_READONLY);
+                                            SEC_HAS_CONTENTS
+                                            | SEC_READONLY);
   if (osec == NULL)
     error (_("Failed to create 'precord' section for corefile %s: %s"),
           recfilename,
-           bfd_errmsg (bfd_get_error ()));
-  bfd_set_section_size (obfd.get (), osec, save_size);
-  bfd_set_section_vma (obfd.get (), osec, 0);
-  bfd_set_section_alignment (obfd.get (), osec, 0);
-  bfd_section_lma (obfd.get (), osec) = 0;
+          bfd_errmsg (bfd_get_error ()));
+  bfd_set_section_size (osec, save_size);
+  bfd_set_section_vma (osec, 0);
+  bfd_set_section_alignment (osec, 0);
 
   /* Save corefile state.  */
   write_gcore_file (obfd.get ());
@@ -2608,10 +2593,10 @@ record_full_base_target::save_record (const char *recfilename)
   /* Write the magic code.  */
   magic = RECORD_FULL_FILE_MAGIC;
   if (record_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "  Writing 4-byte magic cookie "
-                       "RECORD_FULL_FILE_MAGIC (0x%s)\n",
-                     phex_nz (magic, 4));
+    gdb_printf (gdb_stdlog,
+               "  Writing 4-byte magic cookie "
+               "RECORD_FULL_FILE_MAGIC (0x%s)\n",
+               phex_nz (magic, 4));
   bfdcore_write (obfd.get (), osec, &magic, sizeof (magic), &bfd_offset);
 
   /* Save the entries to recfd and forward execute to the end of
@@ -2621,46 +2606,46 @@ record_full_base_target::save_record (const char *recfilename)
     {
       /* Save entry.  */
       if (record_full_list != &record_full_first)
-        {
+       {
          uint8_t type;
          uint32_t regnum, len, signal, count;
-          uint64_t addr;
+         uint64_t addr;
 
          type = record_full_list->type;
-          bfdcore_write (obfd.get (), osec, &type, sizeof (type), &bfd_offset);
+         bfdcore_write (obfd.get (), osec, &type, sizeof (type), &bfd_offset);
 
-          switch (record_full_list->type)
-            {
-            case record_full_reg: /* reg */
+         switch (record_full_list->type)
+           {
+           case record_full_reg: /* reg */
              if (record_debug)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "  Writing register %d (1 "
-                                   "plus %lu plus %d bytes)\n",
-                                   record_full_list->u.reg.num,
-                                   (unsigned long) sizeof (regnum),
-                                   record_full_list->u.reg.len);
-
-              /* Write regnum.  */
-              regnum = netorder32 (record_full_list->u.reg.num);
-              bfdcore_write (obfd.get (), osec, &regnum,
+               gdb_printf (gdb_stdlog,
+                           "  Writing register %d (1 "
+                           "plus %lu plus %d bytes)\n",
+                           record_full_list->u.reg.num,
+                           (unsigned long) sizeof (regnum),
+                           record_full_list->u.reg.len);
+
+             /* Write regnum.  */
+             regnum = netorder32 (record_full_list->u.reg.num);
+             bfdcore_write (obfd.get (), osec, &regnum,
                             sizeof (regnum), &bfd_offset);
 
-              /* Write regval.  */
-              bfdcore_write (obfd.get (), osec,
+             /* Write regval.  */
+             bfdcore_write (obfd.get (), osec,
                             record_full_get_loc (record_full_list),
                             record_full_list->u.reg.len, &bfd_offset);
-              break;
+             break;
 
-            case record_full_mem: /* mem */
+           case record_full_mem: /* mem */
              if (record_debug)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "  Writing memory %s (1 plus "
-                                   "%lu plus %lu plus %d bytes)\n",
-                                   paddress (gdbarch,
-                                             record_full_list->u.mem.addr),
-                                   (unsigned long) sizeof (addr),
-                                   (unsigned long) sizeof (len),
-                                   record_full_list->u.mem.len);
+               gdb_printf (gdb_stdlog,
+                           "  Writing memory %s (1 plus "
+                           "%lu plus %lu plus %d bytes)\n",
+                           paddress (gdbarch,
+                                     record_full_list->u.mem.addr),
+                           (unsigned long) sizeof (addr),
+                           (unsigned long) sizeof (len),
+                           record_full_list->u.mem.len);
 
              /* Write memlen.  */
              len = netorder32 (record_full_list->u.mem.len);
@@ -2676,15 +2661,15 @@ record_full_base_target::save_record (const char *recfilename)
              bfdcore_write (obfd.get (), osec,
                             record_full_get_loc (record_full_list),
                             record_full_list->u.mem.len, &bfd_offset);
-              break;
+             break;
 
-              case record_full_end:
+             case record_full_end:
                if (record_debug)
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "  Writing record_full_end (1 + "
-                                     "%lu + %lu bytes)\n", 
-                                     (unsigned long) sizeof (signal),
-                                     (unsigned long) sizeof (count));
+                 gdb_printf (gdb_stdlog,
+                             "  Writing record_full_end (1 + "
+                             "%lu + %lu bytes)\n", 
+                             (unsigned long) sizeof (signal),
+                             (unsigned long) sizeof (count));
                /* Write signal value.  */
                signal = netorder32 (record_full_list->u.end.sigval);
                bfdcore_write (obfd.get (), osec, &signal,
@@ -2694,17 +2679,17 @@ record_full_base_target::save_record (const char *recfilename)
                count = netorder32 (record_full_list->u.end.insn_num);
                bfdcore_write (obfd.get (), osec, &count,
                               sizeof (count), &bfd_offset);
-                break;
-            }
-        }
+               break;
+           }
+       }
 
       /* Execute entry.  */
       record_full_exec_insn (regcache, gdbarch, record_full_list);
 
       if (record_full_list->next)
-        record_full_list = record_full_list->next;
+       record_full_list = record_full_list->next;
       else
-        break;
+       break;
     }
 
   /* Reverse execute to cur_record_full_list.  */
@@ -2712,19 +2697,19 @@ record_full_base_target::save_record (const char *recfilename)
     {
       /* Check for beginning and end of log.  */
       if (record_full_list == cur_record_full_list)
-        break;
+       break;
 
       record_full_exec_insn (regcache, gdbarch, record_full_list);
 
       if (record_full_list->prev)
-        record_full_list = record_full_list->prev;
+       record_full_list = record_full_list->prev;
     }
 
   unlink_file.keep ();
 
   /* Succeeded.  */
-  printf_filtered (_("Saved core file %s with execution log.\n"),
-                  recfilename);
+  gdb_printf (_("Saved core file %s with execution log.\n"),
+             recfilename);
 }
 
 /* record_full_goto_insn -- rewind the record log (forward or backward,
@@ -2773,33 +2758,15 @@ set_record_full_insn_max_num (const char *args, int from_tty,
       /* Count down record_full_insn_num while releasing records from list.  */
       while (record_full_insn_num > record_full_insn_max_num)
        {
-         record_full_list_release_first ();
-         record_full_insn_num--;
+        record_full_list_release_first ();
+        record_full_insn_num--;
        }
     }
 }
 
-/* The "set record full" command.  */
-
-static void
-set_record_full_command (const char *args, int from_tty)
-{
-  printf_unfiltered (_("\"set record full\" must be followed "
-                      "by an appropriate subcommand.\n"));
-  help_list (set_record_full_cmdlist, "set record full ", all_commands,
-            gdb_stdout);
-}
-
-/* The "show record full" command.  */
-
-static void
-show_record_full_command (const char *args, int from_tty)
-{
-  cmd_show_list (show_record_full_cmdlist, from_tty, "");
-}
-
+void _initialize_record_full ();
 void
-_initialize_record_full (void)
+_initialize_record_full ()
 {
   struct cmd_list_element *c;
 
@@ -2808,90 +2775,97 @@ _initialize_record_full (void)
   record_full_first.next = NULL;
   record_full_first.type = record_full_end;
 
-  add_target (&record_full_ops);
-  add_deprecated_target_alias (&record_full_ops, "record");
-  add_target (&record_full_core_ops);
+  add_target (record_full_target_info, record_full_open);
+  add_deprecated_target_alias (record_full_target_info, "record");
+  add_target (record_full_core_target_info, record_full_open);
 
   add_prefix_cmd ("full", class_obscure, cmd_record_full_start,
                  _("Start full execution recording."), &record_full_cmdlist,
-                 "record full ", 0, &record_cmdlist);
+                 0, &record_cmdlist);
 
-  c = add_cmd ("restore", class_obscure, cmd_record_full_restore,
+  cmd_list_element *record_full_restore_cmd
+    = add_cmd ("restore", class_obscure, cmd_record_full_restore,
               _("Restore the execution log from a file.\n\
 Argument is filename.  File must be created with 'record save'."),
               &record_full_cmdlist);
-  set_cmd_completer (c, filename_completer);
+  set_cmd_completer (record_full_restore_cmd, filename_completer);
 
   /* Deprecate the old version without "full" prefix.  */
-  c = add_alias_cmd ("restore", "full restore", class_obscure, 1,
+  c = add_alias_cmd ("restore", record_full_restore_cmd, class_obscure, 1,
                     &record_cmdlist);
   set_cmd_completer (c, filename_completer);
   deprecate_cmd (c, "record full restore");
 
-  add_prefix_cmd ("full", class_support, set_record_full_command,
-                 _("Set record options"), &set_record_full_cmdlist,
-                 "set record full ", 0, &set_record_cmdlist);
-
-  add_prefix_cmd ("full", class_support, show_record_full_command,
-                 _("Show record options"), &show_record_full_cmdlist,
-                 "show record full ", 0, &show_record_cmdlist);
+  add_setshow_prefix_cmd ("full", class_support,
+                         _("Set record options."),
+                         _("Show record options."),
+                         &set_record_full_cmdlist,
+                         &show_record_full_cmdlist,
+                         &set_record_cmdlist,
+                         &show_record_cmdlist);
 
   /* Record instructions number limit command.  */
-  add_setshow_boolean_cmd ("stop-at-limit", no_class,
-                          &record_full_stop_at_limit, _("\
+  set_show_commands set_record_full_stop_at_limit_cmds
+    = add_setshow_boolean_cmd ("stop-at-limit", no_class,
+                              &record_full_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\
 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."),
-                          NULL, NULL,
-                          &set_record_full_cmdlist, &show_record_full_cmdlist);
+                              NULL, NULL,
+                              &set_record_full_cmdlist,
+                              &show_record_full_cmdlist);
 
-  c = add_alias_cmd ("stop-at-limit", "full stop-at-limit", no_class, 1,
+  c = add_alias_cmd ("stop-at-limit",
+                    set_record_full_stop_at_limit_cmds.set, no_class, 1,
                     &set_record_cmdlist);
   deprecate_cmd (c, "set record full stop-at-limit");
 
-  c = add_alias_cmd ("stop-at-limit", "full stop-at-limit", no_class, 1,
+  c = add_alias_cmd ("stop-at-limit",
+                    set_record_full_stop_at_limit_cmds.show, no_class, 1,
                     &show_record_cmdlist);
   deprecate_cmd (c, "show record full stop-at-limit");
 
-  add_setshow_uinteger_cmd ("insn-number-max", no_class,
-                           &record_full_insn_max_num,
-                           _("Set record/replay buffer limit."),
-                           _("Show record/replay buffer limit."), _("\
+  set_show_commands record_full_insn_number_max_cmds
+    = add_setshow_uinteger_cmd ("insn-number-max", no_class,
+                               &record_full_insn_max_num,
+                               _("Set record/replay buffer limit."),
+                               _("Show record/replay buffer limit."), _("\
 Set the maximum number of instructions to be stored in the\n\
 record/replay buffer.  A value of either \"unlimited\" or zero means no\n\
 limit.  Default is 200000."),
-                           set_record_full_insn_max_num,
-                           NULL, &set_record_full_cmdlist,
-                           &show_record_full_cmdlist);
+                               set_record_full_insn_max_num,
+                               NULL, &set_record_full_cmdlist,
+                               &show_record_full_cmdlist);
 
-  c = add_alias_cmd ("insn-number-max", "full insn-number-max", no_class, 1,
-                    &set_record_cmdlist);
+  c = add_alias_cmd ("insn-number-max", record_full_insn_number_max_cmds.set,
+                    no_class, 1, &set_record_cmdlist);
   deprecate_cmd (c, "set record full insn-number-max");
 
-  c = add_alias_cmd ("insn-number-max", "full insn-number-max", no_class, 1,
-                    &show_record_cmdlist);
+  c = add_alias_cmd ("insn-number-max", record_full_insn_number_max_cmds.show,
+                    no_class, 1, &show_record_cmdlist);
   deprecate_cmd (c, "show record full insn-number-max");
 
-  add_setshow_boolean_cmd ("memory-query", no_class,
-                          &record_full_memory_query, _("\
+  set_show_commands record_full_memory_query_cmds
+    = add_setshow_boolean_cmd ("memory-query", no_class,
+                              &record_full_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_full_cmdlist,
-                          &show_record_full_cmdlist);
+                              NULL, NULL,
+                              &set_record_full_cmdlist,
+                              &show_record_full_cmdlist);
 
-  c = add_alias_cmd ("memory-query", "full memory-query", no_class, 1,
-                    &set_record_cmdlist);
+  c = add_alias_cmd ("memory-query", record_full_memory_query_cmds.set,
+                    no_class, 1, &set_record_cmdlist);
   deprecate_cmd (c, "set record full memory-query");
 
-  c = add_alias_cmd ("memory-query", "full memory-query", no_class, 1,
-                    &show_record_cmdlist);
+  c = add_alias_cmd ("memory-query", record_full_memory_query_cmds.show,
+                    no_class, 1,&show_record_cmdlist);
   deprecate_cmd (c, "show record full memory-query");
 }