Multi-target support
[deliverable/binutils-gdb.git] / gdb / record-full.c
index b8460d9c5d872fce1f7b1dcc936fe7406eb66b46..f759a5185fd2a02a0d7d1235fe9d0ea303c3de9d 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-2020 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"
@@ -35,8 +36,8 @@
 #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 <signal.h>
 
@@ -52,7 +53,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 +159,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
 {
@@ -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;
@@ -217,11 +218,10 @@ static const char record_doc[]
 class record_full_base_target : public target_ops
 {
 public:
-  record_full_base_target ()
-  { to_stratum = record_stratum; }
-
   const target_info &info () const override = 0;
 
+  strata stratum () const override { return record_stratum; }
+
   void close () override;
   void async (int) override;
   ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
@@ -319,7 +319,7 @@ public:
                         struct bp_target_info *,
                         enum remove_bp_reason) override;
 
-  bool has_execution (ptid_t) override;
+  bool has_execution (inferior *inf) override;
 };
 
 static record_full_target record_full_ops;
@@ -696,12 +696,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
@@ -713,61 +707,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;
@@ -782,16 +781,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;
 }
@@ -834,8 +832,7 @@ record_full_exec_insn (struct regcache *regcache,
                               entry->u.reg.num);
 
         regcache->cooked_read (entry->u.reg.num, reg.data ());
-        regcache_cooked_write (regcache, entry->u.reg.num, 
-                              record_full_get_loc (entry));
+        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;
@@ -1015,15 +1012,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)
@@ -1040,9 +1033,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
@@ -1071,6 +1067,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;
@@ -1103,9 +1100,9 @@ record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
         }
 
       /* 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),
@@ -1120,7 +1117,7 @@ void
 record_full_target::commit_resume ()
 {
   if (!RECORD_FULL_IS_REPLAY)
-    beneath->commit_resume ();
+    beneath ()->commit_resume ();
 }
 
 static int record_full_get_sig = 0;
@@ -1141,18 +1138,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
@@ -1202,20 +1187,19 @@ 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);
+             ret = ops->beneath ()->wait (ptid, status, options);
              if (status->kind == TARGET_WAITKIND_IGNORE)
                {
                  if (record_debug)
@@ -1225,7 +1209,7 @@ record_full_wait_1 (struct target_ops *ops,
                  return ret;
                }
 
-             ALL_NON_EXITED_THREADS (tp)
+             for (thread_info *tp : all_non_exited_threads ())
                 delete_single_step_breakpoints (tp);
 
              if (record_full_resume_step)
@@ -1244,6 +1228,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 ();
@@ -1276,14 +1262,17 @@ record_full_wait_1 (struct target_ops *ops,
 
                       if (gdbarch_software_single_step_p (gdbarch))
                        {
+                         process_stratum_target *proc_target
+                           = current_inferior ()->process_target ();
+
                          /* Try to insert the software single step breakpoint.
                             If insert success, set step to 0.  */
-                         set_executing (inferior_ptid, 0);
+                         set_executing (proc_target, inferior_ptid, 0);
                          reinit_frame_cache ();
 
                          step = !insert_single_step_breakpoints (gdbarch);
 
-                         set_executing (inferior_ptid, 1);
+                         set_executing (proc_target, inferior_ptid, 1);
                        }
 
                      if (record_debug)
@@ -1291,8 +1280,8 @@ record_full_wait_1 (struct target_ops *ops,
                                            "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 ();
+                     ops->beneath ()->resume (ptid, step, GDB_SIGNAL_0);
+                     ops->beneath ()->commit_resume ();
                      continue;
                    }
                }
@@ -1306,149 +1295,169 @@ 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->kind = TARGET_WAITKIND_STOPPED;
 
-      /* 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)
+                   fprintf_unfiltered (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->kind = TARGET_WAITKIND_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->kind = TARGET_WAITKIND_NO_HISTORY;
+                 break;
+               }
+
+             record_full_exec_insn (regcache, gdbarch, record_full_list);
+
+             if (record_full_list->type == record_full_end)
+               {
+                 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)
                    {
-                     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)
+                           fprintf_unfiltered (gdb_stdlog,
+                                               "Process record: step.\n");
+                         continue_flag = 0;
+                       }
 
-                     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)
+                           fprintf_unfiltered (gdb_stdlog,
+                                               "Process record: break "
+                                               "at %s.\n",
+                                               paddress (gdbarch, tmp_pc));
 
-                 if (record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT)
-                   {
-                     if (record_debug)
-                       fprintf_unfiltered (gdb_stdlog,
-                                           "Process record: hit hw "
-                                           "watchpoint.\n");
-                     continue_flag = 0;
+                         continue_flag = 0;
+                       }
+
+                     if (record_full_stop_reason
+                         == TARGET_STOPPED_BY_WATCHPOINT)
+                       {
+                         if (record_debug)
+                           fprintf_unfiltered (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;
                    }
-                 /* Check target signal */
-                 if (record_full_list->u.end.sigval != GDB_SIGNAL_0)
-                   /* FIXME: better way to check */
-                   continue_flag = 0;
                }
-           }
 
-         if (continue_flag)
-           {
-             if (execution_direction == EXEC_REVERSE)
-               {
-                 if (record_full_list->prev)
-                   record_full_list = record_full_list->prev;
-               }
-             else
+             if (continue_flag)
                {
-                 if (record_full_list->next)
-                   record_full_list = record_full_list->next;
+                 if (execution_direction == EXEC_REVERSE)
+                   {
+                     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;
+                   }
                }
            }
+         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;
        }
-      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);
@@ -1479,7 +1488,7 @@ 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 ();
 }
 
 bool
@@ -1488,7 +1497,7 @@ record_full_base_target::stopped_data_address (CORE_ADDR *addr_p)
   if (RECORD_FULL_IS_REPLAY)
     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.  */
@@ -1609,10 +1618,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."));
            }
@@ -1623,7 +1632,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
@@ -1688,8 +1697,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
@@ -1701,6 +1710,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;
@@ -1708,15 +1726,12 @@ 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 std::vector<record_full_breakpoint> record_full_breakpoints;
 
 static void
 record_full_sync_record_breakpoints (struct bp_location *loc, void *data)
@@ -1726,14 +1741,10 @@ record_full_sync_record_breakpoints (struct bp_location *loc, void *data)
 
   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);
+      record_full_breakpoints.emplace_back
+       (loc->target_info.placed_address_space,
+        loc->target_info.placed_address,
+        1);
     }
 }
 
@@ -1742,7 +1753,7 @@ record_full_sync_record_breakpoints (struct bp_location *loc, void *data)
 static void
 record_full_init_record_breakpoints (void)
 {
-  VEC_free (record_full_breakpoint_p, record_full_breakpoints);
+  record_full_breakpoints.clear ();
 
   iterate_over_bp_locations (record_full_sync_record_breakpoints);
 }
@@ -1755,9 +1766,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)
     {
@@ -1770,34 +1779,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;
 }
 
@@ -1808,33 +1812,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;
        }
     }
@@ -2014,7 +2013,8 @@ record_full_goto_entry (struct record_full_entry *p)
 
   registers_changed ();
   reinit_frame_cache ();
-  stop_pc = regcache_read_pc (get_current_regcache ());
+  inferior_thread ()->suspend.stop_pc
+    = regcache_read_pc (get_current_regcache ());
   print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
 }
 
@@ -2204,10 +2204,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);
@@ -2224,9 +2224,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.  */
@@ -2251,7 +2251,7 @@ record_full_core_target::remove_breakpoint (struct gdbarch *gdbarch,
 /* "has_execution" method for prec over corefile.  */
 
 bool
-record_full_core_target::has_execution (ptid_t the_ptid)
+record_full_core_target::has_execution (inferior *inf)
 {
   return true;
 }
@@ -2338,7 +2338,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;
@@ -2363,9 +2362,9 @@ record_full_restore (void)
                        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));
+    fprintf_unfiltered (gdb_stdlog, "%s", bfd_section_name (osec));
 
   /* Check the magic code.  */
   bfdcore_read (core_bfd, osec, &magic, sizeof (magic), &bfd_offset);
@@ -2383,108 +2382,114 @@ record_full_restore (void)
   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;
-        }
+             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;
 
-      /* Add rec to record arch list.  */
-      record_full_arch_list_add (rec);
-    }
+           case record_full_mem: /* mem */
+             /* Get len.  */
+             bfdcore_read (core_bfd, osec, &len,
+                           sizeof (len), &bfd_offset);
+             len = netorder32 (len);
 
-  discard_cleanups (old_cleanups);
+             /* 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);
+
+             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);
+       }
+    }
+  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;
@@ -2606,10 +2611,9 @@ record_full_base_target::save_record (const char *recfilename)
     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_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 ());
@@ -2839,11 +2843,11 @@ Argument is filename.  File must be created with 'record save'."),
   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 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 options."), &show_record_full_cmdlist,
                  "show record full ", 0, &show_record_cmdlist);
 
   /* Record instructions number limit command.  */
This page took 0.040572 seconds and 4 git commands to generate.