Fix crash in "run" on macOS when gdb is not signed
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 06b45b44ed6365366e5dc1c64032de7f262ea0af..28a4391c358fdf1a5d7eeee797e693b7eb1d4b00 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-struct-independent code to start (run) and stop an inferior
    process.
 
-   Copyright (C) 1986-2017 Free Software Foundation, Inc.
+   Copyright (C) 1986-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -38,7 +38,7 @@
 #include "inf-loop.h"
 #include "regcache.h"
 #include "value.h"
-#include "observer.h"
+#include "observable.h"
 #include "language.h"
 #include "solib.h"
 #include "main.h"
 
 /* Prototypes for local functions */
 
-static void info_signals_command (char *, int);
-
-static void handle_command (char *, int);
-
 static void sig_print_info (enum gdb_signal);
 
 static void sig_print_header (void);
 
-static void resume_cleanups (void *);
-
-static int hook_stop_stub (void *);
-
-static int restore_selected_frame (void *);
-
 static int follow_fork (void);
 
 static int follow_fork_inferior (int follow_child, int detach_fork);
 
 static void follow_inferior_reset_breakpoints (void);
 
-static void set_schedlock_func (char *args, int from_tty,
-                               struct cmd_list_element *c);
-
 static int currently_stepping (struct thread_info *tp);
 
-void _initialize_infrun (void);
-
 void nullify_last_target_wait_ptid (void);
 
 static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *);
@@ -205,7 +190,7 @@ show_disable_randomization (struct ui_file *file, int from_tty,
 }
 
 static void
-set_disable_randomization (char *args, int from_tty,
+set_disable_randomization (const char *args, int from_tty,
                           struct cmd_list_element *c)
 {
   if (!target_supports_disable_randomization ())
@@ -220,7 +205,7 @@ int non_stop = 0;
 static int non_stop_1 = 0;
 
 static void
-set_non_stop (char *args, int from_tty,
+set_non_stop (const char *args, int from_tty,
              struct cmd_list_element *c)
 {
   if (target_has_execution)
@@ -249,7 +234,7 @@ int observer_mode = 0;
 static int observer_mode_1 = 0;
 
 static void
-set_observer_mode (char *args, int from_tty,
+set_observer_mode (const char *args, int from_tty,
                   struct cmd_list_element *c)
 {
   if (target_has_execution)
@@ -374,7 +359,8 @@ int stop_on_solib_events;
    as appropriate when the above flag is changed.  */
 
 static void
-set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
+set_stop_on_solib_events (const char *args,
+                         int from_tty, struct cmd_list_element *c)
 {
   update_solib_breakpoints ();
 }
@@ -397,8 +383,6 @@ static int stop_print_frame;
 static ptid_t target_last_wait_ptid;
 static struct target_waitstatus target_last_waitstatus;
 
-static void context_switch (ptid_t ptid);
-
 void init_thread_stepping_state (struct thread_info *tss);
 
 static const char follow_fork_mode_child[] = "child";
@@ -472,17 +456,17 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          if (has_vforked)
            {
              /* Keep breakpoints list in sync.  */
-             remove_breakpoints_pid (ptid_get_pid (inferior_ptid));
+             remove_breakpoints_inf (current_inferior ());
            }
 
-         if (info_verbose || debug_infrun)
+         if (print_inferior_events)
            {
              /* Ensure that we have a process ptid.  */
              ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
 
-             target_terminal_ours_for_output ();
+             target_terminal::ours_for_output ();
              fprintf_filtered (gdb_stdlog,
-                               _("Detaching after %s from child %s.\n"),
+                               _("[Detaching after %s from child %s]\n"),
                                has_vforked ? "vfork" : "fork",
                                target_pid_to_str (process_ptid));
            }
@@ -503,7 +487,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          scoped_restore_current_pspace_and_thread restore_pspace_thread;
 
          inferior_ptid = child_ptid;
-         add_thread (inferior_ptid);
+         add_thread_silent (inferior_ptid);
          set_current_inferior (child_inf);
          child_inf->symfile_flags = SYMFILE_NO_READ;
 
@@ -525,7 +509,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          else
            {
              child_inf->aspace = new_address_space ();
-             child_inf->pspace = add_program_space (child_inf->aspace);
+             child_inf->pspace = new program_space (child_inf->aspace);
              child_inf->removable = 1;
              set_current_program_space (child_inf->pspace);
              clone_program_space (child_inf->pspace, parent_inf->pspace);
@@ -563,14 +547,17 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       struct inferior *parent_inf, *child_inf;
       struct program_space *parent_pspace;
 
-      if (info_verbose || debug_infrun)
+      if (print_inferior_events)
        {
-         target_terminal_ours_for_output ();
+         std::string parent_pid = target_pid_to_str (parent_ptid);
+         std::string child_pid = target_pid_to_str (child_ptid);
+
+         target_terminal::ours_for_output ();
          fprintf_filtered (gdb_stdlog,
-                           _("Attaching after %s %s to child %s.\n"),
-                           target_pid_to_str (parent_ptid),
+                           _("[Attaching after %s %s to child %s]\n"),
+                           parent_pid.c_str (),
                            has_vforked ? "vfork" : "fork",
-                           target_pid_to_str (child_ptid));
+                           child_pid.c_str ());
        }
 
       /* Add the new inferior first, so that the target_detach below
@@ -608,19 +595,19 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
        }
       else if (detach_fork)
        {
-         if (info_verbose || debug_infrun)
+         if (print_inferior_events)
            {
              /* Ensure that we have a process ptid.  */
-             ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
+             ptid_t process_ptid = pid_to_ptid (ptid_get_pid (parent_ptid));
 
-             target_terminal_ours_for_output ();
+             target_terminal::ours_for_output ();
              fprintf_filtered (gdb_stdlog,
-                               _("Detaching after fork from "
-                                 "child %s.\n"),
+                               _("[Detaching after fork from "
+                                 "parent %s]\n"),
                                target_pid_to_str (process_ptid));
            }
 
-         target_detach (NULL, 0);
+         target_detach (parent_inf, 0);
        }
 
       /* Note that the detach above makes PARENT_INF dangling.  */
@@ -630,7 +617,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
         informing the solib layer about this new process.  */
 
       inferior_ptid = child_ptid;
-      add_thread (inferior_ptid);
+      add_thread_silent (inferior_ptid);
       set_current_inferior (child_inf);
 
       /* If this is a vfork child, then the address-space is shared
@@ -644,7 +631,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       else
        {
          child_inf->aspace = new_address_space ();
-         child_inf->pspace = add_program_space (child_inf->aspace);
+         child_inf->pspace = new program_space (child_inf->aspace);
          child_inf->removable = 1;
          child_inf->symfile_flags = SYMFILE_NO_READ;
          set_current_program_space (child_inf->pspace);
@@ -700,14 +687,16 @@ follow_fork (void)
 
       /* Check if we switched over from WAIT_PTID, since the event was
         reported.  */
-      if (!ptid_equal (wait_ptid, minus_one_ptid)
-         && !ptid_equal (inferior_ptid, wait_ptid))
+      if (wait_ptid != minus_one_ptid
+         && inferior_ptid != wait_ptid)
        {
          /* We did.  Switch back to WAIT_PTID thread, to tell the
             target to follow it (in either direction).  We'll
             afterwards refuse to resume, and inform the user what
             happened.  */
-         switch_to_thread (wait_ptid);
+         thread_info *wait_thread
+           = find_thread_ptid (wait_ptid);
+         switch_to_thread (wait_thread);
          should_resume = 0;
        }
     }
@@ -778,7 +767,8 @@ follow_fork (void)
            /* If we followed the child, switch to it...  */
            if (follow_child)
              {
-               switch_to_thread (child);
+               thread_info *child_thr = find_thread_ptid (child);
+               switch_to_thread (child_thr);
 
                /* ... and preserve the stepping state, in case the
                   user was stepping over the fork call.  */
@@ -809,8 +799,6 @@ follow_fork (void)
                /* Reset breakpoints in the child as appropriate.  */
                follow_inferior_reset_breakpoints ();
              }
-           else
-             switch_to_thread (parent);
          }
       }
       break;
@@ -876,9 +864,9 @@ proceed_after_vfork_done (struct thread_info *thread,
 {
   int pid = * (int *) arg;
 
-  if (ptid_get_pid (thread->ptid) == pid
-      && is_running (thread->ptid)
-      && !is_executing (thread->ptid)
+  if (thread->ptid.pid () == pid
+      && thread->state == THREAD_RUNNING
+      && !thread->executing
       && !thread->stop_requested
       && thread->suspend.stop_signal == GDB_SIGNAL_0)
     {
@@ -887,7 +875,7 @@ proceed_after_vfork_done (struct thread_info *thread,
                            "infrun: resuming vfork parent thread %s\n",
                            target_pid_to_str (thread->ptid));
 
-      switch_to_thread (thread->ptid);
+      switch_to_thread (thread);
       clear_proceed_status (0);
       proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
@@ -950,8 +938,8 @@ handle_vfork_child_exec_or_exit (int exec)
            maybe_restore_thread.emplace ();
 
          /* We're letting loose of the parent.  */
-         tp = any_live_thread_of_process (inf->vfork_parent->pid);
-         switch_to_thread (tp->ptid);
+         tp = any_live_thread_of_inferior (inf->vfork_parent);
+         switch_to_thread (tp);
 
          /* We're about to detach from the parent, which implicitly
             removes breakpoints from its address space.  There's a
@@ -970,27 +958,28 @@ handle_vfork_child_exec_or_exit (int exec)
          inf->aspace = NULL;
          inf->pspace = NULL;
 
-         if (debug_infrun || info_verbose)
+         if (print_inferior_events)
            {
-             target_terminal_ours_for_output ();
+             const char *pidstr
+               = target_pid_to_str (pid_to_ptid (inf->vfork_parent->pid));
+
+             target_terminal::ours_for_output ();
 
              if (exec)
                {
                  fprintf_filtered (gdb_stdlog,
-                                   _("Detaching vfork parent process "
-                                     "%d after child exec.\n"),
-                                   inf->vfork_parent->pid);
+                                   _("[Detaching vfork parent %s "
+                                     "after child exec]\n"), pidstr);
                }
              else
                {
                  fprintf_filtered (gdb_stdlog,
-                                   _("Detaching vfork parent process "
-                                     "%d after child exit.\n"),
-                                   inf->vfork_parent->pid);
+                                   _("[Detaching vfork parent %s "
+                                     "after child exit]\n"), pidstr);
                }
            }
 
-         target_detach (NULL, 0);
+         target_detach (inf->vfork_parent, 0);
 
          /* Put it back.  */
          inf->pspace = pspace;
@@ -1000,7 +989,7 @@ handle_vfork_child_exec_or_exit (int exec)
        {
          /* We're staying attached to the parent, so, really give the
             child a new address space.  */
-         inf->pspace = add_program_space (maybe_new_address_space ());
+         inf->pspace = new program_space (maybe_new_address_space ());
          inf->aspace = inf->pspace->aspace;
          inf->removable = 1;
          set_current_program_space (inf->pspace);
@@ -1034,7 +1023,7 @@ handle_vfork_child_exec_or_exit (int exec)
             program space resets breakpoints).  */
          inf->aspace = NULL;
          inf->pspace = NULL;
-         pspace = add_program_space (maybe_new_address_space ());
+         pspace = new program_space (maybe_new_address_space ());
          set_current_program_space (pspace);
          inf->removable = 1;
          inf->symfile_flags = SYMFILE_NO_READ;
@@ -1095,8 +1084,6 @@ follow_exec (ptid_t ptid, char *exec_file_target)
   struct inferior *inf = current_inferior ();
   int pid = ptid_get_pid (ptid);
   ptid_t process_ptid;
-  char *exec_file_host;
-  struct cleanup *old_chain;
 
   /* This is an exec event that we actually wish to pay attention to.
      Refresh our symbol table to the newly exec'd program, remove any
@@ -1142,7 +1129,7 @@ follow_exec (ptid_t ptid, char *exec_file_target)
      notifications.  */
   ALL_THREADS_SAFE (th, tmp)
     if (ptid_get_pid (th->ptid) == pid && !ptid_equal (th->ptid, ptid))
-      delete_thread (th->ptid);
+      delete_thread (th);
 
   /* We also need to clear any left over stale state for the
      leader/event thread.  E.g., if there was any step-resume
@@ -1175,8 +1162,8 @@ follow_exec (ptid_t ptid, char *exec_file_target)
 
   breakpoint_init_inferior (inf_execd);
 
-  exec_file_host = exec_file_find (exec_file_target, NULL);
-  old_chain = make_cleanup (xfree, exec_file_host);
+  gdb::unique_xmalloc_ptr<char> exec_file_host
+    = exec_file_find (exec_file_target, NULL);
 
   /* If we were unable to map the executable target pathname onto a host
      pathname, tell the user that.  Otherwise GDB's subsequent behavior
@@ -1211,7 +1198,6 @@ follow_exec (ptid_t ptid, char *exec_file_target)
 
       set_current_inferior (inf);
       set_current_program_space (inf->pspace);
-      add_thread (ptid);
     }
   else
     {
@@ -1231,9 +1217,7 @@ follow_exec (ptid_t ptid, char *exec_file_target)
      Executable) main symbol file will only be computed by
      solib_create_inferior_hook below.  breakpoint_re_set would fail
      to insert the breakpoints with the zero displacement.  */
-  try_open_exec_file (exec_file_host, inf, SYMFILE_DEFER_BP_RESET);
-
-  do_cleanups (old_chain);
+  try_open_exec_file (exec_file_host.get (), inf, SYMFILE_DEFER_BP_RESET);
 
   /* If the target can specify a description, read it.  Must do this
      after flipping to the new executable (because the target supplied
@@ -1243,6 +1227,11 @@ follow_exec (ptid_t ptid, char *exec_file_target)
      registers.  */
   target_find_description ();
 
+  /* The add_thread call ends up reading registers, so do it after updating the
+     target description.  */
+  if (follow_exec_mode_string == follow_exec_mode_new)
+    add_thread (ptid);
+
   solib_create_inferior_hook (0);
 
   jit_inferior_created_hook ();
@@ -1291,7 +1280,7 @@ struct step_over_info
      and address of the instruction the breakpoint is set at.  We'll
      skip inserting all breakpoints here.  Valid iff ASPACE is
      non-NULL.  */
-  struct address_space *aspace;
+  const address_space *aspace;
   CORE_ADDR address;
 
   /* The instruction being stepped over triggers a nonsteppable
@@ -1334,7 +1323,7 @@ static struct step_over_info step_over_info;
    because when we need the info later the thread may be running.  */
 
 static void
-set_step_over_info (struct address_space *aspace, CORE_ADDR address,
+set_step_over_info (const address_space *aspace, CORE_ADDR address,
                    int nonsteppable_watchpoint_p,
                    int thread)
 {
@@ -1447,8 +1436,6 @@ step_over_info_valid_p (void)
      same effect the instruction would have had if we had executed it
      at its original address.  We use this in step n3.
 
-   - gdbarch_displaced_step_free_closure provides cleanup.
-
    The gdbarch_displaced_step_copy_insn and
    gdbarch_displaced_step_fixup functions must be written so that
    copying an instruction with gdbarch_displaced_step_copy_insn,
@@ -1486,6 +1473,10 @@ step_over_info_valid_p (void)
    displaced step operation on it.  See displaced_step_prepare and
    displaced_step_fixup for details.  */
 
+/* Default destructor for displaced_step_closure.  */
+
+displaced_step_closure::~displaced_step_closure () = default;
+
 /* Per-inferior displaced stepping state.  */
 struct displaced_step_inferior_state
 {
@@ -1493,16 +1484,16 @@ struct displaced_step_inferior_state
   struct displaced_step_inferior_state *next;
 
   /* The process this displaced step state refers to.  */
-  int pid;
+  inferior *inf;
 
   /* True if preparing a displaced step ever failed.  If so, we won't
      try displaced stepping for this inferior again.  */
   int failed_before;
 
-  /* If this is not null_ptid, this is the thread carrying out a
+  /* If this is not nullptr, this is the thread carrying out a
      displaced single-step in process PID.  This thread's state will
      require fixing up once it has completed its step.  */
-  ptid_t step_ptid;
+  thread_info *step_thread;
 
   /* The architecture the thread had when we stepped it.  */
   struct gdbarch *step_gdbarch;
@@ -1526,14 +1517,14 @@ static struct displaced_step_inferior_state *displaced_step_inferior_states;
 /* Get the displaced stepping state of process PID.  */
 
 static struct displaced_step_inferior_state *
-get_displaced_stepping_state (int pid)
+get_displaced_stepping_state (inferior *inf)
 {
   struct displaced_step_inferior_state *state;
 
   for (state = displaced_step_inferior_states;
        state != NULL;
        state = state->next)
-    if (state->pid == pid)
+    if (state->inf == inf)
       return state;
 
   return NULL;
@@ -1550,7 +1541,7 @@ displaced_step_in_progress_any_inferior (void)
   for (state = displaced_step_inferior_states;
        state != NULL;
        state = state->next)
-    if (!ptid_equal (state->step_ptid, null_ptid))
+    if (state->step_thread != nullptr)
       return 1;
 
   return 0;
@@ -1560,26 +1551,26 @@ displaced_step_in_progress_any_inferior (void)
    step.  */
 
 static int
-displaced_step_in_progress_thread (ptid_t ptid)
+displaced_step_in_progress_thread (thread_info *thread)
 {
   struct displaced_step_inferior_state *displaced;
 
-  gdb_assert (!ptid_equal (ptid, null_ptid));
+  gdb_assert (thread != NULL);
 
-  displaced = get_displaced_stepping_state (ptid_get_pid (ptid));
+  displaced = get_displaced_stepping_state (thread->inf);
 
-  return (displaced != NULL && ptid_equal (displaced->step_ptid, ptid));
+  return (displaced != NULL && displaced->step_thread == thread);
 }
 
 /* Return true if process PID has a thread doing a displaced step.  */
 
 static int
-displaced_step_in_progress (int pid)
+displaced_step_in_progress (inferior *inf)
 {
   struct displaced_step_inferior_state *displaced;
 
-  displaced = get_displaced_stepping_state (pid);
-  if (displaced != NULL && !ptid_equal (displaced->step_ptid, null_ptid))
+  displaced = get_displaced_stepping_state (inf);
+  if (displaced != NULL && displaced->step_thread != nullptr)
     return 1;
 
   return 0;
@@ -1590,18 +1581,18 @@ displaced_step_in_progress (int pid)
    entry, if it already exists.  Never returns NULL.  */
 
 static struct displaced_step_inferior_state *
-add_displaced_stepping_state (int pid)
+add_displaced_stepping_state (inferior *inf)
 {
   struct displaced_step_inferior_state *state;
 
   for (state = displaced_step_inferior_states;
        state != NULL;
        state = state->next)
-    if (state->pid == pid)
+    if (state->inf == inf)
       return state;
 
   state = XCNEW (struct displaced_step_inferior_state);
-  state->pid = pid;
+  state->inf = inf;
   state->next = displaced_step_inferior_states;
   displaced_step_inferior_states = state;
 
@@ -1616,11 +1607,12 @@ struct displaced_step_closure*
 get_displaced_step_closure_by_addr (CORE_ADDR addr)
 {
   struct displaced_step_inferior_state *displaced
-    = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
+    = get_displaced_stepping_state (current_inferior ());
 
   /* If checking the mode of displaced instruction in copy area.  */
-  if (displaced && !ptid_equal (displaced->step_ptid, null_ptid)
-     && (displaced->step_copy == addr))
+  if (displaced != NULL
+      && displaced->step_thread != nullptr
+      && displaced->step_copy == addr)
     return displaced->step_closure;
 
   return NULL;
@@ -1629,17 +1621,17 @@ get_displaced_step_closure_by_addr (CORE_ADDR addr)
 /* Remove the displaced stepping state of process PID.  */
 
 static void
-remove_displaced_stepping_state (int pid)
+remove_displaced_stepping_state (inferior *inf)
 {
   struct displaced_step_inferior_state *it, **prev_next_p;
 
-  gdb_assert (pid != 0);
+  gdb_assert (inf != nullptr);
 
   it = displaced_step_inferior_states;
   prev_next_p = &displaced_step_inferior_states;
   while (it)
     {
-      if (it->pid == pid)
+      if (it->inf == inf)
        {
          *prev_next_p = it->next;
          xfree (it);
@@ -1654,7 +1646,7 @@ remove_displaced_stepping_state (int pid)
 static void
 infrun_inferior_exit (struct inferior *inf)
 {
-  remove_displaced_stepping_state (inf->pid);
+  remove_displaced_stepping_state (inf);
 }
 
 /* If ON, and the architecture supports it, GDB will use displaced
@@ -1689,11 +1681,11 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
 static int
 use_displaced_stepping (struct thread_info *tp)
 {
-  struct regcache *regcache = get_thread_regcache (tp->ptid);
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct regcache *regcache = get_thread_regcache (tp);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct displaced_step_inferior_state *displaced_state;
 
-  displaced_state = get_displaced_stepping_state (ptid_get_pid (tp->ptid));
+  displaced_state = get_displaced_stepping_state (tp->inf);
 
   return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO
            && target_is_non_stop_p ())
@@ -1709,9 +1701,9 @@ static void
 displaced_step_clear (struct displaced_step_inferior_state *displaced)
 {
   /* Indicate that there is no cleanup pending.  */
-  displaced->step_ptid = null_ptid;
+  displaced->step_thread = nullptr;
 
-  xfree (displaced->step_closure);
+  delete displaced->step_closure;
   displaced->step_closure = NULL;
 }
 
@@ -1754,13 +1746,12 @@ displaced_step_dump_bytes (struct ui_file *file,
    if this instruction can't be displaced stepped.  */
 
 static int
-displaced_step_prepare_throw (ptid_t ptid)
+displaced_step_prepare_throw (thread_info *tp)
 {
   struct cleanup *ignore_cleanups;
-  struct thread_info *tp = find_thread_ptid (ptid);
-  struct regcache *regcache = get_thread_regcache (ptid);
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  struct address_space *aspace = get_regcache_aspace (regcache);
+  regcache *regcache = get_thread_regcache (tp);
+  struct gdbarch *gdbarch = regcache->arch ();
+  const address_space *aspace = regcache->aspace ();
   CORE_ADDR original, copy;
   ULONGEST len;
   struct displaced_step_closure *closure;
@@ -1783,9 +1774,9 @@ displaced_step_prepare_throw (ptid_t ptid)
   /* We have to displaced step one thread at a time, as we only have
      access to a single scratch space per inferior.  */
 
-  displaced = add_displaced_stepping_state (ptid_get_pid (ptid));
+  displaced = add_displaced_stepping_state (tp->inf);
 
-  if (!ptid_equal (displaced->step_ptid, null_ptid))
+  if (displaced->step_thread != nullptr)
     {
       /* Already waiting for a displaced step to finish.  Defer this
         request and place in queue.  */
@@ -1793,7 +1784,7 @@ displaced_step_prepare_throw (ptid_t ptid)
       if (debug_displaced)
        fprintf_unfiltered (gdb_stdlog,
                            "displaced: deferring step of %s\n",
-                           target_pid_to_str (ptid));
+                           target_pid_to_str (tp->ptid));
 
       thread_step_over_chain_enqueue (tp);
       return 0;
@@ -1803,13 +1794,14 @@ displaced_step_prepare_throw (ptid_t ptid)
       if (debug_displaced)
        fprintf_unfiltered (gdb_stdlog,
                            "displaced: stepping %s now\n",
-                           target_pid_to_str (ptid));
+                           target_pid_to_str (tp->ptid));
     }
 
   displaced_step_clear (displaced);
 
-  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
-  inferior_ptid = ptid;
+  scoped_restore_current_thread restore_thread;
+
+  switch_to_thread (tp);
 
   original = regcache_read_pc (regcache);
 
@@ -1869,7 +1861,7 @@ displaced_step_prepare_throw (ptid_t ptid)
 
   /* Save the information we need to fix things up if the step
      succeeds.  */
-  displaced->step_ptid = ptid;
+  displaced->step_thread = tp;
   displaced->step_gdbarch = gdbarch;
   displaced->step_closure = closure;
   displaced->step_original = original;
@@ -1893,13 +1885,13 @@ displaced_step_prepare_throw (ptid_t ptid)
    attempts at displaced stepping if we get a memory error.  */
 
 static int
-displaced_step_prepare (ptid_t ptid)
+displaced_step_prepare (thread_info *thread)
 {
   int prepared = -1;
 
   TRY
     {
-      prepared = displaced_step_prepare_throw (ptid);
+      prepared = displaced_step_prepare_throw (thread);
     }
   CATCH (ex, RETURN_MASK_ERROR)
     {
@@ -1926,7 +1918,7 @@ displaced_step_prepare (ptid_t ptid)
 
       /* Disable further displaced stepping attempts.  */
       displaced_state
-       = get_displaced_stepping_state (ptid_get_pid (ptid));
+       = get_displaced_stepping_state (thread->inf);
       displaced_state->failed_before = 1;
     }
   END_CATCH
@@ -1968,30 +1960,29 @@ displaced_step_restore (struct displaced_step_inferior_state *displaced,
    -1.  If the thread wasn't displaced stepping, return 0.  */
 
 static int
-displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
+displaced_step_fixup (thread_info *event_thread, enum gdb_signal signal)
 {
   struct cleanup *old_cleanups;
   struct displaced_step_inferior_state *displaced
-    = get_displaced_stepping_state (ptid_get_pid (event_ptid));
+    = get_displaced_stepping_state (event_thread->inf);
   int ret;
 
   /* Was any thread of this process doing a displaced step?  */
   if (displaced == NULL)
     return 0;
 
-  /* Was this event for the pid we displaced?  */
-  if (ptid_equal (displaced->step_ptid, null_ptid)
-      || ! ptid_equal (displaced->step_ptid, event_ptid))
+  /* Was this event for the thread we displaced?  */
+  if (displaced->step_thread != event_thread)
     return 0;
 
   old_cleanups = make_cleanup (displaced_step_clear_cleanup, displaced);
 
-  displaced_step_restore (displaced, displaced->step_ptid);
+  displaced_step_restore (displaced, displaced->step_thread->ptid);
 
   /* Fixup may need to read memory/registers.  Switch to the thread
      that we're fixing up.  Also, target_stopped_by_watchpoint checks
      the current thread.  */
-  switch_to_thread (event_ptid);
+  switch_to_thread (event_thread);
 
   /* Did the instruction complete successfully?  */
   if (signal == GDB_SIGNAL_TRAP
@@ -2004,14 +1995,14 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
                                     displaced->step_closure,
                                     displaced->step_original,
                                     displaced->step_copy,
-                                    get_thread_regcache (displaced->step_ptid));
+                                    get_thread_regcache (displaced->step_thread));
       ret = 1;
     }
   else
     {
       /* Since the instruction didn't complete, all we can do is
          relocate the PC.  */
-      struct regcache *regcache = get_thread_regcache (event_ptid);
+      struct regcache *regcache = get_thread_regcache (event_thread);
       CORE_ADDR pc = regcache_read_pc (regcache);
 
       pc = displaced->step_original + (pc - displaced->step_copy);
@@ -2021,7 +2012,7 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 
   do_cleanups (old_cleanups);
 
-  displaced->step_ptid = null_ptid;
+  displaced->step_thread = nullptr;
 
   return ret;
 }
@@ -2090,7 +2081,7 @@ start_step_over (void)
 
       /* If this inferior already has a displaced step in process,
         don't start a new one.  */
-      if (displaced_step_in_progress (ptid_get_pid (tp->ptid)))
+      if (displaced_step_in_progress (tp->inf))
        continue;
 
       step_what = thread_still_needs_step_over (tp);
@@ -2140,7 +2131,7 @@ start_step_over (void)
       if (!target_is_non_stop_p () && !step_what)
        continue;
 
-      switch_to_thread (tp->ptid);
+      switch_to_thread (tp);
       reset_ecs (ecs, tp);
       keep_going_pass_signal (ecs);
 
@@ -2187,28 +2178,9 @@ infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
 
   if (ptid_equal (inferior_ptid, old_ptid))
     inferior_ptid = new_ptid;
-
-  for (displaced = displaced_step_inferior_states;
-       displaced;
-       displaced = displaced->next)
-    {
-      if (ptid_equal (displaced->step_ptid, old_ptid))
-       displaced->step_ptid = new_ptid;
-    }
 }
 
 \f
-/* Resuming.  */
-
-/* Things to clean up if we QUIT out of resume ().  */
-static void
-resume_cleanups (void *ignore)
-{
-  if (!ptid_equal (inferior_ptid, null_ptid))
-    delete_single_step_breakpoints (inferior_thread ());
-
-  normal_stop ();
-}
 
 static const char schedlock_off[] = "off";
 static const char schedlock_on[] = "on";
@@ -2233,7 +2205,7 @@ show_scheduler_mode (struct ui_file *file, int from_tty,
 }
 
 static void
-set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
+set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c)
 {
   if (!target_can_lock_scheduler)
     {
@@ -2337,7 +2309,7 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
   gdb_assert (!tp->stop_requested);
 
   /* Install inferior's terminal modes.  */
-  target_terminal_inferior ();
+  target_terminal::inferior ();
 
   /* Avoid confusing the next resume, if the next stop/resume
      happens to apply to another thread.  */
@@ -2363,7 +2335,7 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
        return to the scratch pad area, which would no longer be
        valid.  */
   if (step_over_info_valid_p ()
-      || displaced_step_in_progress (ptid_get_pid (tp->ptid)))
+      || displaced_step_in_progress (tp->inf))
     target_pass_signals (0, NULL);
   else
     target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
@@ -2373,22 +2345,18 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
   target_commit_resume ();
 }
 
-/* Resume the inferior, but allow a QUIT.  This is useful if the user
-   wants to interrupt some lengthy single-stepping operation
-   (for child processes, the SIGINT goes to the inferior, and so
-   we get a SIGINT random_signal, but for remote debugging and perhaps
-   other targets, that's not true).
+/* Resume the inferior.  SIG is the signal to give the inferior
+   (GDB_SIGNAL_0 for none).  Note: don't call this directly; instead
+   call 'resume', which handles exceptions.  */
 
-   SIG is the signal to give the inferior (zero for none).  */
-void
-resume (enum gdb_signal sig)
+static void
+resume_1 (enum gdb_signal sig)
 {
-  struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
   struct regcache *regcache = get_current_regcache ();
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct thread_info *tp = inferior_thread ();
   CORE_ADDR pc = regcache_read_pc (regcache);
-  struct address_space *aspace = get_regcache_aspace (regcache);
+  const address_space *aspace = regcache->aspace ();
   ptid_t resume_ptid;
   /* This represents the user's step vs continue request.  When
      deciding whether "set scheduler-locking step" applies, it's the
@@ -2403,8 +2371,6 @@ resume (enum gdb_signal sig)
   gdb_assert (!tp->stop_requested);
   gdb_assert (!thread_is_in_step_over_chain (tp));
 
-  QUIT;
-
   if (tp->suspend.waitstatus_pending_p)
     {
       if (debug_infrun)
@@ -2431,10 +2397,13 @@ resume (enum gdb_signal sig)
        }
 
       tp->suspend.stop_signal = GDB_SIGNAL_0;
-      discard_cleanups (old_cleanups);
 
       if (target_can_async_p ())
-       target_async (1);
+       {
+         target_async (1);
+         /* Tell the event loop we have an event to process. */
+         mark_async_event_handler (infrun_async_inferior_event_token);
+       }
       return;
     }
 
@@ -2543,7 +2512,6 @@ resume (enum gdb_signal sig)
 
              resume_ptid = internal_resume_ptid (user_step);
              do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
-             discard_cleanups (old_cleanups);
              tp->resumed = 1;
              return;
            }
@@ -2572,7 +2540,7 @@ resume (enum gdb_signal sig)
       && sig == GDB_SIGNAL_0
       && !current_inferior ()->waiting_for_vfork_done)
     {
-      int prepared = displaced_step_prepare (inferior_ptid);
+      int prepared = displaced_step_prepare (tp);
 
       if (prepared == 0)
        {
@@ -2581,7 +2549,6 @@ resume (enum gdb_signal sig)
                                "Got placed in step-over queue\n");
 
          tp->control.trap_expected = 0;
-         discard_cleanups (old_cleanups);
          return;
        }
       else if (prepared < 0)
@@ -2591,7 +2558,7 @@ resume (enum gdb_signal sig)
          if (target_is_non_stop_p ())
            stop_all_threads ();
 
-         set_step_over_info (get_regcache_aspace (regcache),
+         set_step_over_info (regcache->aspace (),
                              regcache_read_pc (regcache), 0, tp->global_num);
 
          step = maybe_software_singlestep (gdbarch, pc);
@@ -2604,9 +2571,9 @@ resume (enum gdb_signal sig)
 
          /* Update pc to reflect the new address from which we will
             execute instructions due to displaced stepping.  */
-         pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
+         pc = regcache_read_pc (get_thread_regcache (tp));
 
-         displaced = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
+         displaced = get_displaced_stepping_state (tp->inf);
          step = gdbarch_displaced_step_hw_singlestep (gdbarch,
                                                       displaced->step_closure);
        }
@@ -2735,8 +2702,8 @@ resume (enum gdb_signal sig)
       && use_displaced_stepping (tp)
       && !step_over_info_valid_p ())
     {
-      struct regcache *resume_regcache = get_thread_regcache (tp->ptid);
-      struct gdbarch *resume_gdbarch = get_regcache_arch (resume_regcache);
+      struct regcache *resume_regcache = get_thread_regcache (tp);
+      struct gdbarch *resume_gdbarch = resume_regcache->arch ();
       CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
       gdb_byte buf[4];
 
@@ -2758,8 +2725,33 @@ resume (enum gdb_signal sig)
 
   do_target_resume (resume_ptid, step, sig);
   tp->resumed = 1;
-  discard_cleanups (old_cleanups);
 }
+
+/* Resume the inferior.  SIG is the signal to give the inferior
+   (GDB_SIGNAL_0 for none).  This is a wrapper around 'resume_1' that
+   rolls back state on error.  */
+
+void
+resume (gdb_signal sig)
+{
+  TRY
+    {
+      resume_1 (sig);
+    }
+  CATCH (ex, RETURN_MASK_ALL)
+    {
+      /* If resuming is being aborted for any reason, delete any
+        single-step breakpoint resume_1 may have created, to avoid
+        confusing the following resumption, and to avoid leaving
+        single-step breakpoints perturbing other threads, in case
+        we're running in non-stop mode.  */
+      if (inferior_ptid != null_ptid)
+       delete_single_step_breakpoints (inferior_thread ());
+      throw_exception (ex);
+    }
+  END_CATCH
+}
+
 \f
 /* Proceeding.  */
 
@@ -2906,7 +2898,7 @@ clear_proceed_status (int step)
       inferior->control.stop_soon = NO_STOP_QUIETLY;
     }
 
-  observer_notify_about_to_proceed ();
+  gdb::observers::about_to_proceed.notify ();
 }
 
 /* Returns true if TP is still stopped at a breakpoint that needs
@@ -2918,9 +2910,9 @@ thread_still_needs_step_over_bp (struct thread_info *tp)
 {
   if (tp->stepping_over_breakpoint)
     {
-      struct regcache *regcache = get_thread_regcache (tp->ptid);
+      struct regcache *regcache = get_thread_regcache (tp);
 
-      if (breakpoint_here_p (get_regcache_aspace (regcache),
+      if (breakpoint_here_p (regcache->aspace (),
                             regcache_read_pc (regcache))
          == ordinary_breakpoint_here)
        return 1;
@@ -2983,12 +2975,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   struct gdbarch *gdbarch;
   struct thread_info *tp;
   CORE_ADDR pc;
-  struct address_space *aspace;
   ptid_t resume_ptid;
   struct execution_control_state ecss;
   struct execution_control_state *ecs = &ecss;
-  struct cleanup *old_chain;
-  struct cleanup *defer_resume_cleanup;
   int started;
 
   /* If we're stopped at a fork/vfork, follow the branch set by the
@@ -3007,8 +2996,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   previous_inferior_ptid = inferior_ptid;
 
   regcache = get_current_regcache ();
-  gdbarch = get_regcache_arch (regcache);
-  aspace = get_regcache_aspace (regcache);
+  gdbarch = regcache->arch ();
+  const address_space *aspace = regcache->aspace ();
+
   pc = regcache_read_pc (regcache);
   tp = inferior_thread ();
 
@@ -3019,7 +3009,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 
   if (addr == (CORE_ADDR) -1)
     {
-      if (pc == stop_pc
+      if (pc == tp->suspend.stop_pc
          && breakpoint_here_p (aspace, pc) == ordinary_breakpoint_here
          && execution_direction != EXEC_REVERSE)
        /* There is a breakpoint at the address we will resume at,
@@ -3051,7 +3041,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   /* If an exception is thrown from this point on, make sure to
      propagate GDB's knowledge of the executing state to the
      frontend/user running state.  */
-  old_chain = make_cleanup (finish_thread_state_cleanup, &resume_ptid);
+  scoped_finish_thread_state finish_state (resume_ptid);
 
   /* Even if RESUME_PTID is a wildcard, and we end up resuming fewer
      threads (e.g., we might need to set threads stepping over
@@ -3074,6 +3064,12 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
      inferior.  */
   gdb_flush (gdb_stdout);
 
+  /* Since we've marked the inferior running, give it the terminal.  A
+     QUIT/Ctrl-C from here on is forwarded to the target (which can
+     still detect attempts to unblock a stuck connection with repeated
+     Ctrl-C from within target_pass_ctrlc).  */
+  target_terminal::inferior ();
+
   /* In a multi-threaded task we may select another thread and
      then continue or step.
 
@@ -3130,26 +3126,27 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
      until the target stops again.  */
   tp->prev_pc = regcache_read_pc (regcache);
 
-  defer_resume_cleanup = make_cleanup_defer_target_commit_resume ();
+  {
+    scoped_restore save_defer_tc = make_scoped_defer_target_commit_resume ();
 
-  started = start_step_over ();
+    started = start_step_over ();
 
-  if (step_over_info_valid_p ())
-    {
-      /* Either this thread started a new in-line step over, or some
-        other thread was already doing one.  In either case, don't
-        resume anything else until the step-over is finished.  */
-    }
-  else if (started && !target_is_non_stop_p ())
-    {
-      /* A new displaced stepping sequence was started.  In all-stop,
-        we can't talk to the target anymore until it next stops.  */
-    }
-  else if (!non_stop && target_is_non_stop_p ())
-    {
-      /* In all-stop, but the target is always in non-stop mode.
-        Start all other threads that are implicitly resumed too.  */
-      ALL_NON_EXITED_THREADS (tp)
+    if (step_over_info_valid_p ())
+      {
+       /* Either this thread started a new in-line step over, or some
+          other thread was already doing one.  In either case, don't
+          resume anything else until the step-over is finished.  */
+      }
+    else if (started && !target_is_non_stop_p ())
+      {
+       /* A new displaced stepping sequence was started.  In all-stop,
+          we can't talk to the target anymore until it next stops.  */
+      }
+    else if (!non_stop && target_is_non_stop_p ())
+      {
+       /* In all-stop, but the target is always in non-stop mode.
+          Start all other threads that are implicitly resumed too.  */
+       ALL_NON_EXITED_THREADS (tp)
         {
          /* Ignore threads of processes we're not resuming.  */
          if (!ptid_match (tp->ptid, resume_ptid))
@@ -3180,26 +3177,26 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
                                target_pid_to_str (tp->ptid));
 
          reset_ecs (ecs, tp);
-         switch_to_thread (tp->ptid);
+         switch_to_thread (tp);
          keep_going_pass_signal (ecs);
          if (!ecs->wait_some_more)
            error (_("Command aborted."));
        }
-    }
-  else if (!tp->resumed && !thread_is_in_step_over_chain (tp))
-    {
-      /* The thread wasn't started, and isn't queued, run it now.  */
-      reset_ecs (ecs, tp);
-      switch_to_thread (tp->ptid);
-      keep_going_pass_signal (ecs);
-      if (!ecs->wait_some_more)
-       error (_("Command aborted."));
-    }
+      }
+    else if (!tp->resumed && !thread_is_in_step_over_chain (tp))
+      {
+       /* The thread wasn't started, and isn't queued, run it now.  */
+       reset_ecs (ecs, tp);
+       switch_to_thread (tp);
+       keep_going_pass_signal (ecs);
+       if (!ecs->wait_some_more)
+         error (_("Command aborted."));
+      }
+  }
 
-  do_cleanups (defer_resume_cleanup);
   target_commit_resume ();
 
-  discard_cleanups (old_chain);
+  finish_state.release ();
 
   /* Tell the event loop to wait for it to stop.  If the target
      supports asynchronous execution, it'll do this from within
@@ -3238,7 +3235,7 @@ start_remote (int from_tty)
   /* Now that the inferior has stopped, do any bookkeeping like
      loading shared libraries.  We want to do this before normal_stop,
      so that the displayed frame is up to date.  */
-  post_create_inferior (&current_target, from_tty);
+  post_create_inferior (current_top_target (), from_tty);
 
   normal_stop ();
 }
@@ -3518,8 +3515,8 @@ do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
       && (tp->suspend.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
          || tp->suspend.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT))
     {
-      struct regcache *regcache = get_thread_regcache (tp->ptid);
-      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      struct regcache *regcache = get_thread_regcache (tp);
+      struct gdbarch *gdbarch = regcache->arch ();
       CORE_ADDR pc;
       int discard = 0;
 
@@ -3531,11 +3528,11 @@ do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
            fprintf_unfiltered (gdb_stdlog,
                                "infrun: PC of %s changed.  was=%s, now=%s\n",
                                target_pid_to_str (tp->ptid),
-                               paddress (gdbarch, tp->prev_pc),
+                               paddress (gdbarch, tp->suspend.stop_pc),
                                paddress (gdbarch, pc));
          discard = 1;
        }
-      else if (!breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+      else if (!breakpoint_inserted_here_p (regcache->aspace (), pc))
        {
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog,
@@ -3581,8 +3578,8 @@ do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
          struct gdbarch *gdbarch;
          int decr_pc;
 
-         regcache = get_thread_regcache (tp->ptid);
-         gdbarch = get_regcache_arch (regcache);
+         regcache = get_thread_regcache (tp);
+         gdbarch = regcache->arch ();
 
          decr_pc = gdbarch_decr_pc_after_break (gdbarch);
          if (decr_pc != 0)
@@ -3625,13 +3622,12 @@ prepare_for_detach (void)
 {
   struct inferior *inf = current_inferior ();
   ptid_t pid_ptid = pid_to_ptid (inf->pid);
-  struct displaced_step_inferior_state *displaced;
 
-  displaced = get_displaced_stepping_state (inf->pid);
+  displaced_step_inferior_state *displaced = get_displaced_stepping_state (inf);
 
   /* Is any thread of this process displaced stepping?  If not,
      there's nothing else to do.  */
-  if (displaced == NULL || ptid_equal (displaced->step_ptid, null_ptid))
+  if (displaced == NULL || displaced->step_thread == nullptr)
     return;
 
   if (debug_infrun)
@@ -3640,9 +3636,8 @@ prepare_for_detach (void)
 
   scoped_restore restore_detaching = make_scoped_restore (&inf->detaching, true);
 
-  while (!ptid_equal (displaced->step_ptid, null_ptid))
+  while (displaced->step_thread != nullptr)
     {
-      struct cleanup *old_chain_2;
       struct execution_control_state ecss;
       struct execution_control_state *ecs;
 
@@ -3664,14 +3659,13 @@ prepare_for_detach (void)
       /* If an error happens while handling the event, propagate GDB's
         knowledge of the executing state to the frontend/user running
         state.  */
-      old_chain_2 = make_cleanup (finish_thread_state_cleanup,
-                                 &minus_one_ptid);
+      scoped_finish_thread_state finish_state (minus_one_ptid);
 
       /* Now figure out what to do with the result of the result.  */
       handle_inferior_event (ecs);
 
       /* No error, don't finish the state yet.  */
-      discard_cleanups (old_chain_2);
+      finish_state.release ();
 
       /* Breakpoints and watchpoints are not installed on the target
         at this point, and signals are passed directly to the
@@ -3697,7 +3691,6 @@ void
 wait_for_inferior (void)
 {
   struct cleanup *old_cleanups;
-  struct cleanup *thread_state_chain;
 
   if (debug_infrun)
     fprintf_unfiltered
@@ -3710,7 +3703,7 @@ wait_for_inferior (void)
   /* If an error happens while handling the event, propagate GDB's
      knowledge of the executing state to the frontend/user running
      state.  */
-  thread_state_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+  scoped_finish_thread_state finish_state (minus_one_ptid);
 
   while (1)
     {
@@ -3741,7 +3734,7 @@ wait_for_inferior (void)
     }
 
   /* No error, don't finish the state yet.  */
-  discard_cleanups (thread_state_chain);
+  finish_state.release ();
 
   do_cleanups (old_cleanups);
 }
@@ -3795,12 +3788,12 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
          if (thr == ecs->event_thread)
            continue;
 
-         switch_to_thread (thr->ptid);
+         switch_to_thread (thr);
          thread_fsm_clean_up (thr->thread_fsm, thr);
        }
 
       if (ecs->event_thread != NULL)
-       switch_to_thread (ecs->event_thread->ptid);
+       switch_to_thread (ecs->event_thread);
     }
 }
 
@@ -3816,8 +3809,8 @@ check_curr_ui_sync_execution_done (void)
       && ui->async
       && !gdb_in_secondary_prompt_p (ui))
     {
-      target_terminal_ours ();
-      observer_notify_sync_execution_done ();
+      target_terminal::ours ();
+      gdb::observers::sync_execution_done.notify ();
       ui_register_input_event_handler (ui);
     }
 }
@@ -3860,7 +3853,6 @@ fetch_inferior_event (void *client_data)
   struct execution_control_state ecss;
   struct execution_control_state *ecs = &ecss;
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-  struct cleanup *ts_old_chain;
   int cmd_done = 0;
   ptid_t waiton_ptid = minus_one_ptid;
 
@@ -3878,9 +3870,10 @@ fetch_inferior_event (void *client_data)
      debugging.  If we're looking at traceframes while the target is
      running, we're going to need to get back to that mode after
      handling the event.  */
+  gdb::optional<scoped_restore_current_traceframe> maybe_restore_traceframe;
   if (non_stop)
     {
-      make_cleanup_restore_current_traceframe ();
+      maybe_restore_traceframe.emplace ();
       set_current_traceframe (-1);
     }
 
@@ -3912,14 +3905,12 @@ fetch_inferior_event (void *client_data)
   /* If an error happens while handling the event, propagate GDB's
      knowledge of the executing state to the frontend/user running
      state.  */
-  if (!target_is_non_stop_p ())
-    ts_old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
-  else
-    ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
+  ptid_t finish_ptid = !target_is_non_stop_p () ? minus_one_ptid : ecs->ptid;
+  scoped_finish_thread_state finish_state (finish_ptid);
 
   /* Get executed before make_cleanup_restore_current_thread above to apply
      still for the thread which has thrown the exception.  */
-  make_bpstat_clear_actions_cleanup ();
+  struct cleanup *ts_old_chain = make_bpstat_clear_actions_cleanup ();
 
   make_cleanup (delete_just_stopped_threads_infrun_breakpoints_cleanup, NULL);
 
@@ -3931,7 +3922,6 @@ fetch_inferior_event (void *client_data)
       struct inferior *inf = find_inferior_ptid (ecs->ptid);
       int should_stop = 1;
       struct thread_info *thr = ecs->event_thread;
-      int should_notify_stop = 1;
 
       delete_just_stopped_threads_infrun_breakpoints ();
 
@@ -3949,6 +3939,9 @@ fetch_inferior_event (void *client_data)
        }
       else
        {
+         int should_notify_stop = 1;
+         int proceeded = 0;
+
          clean_up_just_stopped_threads_fsms (ecs);
 
          if (thr != NULL && thr->thread_fsm != NULL)
@@ -3959,24 +3952,24 @@ fetch_inferior_event (void *client_data)
 
          if (should_notify_stop)
            {
-             int proceeded = 0;
-
              /* We may not find an inferior if this was a process exit.  */
              if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
                proceeded = normal_stop ();
+           }
 
-             if (!proceeded)
-               {
-                 inferior_event_handler (INF_EXEC_COMPLETE, NULL);
-                 cmd_done = 1;
-               }
+         if (!proceeded)
+           {
+             inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+             cmd_done = 1;
            }
        }
     }
 
-  /* No error, don't finish the thread states yet.  */
   discard_cleanups (ts_old_chain);
 
+  /* No error, don't finish the thread states yet.  */
+  finish_state.release ();
+
   /* Revert thread and frame.  */
   do_cleanups (old_chain);
 
@@ -3987,8 +3980,8 @@ fetch_inferior_event (void *client_data)
 
   if (cmd_done
       && exec_done_display_p
-      && (ptid_equal (inferior_ptid, null_ptid)
-         || !is_running (inferior_ptid)))
+      && (inferior_ptid == null_ptid
+         || inferior_thread ()->state != THREAD_RUNNING))
     printf_unfiltered (_("completed.\n"));
 }
 
@@ -4046,17 +4039,19 @@ nullify_last_target_wait_ptid (void)
 /* Switch thread contexts.  */
 
 static void
-context_switch (ptid_t ptid)
+context_switch (execution_control_state *ecs)
 {
-  if (debug_infrun && !ptid_equal (ptid, inferior_ptid))
+  if (debug_infrun
+      && ecs->ptid != inferior_ptid
+      && ecs->event_thread != inferior_thread ())
     {
       fprintf_unfiltered (gdb_stdlog, "infrun: Switching context from %s ",
                          target_pid_to_str (inferior_ptid));
       fprintf_unfiltered (gdb_stdlog, "to %s\n",
-                         target_pid_to_str (ptid));
+                         target_pid_to_str (ecs->ptid));
     }
 
-  switch_to_thread (ptid);
+  switch_to_thread (ecs->event_thread);
 }
 
 /* If the target can't tell whether we've hit breakpoints
@@ -4070,7 +4065,6 @@ adjust_pc_after_break (struct thread_info *thread,
 {
   struct regcache *regcache;
   struct gdbarch *gdbarch;
-  struct address_space *aspace;
   CORE_ADDR breakpoint_pc, decr_pc;
 
   /* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP.  If
@@ -4143,14 +4137,14 @@ adjust_pc_after_break (struct thread_info *thread,
 
   /* If this target does not decrement the PC after breakpoints, then
      we have nothing to do.  */
-  regcache = get_thread_regcache (thread->ptid);
-  gdbarch = get_regcache_arch (regcache);
+  regcache = get_thread_regcache (thread);
+  gdbarch = regcache->arch ();
 
   decr_pc = gdbarch_decr_pc_after_break (gdbarch);
   if (decr_pc == 0)
     return;
 
-  aspace = get_regcache_aspace (regcache);
+  const address_space *aspace = regcache->aspace ();
 
   /* Find the location where (if we've hit a breakpoint) the
      breakpoint would be.  */
@@ -4176,10 +4170,11 @@ adjust_pc_after_break (struct thread_info *thread,
       || (target_is_non_stop_p ()
          && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
-      struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
+      gdb::optional<scoped_restore_tmpl<int>> restore_operation_disable;
 
       if (record_full_is_used ())
-       record_full_gdb_operation_disable_set ();
+       restore_operation_disable.emplace
+         (record_full_gdb_operation_disable_set ());
 
       /* When using hardware single-step, a SIGTRAP is reported for both
         a completed single-step and a software breakpoint.  Need to
@@ -4203,8 +4198,6 @@ adjust_pc_after_break (struct thread_info *thread,
          || (thread->stepped_breakpoint
              && thread->prev_pc == breakpoint_pc))
        regcache_write_pc (regcache, breakpoint_pc);
-
-      do_cleanups (old_cleanups);
     }
 }
 
@@ -4252,12 +4245,11 @@ handle_syscall_event (struct execution_control_state *ecs)
   struct regcache *regcache;
   int syscall_number;
 
-  if (!ptid_equal (ecs->ptid, inferior_ptid))
-    context_switch (ecs->ptid);
+  context_switch (ecs);
 
-  regcache = get_thread_regcache (ecs->ptid);
+  regcache = get_thread_regcache (ecs->event_thread);
   syscall_number = ecs->ws.value.syscall_number;
-  stop_pc = regcache_read_pc (regcache);
+  ecs->event_thread->suspend.stop_pc = regcache_read_pc (regcache);
 
   if (catch_syscall_enabled () > 0
       && catching_syscall_number (syscall_number) > 0)
@@ -4267,8 +4259,9 @@ handle_syscall_event (struct execution_control_state *ecs)
                             syscall_number);
 
       ecs->event_thread->control.stop_bpstat
-       = bpstat_stop_status (get_regcache_aspace (regcache),
-                             stop_pc, ecs->ptid, &ecs->ws);
+       = bpstat_stop_status (regcache->aspace (),
+                             ecs->event_thread->suspend.stop_pc,
+                             ecs->event_thread, &ecs->ws);
 
       if (handle_stop_requested (ecs))
        return 0;
@@ -4298,7 +4291,8 @@ fill_in_stop_func (struct gdbarch *gdbarch,
     {
       /* Don't care about return value; stop_func_start and stop_func_name
         will both be 0 if it doesn't work.  */
-      find_pc_partial_function (stop_pc, &ecs->stop_func_name,
+      find_pc_partial_function (ecs->event_thread->suspend.stop_pc,
+                               &ecs->stop_func_name,
                                &ecs->stop_func_start, &ecs->stop_func_end);
       ecs->stop_func_start
        += gdbarch_deprecated_function_start_offset (gdbarch);
@@ -4312,12 +4306,12 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 }
 
 
-/* Return the STOP_SOON field of the inferior pointed at by PTID.  */
+/* Return the STOP_SOON field of the inferior pointed at by ECS.  */
 
 static enum stop_kind
-get_inferior_stop_soon (ptid_t ptid)
+get_inferior_stop_soon (execution_control_state *ecs)
 {
-  struct inferior *inf = find_inferior_ptid (ptid);
+  struct inferior *inf = find_inferior_ptid (ecs->ptid);
 
   gdb_assert (inf != NULL);
   return inf->control.stop_soon;
@@ -4370,24 +4364,11 @@ THREAD_STOPPED_BY (sw_breakpoint)
 /* Generate thread_stopped_by_hw_breakpoint.  */
 THREAD_STOPPED_BY (hw_breakpoint)
 
-/* Cleanups that switches to the PTID pointed at by PTID_P.  */
-
-static void
-switch_to_thread_cleanup (void *ptid_p)
-{
-  ptid_t ptid = *(ptid_t *) ptid_p;
-
-  switch_to_thread (ptid);
-}
-
 /* Save the thread's event and stop reason to process it later.  */
 
 static void
 save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
 {
-  struct regcache *regcache;
-  struct address_space *aspace;
-
   if (debug_infrun)
     {
       std::string statstr = target_waitstatus_to_string (ws);
@@ -4404,8 +4385,8 @@ save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
   tp->suspend.waitstatus = *ws;
   tp->suspend.waitstatus_pending_p = 1;
 
-  regcache = get_thread_regcache (tp->ptid);
-  aspace = get_regcache_aspace (regcache);
+  struct regcache *regcache = get_thread_regcache (tp);
+  const address_space *aspace = regcache->aspace ();
 
   if (ws->kind == TARGET_WAITKIND_STOPPED
       && ws->value.sig == GDB_SIGNAL_TRAP)
@@ -4470,7 +4451,6 @@ stop_all_threads (void)
   /* We may need multiple passes to discover all threads.  */
   int pass;
   int iterations = 0;
-  ptid_t entry_ptid;
   struct cleanup *old_chain;
 
   gdb_assert (target_is_non_stop_p ());
@@ -4478,11 +4458,10 @@ stop_all_threads (void)
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads\n");
 
-  entry_ptid = inferior_ptid;
-  old_chain = make_cleanup (switch_to_thread_cleanup, &entry_ptid);
+  scoped_restore_current_thread restore_thread;
 
   target_thread_events (1);
-  make_cleanup (disable_thread_events, NULL);
+  old_chain = make_cleanup (disable_thread_events, NULL);
 
   /* Request threads to stop, and then wait for the stops.  Because
      threads we already know about can spawn more threads while we're
@@ -4557,6 +4536,7 @@ stop_all_threads (void)
            pass = -1;
 
          event_ptid = wait_one (&ws);
+
          if (ws.kind == TARGET_WAITKIND_NO_RESUMED)
            {
              /* All resumed threads exited.  */
@@ -4577,7 +4557,7 @@ stop_all_threads (void)
            }
          else
            {
-             struct inferior *inf;
+             inferior *inf;
 
              t = find_thread_ptid (event_ptid);
              if (t == NULL)
@@ -4605,7 +4585,7 @@ stop_all_threads (void)
                  t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
                  t->suspend.waitstatus_pending_p = 0;
 
-                 if (displaced_step_fixup (t->ptid, GDB_SIGNAL_0) < 0)
+                 if (displaced_step_fixup (t, GDB_SIGNAL_0) < 0)
                    {
                      /* Add it back to the step-over queue.  */
                      if (debug_infrun)
@@ -4644,14 +4624,14 @@ stop_all_threads (void)
                  sig = (ws.kind == TARGET_WAITKIND_STOPPED
                         ? ws.value.sig : GDB_SIGNAL_0);
 
-                 if (displaced_step_fixup (t->ptid, sig) < 0)
+                 if (displaced_step_fixup (t, sig) < 0)
                    {
                      /* Add it back to the step-over queue.  */
                      t->control.trap_expected = 0;
                      thread_step_over_chain_enqueue (t);
                    }
 
-                 regcache = get_thread_regcache (t->ptid);
+                 regcache = get_thread_regcache (t);
                  t->suspend.stop_pc = regcache_read_pc (regcache);
 
                  if (debug_infrun)
@@ -4770,7 +4750,7 @@ handle_no_resumed (struct execution_control_state *ecs)
       if (inf->pid == 0)
        continue;
 
-      thread = any_live_thread_of_process (inf->pid);
+      thread_info *thread = any_live_thread_of_inferior (inf);
       if (thread == NULL)
        {
          if (debug_infrun)
@@ -4887,9 +4867,9 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
          || ecs->ws.value.sig == GDB_SIGNAL_SEGV
          || ecs->ws.value.sig == GDB_SIGNAL_EMT))
     {
-      struct regcache *regcache = get_thread_regcache (ecs->ptid);
+      struct regcache *regcache = get_thread_regcache (ecs->event_thread);
 
-      if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
+      if (breakpoint_inserted_here_p (regcache->aspace (),
                                      regcache_read_pc (regcache)))
        {
          if (debug_infrun)
@@ -4940,8 +4920,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
     case TARGET_WAITKIND_LOADED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+      context_switch (ecs);
       /* Ignore gracefully during startup of the inferior, as it might
          be the shell which has just loaded some objects, otherwise
          add the symbols for the newly loaded objects.  Also ignore at
@@ -4949,18 +4928,19 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
          the full list of libraries once the connection is
          established.  */
 
-      stop_soon = get_inferior_stop_soon (ecs->ptid);
+      stop_soon = get_inferior_stop_soon (ecs);
       if (stop_soon == NO_STOP_QUIETLY)
        {
          struct regcache *regcache;
 
-         regcache = get_thread_regcache (ecs->ptid);
+         regcache = get_thread_regcache (ecs->event_thread);
 
          handle_solib_event ();
 
          ecs->event_thread->control.stop_bpstat
-           = bpstat_stop_status (get_regcache_aspace (regcache),
-                                 stop_pc, ecs->ptid, &ecs->ws);
+           = bpstat_stop_status (regcache->aspace (),
+                                 ecs->event_thread->suspend.stop_pc,
+                                 ecs->event_thread, &ecs->ws);
 
          if (handle_stop_requested (ecs))
            return;
@@ -5021,8 +5001,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SPURIOUS\n");
       if (handle_stop_requested (ecs))
        return;
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+      context_switch (ecs);
       resume (GDB_SIGNAL_0);
       prepare_to_wait (ecs);
       return;
@@ -5032,8 +5011,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_THREAD_CREATED\n");
       if (handle_stop_requested (ecs))
        return;
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+      context_switch (ecs);
       if (!switch_back_to_stepped_thread (ecs))
        keep_going (ecs);
       return;
@@ -5054,7 +5032,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
       set_current_inferior (find_inferior_ptid (ecs->ptid));
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
-      target_terminal_ours (); /* Must do this before mourn anyway.  */
+      target_terminal::ours ();        /* Must do this before mourn anyway.  */
 
       /* Clearing any previous state of convenience variables.  */
       clear_exit_convenience_vars ();
@@ -5073,12 +5051,11 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
          /* Support the --return-child-result option.  */
          return_child_result_value = ecs->ws.value.integer;
 
-         observer_notify_exited (ecs->ws.value.integer);
+         gdb::observers::exited.notify (ecs->ws.value.integer);
        }
       else
        {
-         struct regcache *regcache = get_thread_regcache (ecs->ptid);
-         struct gdbarch *gdbarch = get_regcache_arch (regcache);
+         struct gdbarch *gdbarch = current_inferior ()->gdbarch;
 
          if (gdbarch_gdb_signal_to_target_p (gdbarch))
            {
@@ -5102,7 +5079,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
 Cannot fill $_exitsignal with the correct signal number.\n"));
            }
 
-         observer_notify_signal_exited (ecs->ws.value.sig);
+         gdb::observers::signal_exited.notify (ecs->ws.value.sig);
        }
 
       gdb_flush (gdb_stdout);
@@ -5125,12 +5102,12 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
 
       /* Check whether the inferior is displaced stepping.  */
       {
-       struct regcache *regcache = get_thread_regcache (ecs->ptid);
-       struct gdbarch *gdbarch = get_regcache_arch (regcache);
+       struct regcache *regcache = get_thread_regcache (ecs->event_thread);
+       struct gdbarch *gdbarch = regcache->arch ();
 
        /* If checking displaced stepping is supported, and thread
           ecs->ptid is displaced stepping.  */
-       if (displaced_step_in_progress_thread (ecs->ptid))
+       if (displaced_step_in_progress_thread (ecs->event_thread))
          {
            struct inferior *parent_inf
              = find_inferior_ptid (ecs->ptid);
@@ -5142,7 +5119,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
               has been done.  Perform cleanup for parent process here.  Note
               that this operation also cleans up the child process for vfork,
               because their pages are shared.  */
-           displaced_step_fixup (ecs->ptid, GDB_SIGNAL_TRAP);
+           displaced_step_fixup (ecs->event_thread, GDB_SIGNAL_TRAP);
            /* Start a new step-over in another thread if there's one
               that needs it.  */
            start_step_over ();
@@ -5150,7 +5127,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
            if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
              {
                struct displaced_step_inferior_state *displaced
-                 = get_displaced_stepping_state (ptid_get_pid (ecs->ptid));
+                 = get_displaced_stepping_state (parent_inf);
 
                /* Restore scratch pad for child process.  */
                displaced_step_restore (displaced, ecs->ws.value.related_pid);
@@ -5181,8 +5158,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
          }
       }
 
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+      context_switch (ecs);
 
       /* Immediately detach breakpoints from the child before there's
         any chance of letting the user delete breakpoints from the
@@ -5210,11 +5186,13 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
         and not immediately.  */
       ecs->event_thread->pending_follow = ecs->ws;
 
-      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+      ecs->event_thread->suspend.stop_pc
+       = regcache_read_pc (get_thread_regcache (ecs->event_thread));
 
       ecs->event_thread->control.stop_bpstat
-       = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
-                             stop_pc, ecs->ptid, &ecs->ws);
+       = bpstat_stop_status (get_current_regcache ()->aspace (),
+                             ecs->event_thread->suspend.stop_pc,
+                             ecs->event_thread, &ecs->ws);
 
       if (handle_stop_requested (ecs))
        return;
@@ -5225,8 +5203,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
         watchpoints, for example, always appear in the bpstat.  */
       if (!bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
        {
-         ptid_t parent;
-         ptid_t child;
          int should_resume;
          int follow_child
            = (follow_fork_mode_string == follow_fork_mode_child);
@@ -5235,19 +5211,19 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
 
          should_resume = follow_fork ();
 
-         parent = ecs->ptid;
-         child = ecs->ws.value.related_pid;
+         thread_info *parent = ecs->event_thread;
+         thread_info *child = find_thread_ptid (ecs->ws.value.related_pid);
 
          /* At this point, the parent is marked running, and the
             child is marked stopped.  */
 
          /* If not resuming the parent, mark it stopped.  */
          if (follow_child && !detach_fork && !non_stop && !sched_multi)
-           set_running (parent, 0);
+           parent->set_running (false);
 
          /* If resuming the child, mark it running.  */
          if (follow_child || (!detach_fork && (non_stop || sched_multi)))
-           set_running (child, 1);
+           child->set_running (true);
 
          /* In non-stop mode, also resume the other branch.  */
          if (!detach_fork && (non_stop
@@ -5288,8 +5264,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
        fprintf_unfiltered (gdb_stdlog,
                            "infrun: TARGET_WAITKIND_VFORK_DONE\n");
 
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+      context_switch (ecs);
 
       current_inferior ()->waiting_for_vfork_done = 0;
       current_inferior ()->pspace->breakpoints_not_allowed = 0;
@@ -5306,10 +5281,10 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n");
 
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
-
-      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+      /* Note we can't read registers yet (the stop_pc), because we
+        don't yet know the inferior's post-exec architecture.
+        'stop_pc' is explicitly read below instead.  */
+      switch_to_thread_no_regs (ecs->event_thread);
 
       /* Do whatever is necessary to the parent branch of the vfork.  */
       handle_vfork_child_exec_or_exit (1);
@@ -5324,9 +5299,13 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
         execd thread for that case (this is a nop otherwise).  */
       ecs->event_thread = inferior_thread ();
 
+      ecs->event_thread->suspend.stop_pc
+       = regcache_read_pc (get_thread_regcache (ecs->event_thread));
+
       ecs->event_thread->control.stop_bpstat
-       = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
-                             stop_pc, ecs->ptid, &ecs->ws);
+       = bpstat_stop_status (get_current_regcache ()->aspace (),
+                             ecs->event_thread->suspend.stop_pc,
+                             ecs->event_thread, &ecs->ws);
 
       /* Note that this may be referenced from inside
         bpstat_stop_status above, through inferior_has_execd.  */
@@ -5382,18 +5361,18 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
       /* Reverse execution: target ran out of history info.  */
 
       /* Switch to the stopped thread.  */
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+      context_switch (ecs);
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
 
       delete_just_stopped_threads_single_step_breakpoints ();
-      stop_pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
+      ecs->event_thread->suspend.stop_pc
+       = regcache_read_pc (get_thread_regcache (inferior_thread ()));
 
       if (handle_stop_requested (ecs))
        return;
 
-      observer_notify_no_history ();
+      gdb::observers::no_history.notify ();
       stop_waiting (ecs);
       return;
     }
@@ -5513,7 +5492,7 @@ restart_threads (struct thread_info *event_thread)
                                "infrun: restart threads: [%s] continuing\n",
                                target_pid_to_str (tp->ptid));
          reset_ecs (ecs, tp);
-         switch_to_thread (tp->ptid);
+         switch_to_thread (tp);
          keep_going_pass_signal (ecs);
        }
     }
@@ -5541,7 +5520,7 @@ finish_step_over (struct execution_control_state *ecs)
 {
   int had_step_over_info;
 
-  displaced_step_fixup (ecs->ptid,
+  displaced_step_fixup (ecs->event_thread,
                        ecs->event_thread->suspend.stop_signal);
 
   had_step_over_info = step_over_info_valid_p ();
@@ -5579,7 +5558,7 @@ finish_step_over (struct execution_control_state *ecs)
         another thread has a pending event for this breakpoint too,
         we'd discard its event (because the breakpoint that
         originally caused the event was no longer inserted).  */
-      context_switch (ecs->ptid);
+      context_switch (ecs);
       insert_breakpoints ();
 
       restart_threads (ecs->event_thread);
@@ -5622,7 +5601,7 @@ finish_step_over (struct execution_control_state *ecs)
 
          gdb_assert (!tp->executing);
 
-         regcache = get_thread_regcache (tp->ptid);
+         regcache = get_thread_regcache (tp);
          tp->suspend.stop_pc = regcache_read_pc (regcache);
 
          if (debug_infrun)
@@ -5680,25 +5659,27 @@ handle_signal_stop (struct execution_control_state *ecs)
       && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
     ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
 
-  stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+  ecs->event_thread->suspend.stop_pc
+    = regcache_read_pc (get_thread_regcache (ecs->event_thread));
 
   if (debug_infrun)
     {
-      struct regcache *regcache = get_thread_regcache (ecs->ptid);
-      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      struct regcache *regcache = get_thread_regcache (ecs->event_thread);
+      struct gdbarch *gdbarch = regcache->arch ();
       scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
 
       inferior_ptid = ecs->ptid;
 
       fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
-                          paddress (gdbarch, stop_pc));
+                         paddress (gdbarch,
+                                   ecs->event_thread->suspend.stop_pc));
       if (target_stopped_by_watchpoint ())
        {
           CORE_ADDR addr;
 
          fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
 
-          if (target_stopped_data_address (&current_target, &addr))
+         if (target_stopped_data_address (current_top_target (), &addr))
             fprintf_unfiltered (gdb_stdlog,
                                 "infrun: stopped data address = %s\n",
                                 paddress (gdbarch, addr));
@@ -5710,11 +5691,10 @@ handle_signal_stop (struct execution_control_state *ecs)
 
   /* This is originated from start_remote(), start_inferior() and
      shared libraries hook functions.  */
-  stop_soon = get_inferior_stop_soon (ecs->ptid);
+  stop_soon = get_inferior_stop_soon (ecs);
   if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
     {
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+      context_switch (ecs);
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
       stop_print_frame = 1;
@@ -5760,10 +5740,10 @@ handle_signal_stop (struct execution_control_state *ecs)
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog, "infrun: context switch\n");
 
-      context_switch (ecs->ptid);
+      context_switch (ecs);
 
       if (deprecated_context_hook)
-       deprecated_context_hook (ptid_to_global_thread_id (ecs->ptid));
+       deprecated_context_hook (ecs->event_thread->global_num);
     }
 
   /* At this point, get hold of the now-current thread's frame.  */
@@ -5774,11 +5754,11 @@ handle_signal_stop (struct execution_control_state *ecs)
   if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
     {
       struct regcache *regcache;
-      struct address_space *aspace;
       CORE_ADDR pc;
 
-      regcache = get_thread_regcache (ecs->ptid);
-      aspace = get_regcache_aspace (regcache);
+      regcache = get_thread_regcache (ecs->event_thread);
+      const address_space *aspace = regcache->aspace ();
+
       pc = regcache_read_pc (regcache);
 
       /* However, before doing so, if this single-step breakpoint was
@@ -5863,14 +5843,15 @@ handle_signal_stop (struct execution_control_state *ecs)
   ecs->event_thread->control.stop_step = 0;
   stop_print_frame = 1;
   stopped_by_random_signal = 0;
+  bpstat stop_chain = NULL;
 
   /* Hide inlined functions starting here, unless we just performed stepi or
      nexti.  After stepi and nexti, always show the innermost frame (not any
      inline function call sites).  */
   if (ecs->event_thread->control.step_range_end != 1)
     {
-      struct address_space *aspace = 
-       get_regcache_aspace (get_thread_regcache (ecs->ptid));
+      const address_space *aspace
+       = get_thread_regcache (ecs->event_thread)->aspace ();
 
       /* skip_inline_frames is expensive, so we avoid it if we can
         determine that the address is one where functions cannot have
@@ -5887,14 +5868,19 @@ handle_signal_stop (struct execution_control_state *ecs)
         user had set a breakpoint on that inlined code, the missing
         skip_inline_frames call would break things.  Fortunately
         that's an extremely unlikely scenario.  */
-      if (!pc_at_non_inline_function (aspace, stop_pc, &ecs->ws)
+      if (!pc_at_non_inline_function (aspace,
+                                     ecs->event_thread->suspend.stop_pc,
+                                     &ecs->ws)
          && !(ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
               && ecs->event_thread->control.trap_expected
               && pc_at_non_inline_function (aspace,
                                             ecs->event_thread->prev_pc,
                                             &ecs->ws)))
        {
-         skip_inline_frames (ecs->ptid);
+         stop_chain = build_bpstat_chain (aspace,
+                                          ecs->event_thread->suspend.stop_pc,
+                                          &ecs->ws);
+         skip_inline_frames (ecs->event_thread, stop_chain);
 
          /* Re-fetch current thread's frame in case that invalidated
             the frame cache.  */
@@ -5942,8 +5928,9 @@ handle_signal_stop (struct execution_control_state *ecs)
   /* See if there is a breakpoint/watchpoint/catchpoint/etc. that
      handles this event.  */
   ecs->event_thread->control.stop_bpstat
-    = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
-                         stop_pc, ecs->ptid, &ecs->ws);
+    = bpstat_stop_status (get_current_regcache ()->aspace (),
+                         ecs->event_thread->suspend.stop_pc,
+                         ecs->event_thread, &ecs->ws, stop_chain);
 
   /* Following in case break condition called a
      function.  */
@@ -5995,25 +5982,27 @@ handle_signal_stop (struct execution_control_state *ecs)
      been removed.  */
   if (random_signal && target_stopped_by_sw_breakpoint ())
     {
-      if (program_breakpoint_here_p (gdbarch, stop_pc))
+      if (program_breakpoint_here_p (gdbarch,
+                                    ecs->event_thread->suspend.stop_pc))
        {
          struct regcache *regcache;
          int decr_pc;
 
          /* Re-adjust PC to what the program would see if GDB was not
             debugging it.  */
-         regcache = get_thread_regcache (ecs->event_thread->ptid);
+         regcache = get_thread_regcache (ecs->event_thread);
          decr_pc = gdbarch_decr_pc_after_break (gdbarch);
          if (decr_pc != 0)
            {
-             struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
+             gdb::optional<scoped_restore_tmpl<int>>
+               restore_operation_disable;
 
              if (record_full_is_used ())
-               record_full_gdb_operation_disable_set ();
-
-             regcache_write_pc (regcache, stop_pc + decr_pc);
+               restore_operation_disable.emplace
+                 (record_full_gdb_operation_disable_set ());
 
-             do_cleanups (old_cleanups);
+             regcache_write_pc (regcache,
+                                ecs->event_thread->suspend.stop_pc + decr_pc);
            }
        }
       else
@@ -6096,16 +6085,16 @@ handle_signal_stop (struct execution_control_state *ecs)
       if (signal_print[ecs->event_thread->suspend.stop_signal])
        {
          /* The signal table tells us to print about this signal.  */
-         target_terminal_ours_for_output ();
-         observer_notify_signal_received (ecs->event_thread->suspend.stop_signal);
-         target_terminal_inferior ();
+         target_terminal::ours_for_output ();
+         gdb::observers::signal_received.notify (ecs->event_thread->suspend.stop_signal);
+         target_terminal::inferior ();
        }
 
       /* Clear the signal if it should not be passed.  */
       if (signal_program[ecs->event_thread->suspend.stop_signal] == 0)
        ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
 
-      if (ecs->event_thread->prev_pc == stop_pc
+      if (ecs->event_thread->prev_pc == ecs->event_thread->suspend.stop_pc
          && ecs->event_thread->control.trap_expected
          && ecs->event_thread->control.step_resume_breakpoint == NULL)
        {
@@ -6137,7 +6126,8 @@ handle_signal_stop (struct execution_control_state *ecs)
        }
 
       if (ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0
-         && (pc_in_thread_step_range (stop_pc, ecs->event_thread)
+         && (pc_in_thread_step_range (ecs->event_thread->suspend.stop_pc,
+                                      ecs->event_thread)
              || ecs->event_thread->control.step_range_end == 1)
          && frame_id_eq (get_stack_frame_id (frame),
                          ecs->event_thread->control.step_stack_frame_id)
@@ -6367,7 +6357,7 @@ process_event_stop_test (struct execution_control_state *ecs)
          return;
        }
       fill_in_stop_func (gdbarch, ecs);
-      if (stop_pc == ecs->stop_func_start
+      if (ecs->event_thread->suspend.stop_pc == ecs->stop_func_start
          && execution_direction == EXEC_REVERSE)
        {
          /* We are stepping over a function call in reverse, and just
@@ -6500,7 +6490,8 @@ process_event_stop_test (struct execution_control_state *ecs)
      through a function epilogue and therefore must detect when
      the current-frame changes in the middle of a line.  */
 
-  if (pc_in_thread_step_range (stop_pc, ecs->event_thread)
+  if (pc_in_thread_step_range (ecs->event_thread->suspend.stop_pc,
+                              ecs->event_thread)
       && (execution_direction != EXEC_REVERSE
          || frame_id_eq (get_frame_id (frame),
                          ecs->event_thread->control.step_frame_id)))
@@ -6519,6 +6510,7 @@ process_event_stop_test (struct execution_control_state *ecs)
       /* When stepping backward, stop at beginning of line range
         (unless it's the function entry point, in which case
         keep going back to the call point).  */
+      CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
       if (stop_pc == ecs->event_thread->control.step_range_start
          && stop_pc != ecs->stop_func_start
          && execution_direction == EXEC_REVERSE)
@@ -6545,10 +6537,11 @@ process_event_stop_test (struct execution_control_state *ecs)
 
   if (execution_direction != EXEC_REVERSE
       && ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
-      && in_solib_dynsym_resolve_code (stop_pc))
+      && in_solib_dynsym_resolve_code (ecs->event_thread->suspend.stop_pc))
     {
       CORE_ADDR pc_after_resolver =
-       gdbarch_skip_solib_resolver (gdbarch, stop_pc);
+       gdbarch_skip_solib_resolver (gdbarch,
+                                    ecs->event_thread->suspend.stop_pc);
 
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog,
@@ -6558,9 +6551,7 @@ process_event_stop_test (struct execution_control_state *ecs)
        {
          /* Set up a step-resume breakpoint at the address
             indicated by SKIP_SOLIB_RESOLVER.  */
-         struct symtab_and_line sr_sal;
-
-         init_sal (&sr_sal);
+         symtab_and_line sr_sal;
          sr_sal.pc = pc_after_resolver;
          sr_sal.pspace = get_frame_program_space (frame);
 
@@ -6572,6 +6563,18 @@ process_event_stop_test (struct execution_control_state *ecs)
       return;
     }
 
+  /* Step through an indirect branch thunk.  */
+  if (ecs->event_thread->control.step_over_calls != STEP_OVER_NONE
+      && gdbarch_in_indirect_branch_thunk (gdbarch,
+                                          ecs->event_thread->suspend.stop_pc))
+    {
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog,
+                            "infrun: stepped into indirect branch thunk\n");
+      keep_going (ecs);
+      return;
+    }
+
   if (ecs->event_thread->control.step_range_end != 1
       && (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
          || ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
@@ -6595,13 +6598,14 @@ process_event_stop_test (struct execution_control_state *ecs)
      call check below as on some targets return trampolines look
      like subroutine calls (MIPS16 return thunks).  */
   if (gdbarch_in_solib_return_trampoline (gdbarch,
-                                         stop_pc, ecs->stop_func_name)
+                                         ecs->event_thread->suspend.stop_pc,
+                                         ecs->stop_func_name)
       && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE)
     {
       /* Determine where this trampoline returns.  */
-      CORE_ADDR real_stop_pc;
-
-      real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
+      CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
+      CORE_ADDR real_stop_pc
+       = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
 
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog,
@@ -6611,9 +6615,7 @@ process_event_stop_test (struct execution_control_state *ecs)
       if (real_stop_pc)
        {
          /* And put the step-breakpoint there and go until there.  */
-         struct symtab_and_line sr_sal;
-
-         init_sal (&sr_sal);   /* initialize to zeroes */
+         symtab_and_line sr_sal;
          sr_sal.pc = real_stop_pc;
          sr_sal.section = find_pc_overlay (sr_sal.pc);
          sr_sal.pspace = get_frame_program_space (frame);
@@ -6655,8 +6657,9 @@ process_event_stop_test (struct execution_control_state *ecs)
          && (!frame_id_eq (ecs->event_thread->control.step_stack_frame_id,
                            outer_frame_id)
              || (ecs->event_thread->control.step_start_function
-                 != find_pc_function (stop_pc)))))
+                 != find_pc_function (ecs->event_thread->suspend.stop_pc)))))
     {
+      CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
       CORE_ADDR real_stop_pc;
 
       if (debug_infrun)
@@ -6711,10 +6714,8 @@ process_event_stop_test (struct execution_control_state *ecs)
                 to the caller.  */
              if (ecs->stop_func_start != stop_pc && ecs->stop_func_start != 0)
                {
-                 struct symtab_and_line sr_sal;
-
                  /* Normal function call return (static or dynamic).  */
-                 init_sal (&sr_sal);
+                 symtab_and_line sr_sal;
                  sr_sal.pc = ecs->stop_func_start;
                  sr_sal.pspace = get_frame_program_space (frame);
                  insert_step_resume_breakpoint_at_sal (gdbarch,
@@ -6741,9 +6742,7 @@ process_event_stop_test (struct execution_control_state *ecs)
 
       if (real_stop_pc != 0 && in_solib_dynsym_resolve_code (real_stop_pc))
        {
-         struct symtab_and_line sr_sal;
-
-         init_sal (&sr_sal);
+         symtab_and_line sr_sal;
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
 
@@ -6797,9 +6796,7 @@ process_event_stop_test (struct execution_control_state *ecs)
            {
              /* Set a breakpoint at callee's start address.
                 From there we can step once and be back in the caller.  */
-             struct symtab_and_line sr_sal;
-
-             init_sal (&sr_sal);
+             symtab_and_line sr_sal;
              sr_sal.pc = ecs->stop_func_start;
              sr_sal.pspace = get_frame_program_space (frame);
              insert_step_resume_breakpoint_at_sal (gdbarch,
@@ -6820,6 +6817,8 @@ process_event_stop_test (struct execution_control_state *ecs)
   if (execution_direction == EXEC_REVERSE
       && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE)
     {
+      CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
+
       if (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc)
          || (ecs->stop_func_start == 0
              && in_solib_dynsym_resolve_code (stop_pc)))
@@ -6837,9 +6836,7 @@ process_event_stop_test (struct execution_control_state *ecs)
          /* Stepped backward into the solib dynsym resolver.
             Set a breakpoint at its start and continue, then
             one more step will take us out.  */
-         struct symtab_and_line sr_sal;
-
-         init_sal (&sr_sal);
+         symtab_and_line sr_sal;
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
          insert_step_resume_breakpoint_at_sal (gdbarch, 
@@ -6849,7 +6846,7 @@ process_event_stop_test (struct execution_control_state *ecs)
        }
     }
 
-  stop_pc_sal = find_pc_line (stop_pc, 0);
+  stop_pc_sal = find_pc_line (ecs->event_thread->suspend.stop_pc, 0);
 
   /* NOTE: tausq/2004-05-24: This if block used to be done before all
      the trampoline processing logic, however, there are some trampolines 
@@ -6917,15 +6914,13 @@ process_event_stop_test (struct execution_control_state *ecs)
 
   if (frame_id_eq (get_frame_id (get_current_frame ()),
                   ecs->event_thread->control.step_frame_id)
-      && inline_skipped_frames (ecs->ptid))
+      && inline_skipped_frames (ecs->event_thread))
     {
-      struct symtab_and_line call_sal;
-
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog,
                            "infrun: stepped into inlined function\n");
 
-      find_frame_sal (get_current_frame (), &call_sal);
+      symtab_and_line call_sal = find_frame_sal (get_current_frame ());
 
       if (ecs->event_thread->control.step_over_calls != STEP_OVER_ALL)
        {
@@ -6936,7 +6931,7 @@ process_event_stop_test (struct execution_control_state *ecs)
 
          if (call_sal.line == ecs->event_thread->current_line
              && call_sal.symtab == ecs->event_thread->current_symtab)
-           step_into_inline_frame (ecs->ptid);
+           step_into_inline_frame (ecs->event_thread);
 
          end_stepping_range (ecs);
          return;
@@ -6977,7 +6972,7 @@ process_event_stop_test (struct execution_control_state *ecs)
       return;
     }
 
-  if ((stop_pc == stop_pc_sal.pc)
+  if ((ecs->event_thread->suspend.stop_pc == stop_pc_sal.pc)
       && (ecs->event_thread->current_line != stop_pc_sal.line
          || ecs->event_thread->current_symtab != stop_pc_sal.symtab))
     {
@@ -7193,15 +7188,14 @@ keep_going_stepped_thread (struct thread_info *tp)
        stepping thread is still alive.  For that reason, we need to
        synchronously query the target now.  */
 
-  if (is_exited (tp->ptid)
-      || !target_thread_alive (tp->ptid))
+  if (tp->state == THREAD_EXITED || !target_thread_alive (tp->ptid))
     {
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog,
                            "infrun: not resuming previously  "
                            "stepped thread, it has vanished\n");
 
-      delete_thread (tp->ptid);
+      delete_thread (tp);
       return 0;
     }
 
@@ -7210,9 +7204,9 @@ keep_going_stepped_thread (struct thread_info *tp)
                        "infrun: resuming previously stepped thread\n");
 
   reset_ecs (ecs, tp);
-  switch_to_thread (tp->ptid);
+  switch_to_thread (tp);
 
-  stop_pc = regcache_read_pc (get_thread_regcache (tp->ptid));
+  tp->suspend.stop_pc = regcache_read_pc (get_thread_regcache (tp));
   frame = get_current_frame ();
 
   /* If the PC of the thread we were trying to single-step has
@@ -7228,7 +7222,7 @@ keep_going_stepped_thread (struct thread_info *tp)
      This prevents us continuously moving the single-step breakpoint
      forward, one instruction at a time, overstepping.  */
 
-  if (stop_pc != tp->prev_pc)
+  if (tp->suspend.stop_pc != tp->prev_pc)
     {
       ptid_t resume_ptid;
 
@@ -7236,7 +7230,7 @@ keep_going_stepped_thread (struct thread_info *tp)
        fprintf_unfiltered (gdb_stdlog,
                            "infrun: expected thread advanced also (%s -> %s)\n",
                            paddress (target_gdbarch (), tp->prev_pc),
-                           paddress (target_gdbarch (), stop_pc));
+                           paddress (target_gdbarch (), tp->suspend.stop_pc));
 
       /* Clear the info of the previous step-over, as it's no longer
         valid (if the thread was trying to step over a breakpoint, it
@@ -7250,7 +7244,7 @@ keep_going_stepped_thread (struct thread_info *tp)
 
       insert_single_step_breakpoint (get_frame_arch (frame),
                                     get_frame_address_space (frame),
-                                    stop_pc);
+                                    tp->suspend.stop_pc);
 
       tp->resumed = 1;
       resume_ptid = internal_resume_ptid (tp->control.stepping_command);
@@ -7289,17 +7283,15 @@ static void
 handle_step_into_function (struct gdbarch *gdbarch,
                           struct execution_control_state *ecs)
 {
-  struct compunit_symtab *cust;
-  struct symtab_and_line stop_func_sal, sr_sal;
-
   fill_in_stop_func (gdbarch, ecs);
 
-  cust = find_pc_compunit_symtab (stop_pc);
+  compunit_symtab *cust
+    = find_pc_compunit_symtab (ecs->event_thread->suspend.stop_pc);
   if (cust != NULL && compunit_language (cust) != language_asm)
     ecs->stop_func_start
       = gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
 
-  stop_func_sal = find_pc_line (ecs->stop_func_start, 0);
+  symtab_and_line stop_func_sal = find_pc_line (ecs->stop_func_start, 0);
   /* Use the step_resume_break to step until the end of the prologue,
      even if that involves jumps (as it seems to on the vax under
      4.2).  */
@@ -7334,7 +7326,7 @@ handle_step_into_function (struct gdbarch *gdbarch,
                                             ecs->stop_func_start);
     }
 
-  if (ecs->stop_func_start == stop_pc)
+  if (ecs->stop_func_start == ecs->event_thread->suspend.stop_pc)
     {
       /* We are already there: stop now.  */
       end_stepping_range (ecs);
@@ -7343,7 +7335,7 @@ handle_step_into_function (struct gdbarch *gdbarch,
   else
     {
       /* Put the step-breakpoint there and go until there.  */
-      init_sal (&sr_sal);      /* initialize to zeroes */
+      symtab_and_line sr_sal;
       sr_sal.pc = ecs->stop_func_start;
       sr_sal.section = find_pc_overlay (ecs->stop_func_start);
       sr_sal.pspace = get_frame_program_space (get_current_frame ());
@@ -7373,15 +7365,15 @@ handle_step_into_function_backward (struct gdbarch *gdbarch,
 
   fill_in_stop_func (gdbarch, ecs);
 
-  cust = find_pc_compunit_symtab (stop_pc);
+  cust = find_pc_compunit_symtab (ecs->event_thread->suspend.stop_pc);
   if (cust != NULL && compunit_language (cust) != language_asm)
     ecs->stop_func_start
       = gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
 
-  stop_func_sal = find_pc_line (stop_pc, 0);
+  stop_func_sal = find_pc_line (ecs->event_thread->suspend.stop_pc, 0);
 
   /* OK, we're just going to keep stepping here.  */
-  if (stop_func_sal.pc == stop_pc)
+  if (stop_func_sal.pc == ecs->event_thread->suspend.stop_pc)
     {
       /* We're there already.  Just stop stepping now.  */
       end_stepping_range (ecs);
@@ -7419,7 +7411,7 @@ insert_step_resume_breakpoint_at_sal_1 (struct gdbarch *gdbarch,
                        paddress (gdbarch, sr_sal.pc));
 
   inferior_thread ()->control.step_resume_breakpoint
-    = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type);
+    = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type).release ();
 }
 
 void
@@ -7442,13 +7434,11 @@ insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch,
 static void
 insert_hp_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
 {
-  struct symtab_and_line sr_sal;
-  struct gdbarch *gdbarch;
-
   gdb_assert (return_frame != NULL);
-  init_sal (&sr_sal);          /* initialize to zeros */
 
-  gdbarch = get_frame_arch (return_frame);
+  struct gdbarch *gdbarch = get_frame_arch (return_frame);
+
+  symtab_and_line sr_sal;
   sr_sal.pc = gdbarch_addr_bits_remove (gdbarch, get_frame_pc (return_frame));
   sr_sal.section = find_pc_overlay (sr_sal.pc);
   sr_sal.pspace = get_frame_program_space (return_frame);
@@ -7475,16 +7465,13 @@ insert_hp_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
 static void
 insert_step_resume_breakpoint_at_caller (struct frame_info *next_frame)
 {
-  struct symtab_and_line sr_sal;
-  struct gdbarch *gdbarch;
-
   /* We shouldn't have gotten here if we don't know where the call site
      is.  */
   gdb_assert (frame_id_p (frame_unwind_caller_id (next_frame)));
 
-  init_sal (&sr_sal);          /* initialize to zeros */
+  struct gdbarch *gdbarch = frame_unwind_caller_arch (next_frame);
 
-  gdbarch = frame_unwind_caller_arch (next_frame);
+  symtab_and_line sr_sal;
   sr_sal.pc = gdbarch_addr_bits_remove (gdbarch,
                                        frame_unwind_caller_pc (next_frame));
   sr_sal.section = find_pc_overlay (sr_sal.pc);
@@ -7513,7 +7500,7 @@ insert_longjmp_resume_breakpoint (struct gdbarch *gdbarch, CORE_ADDR pc)
                        paddress (gdbarch, pc));
 
   inferior_thread ()->control.exception_resume_breakpoint =
-    set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume);
+    set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume).release ();
 }
 
 /* Insert an exception resume breakpoint.  TP is the thread throwing
@@ -7535,7 +7522,8 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
       CORE_ADDR handler;
       struct breakpoint *bp;
 
-      vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL);
+      vsym = lookup_symbol_search_name (SYMBOL_SEARCH_NAME (sym),
+                                       b, VAR_DOMAIN);
       value = read_var_value (vsym.symbol, vsym.block, frame);
       /* If the value was optimized out, revert to the old behavior.  */
       if (! value_optimized_out (value))
@@ -7548,7 +7536,8 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
                                (unsigned long) handler);
 
          bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
-                                              handler, bp_exception_resume);
+                                              handler,
+                                              bp_exception_resume).release ();
 
          /* set_momentary_breakpoint_at_pc invalidates FRAME.  */
          frame = NULL;
@@ -7589,7 +7578,7 @@ insert_exception_resume_from_probe (struct thread_info *tp,
                                  handler));
 
   bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
-                                      handler, bp_exception_resume);
+                                      handler, bp_exception_resume).release ();
   bp->thread = tp->global_num;
   inferior_thread ()->control.exception_resume_breakpoint = bp;
 }
@@ -7610,7 +7599,7 @@ check_exception_resume (struct execution_control_state *ecs,
      CFA and the HANDLER.  We ignore the CFA, extract the handler, and
      set a breakpoint there.  */
   probe = find_probe_by_pc (get_frame_pc (frame));
-  if (probe.probe)
+  if (probe.prob)
     {
       insert_exception_resume_from_probe (ecs->event_thread, &probe, frame);
       return;
@@ -7684,16 +7673,12 @@ stop_waiting (struct execution_control_state *ecs)
 static void
 keep_going_pass_signal (struct execution_control_state *ecs)
 {
-  /* Make sure normal_stop is called if we get a QUIT handled before
-     reaching resume.  */
-  struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
-
   gdb_assert (ptid_equal (ecs->event_thread->ptid, inferior_ptid));
   gdb_assert (!ecs->event_thread->resumed);
 
   /* Save the pc before execution, to compare with pc after stop.  */
   ecs->event_thread->prev_pc
-    = regcache_read_pc (get_thread_regcache (ecs->ptid));
+    = regcache_read_pc (get_thread_regcache (ecs->event_thread));
 
   if (ecs->event_thread->control.trap_expected)
     {
@@ -7709,7 +7694,6 @@ keep_going_pass_signal (struct execution_control_state *ecs)
         non-signal event (e.g., a fork); or took a signal which we
         are supposed to pass through to the inferior.  Simply
         continue.  */
-      discard_cleanups (old_cleanups);
       resume (ecs->event_thread->suspend.stop_signal);
     }
   else if (step_over_info_valid_p ())
@@ -7737,8 +7721,6 @@ keep_going_pass_signal (struct execution_control_state *ecs)
                                "resume of %s deferred\n",
                                target_pid_to_str (tp->ptid));
        }
-
-      discard_cleanups (old_cleanups);
     }
   else
     {
@@ -7778,7 +7760,7 @@ keep_going_pass_signal (struct execution_control_state *ecs)
       if (remove_bp
          && (remove_wps || !use_displaced_stepping (ecs->event_thread)))
        {
-         set_step_over_info (get_regcache_aspace (regcache),
+         set_step_over_info (regcache->aspace (),
                              regcache_read_pc (regcache), remove_wps,
                              ecs->event_thread->global_num);
        }
@@ -7802,14 +7784,13 @@ keep_going_pass_signal (struct execution_control_state *ecs)
        {
          exception_print (gdb_stderr, e);
          stop_waiting (ecs);
-         discard_cleanups (old_cleanups);
+         clear_step_over_info ();
          return;
        }
       END_CATCH
 
       ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
 
-      discard_cleanups (old_cleanups);
       resume (ecs->event_thread->suspend.stop_signal);
     }
 
@@ -7942,7 +7923,7 @@ static void
 handle_segmentation_fault (struct ui_out *uiout)
 {
   struct regcache *regcache = get_current_regcache ();
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
 
   if (gdbarch_handle_segmentation_fault_p (gdbarch))
     gdbarch_handle_segmentation_fault (gdbarch, uiout);
@@ -8027,7 +8008,8 @@ print_stop_location (struct target_waitstatus *ws)
       if (tp->control.stop_step
          && frame_id_eq (tp->control.step_frame_id,
                          get_frame_id (get_current_frame ()))
-         && tp->control.step_start_function == find_pc_function (stop_pc))
+         && (tp->control.step_start_function
+             == find_pc_function (tp->suspend.stop_pc)))
        {
          /* Finished step, just print source line.  */
          source_flag = SRC_LINE;
@@ -8104,7 +8086,7 @@ maybe_remove_breakpoints (void)
     {
       if (remove_breakpoints ())
        {
-         target_terminal_ours_for_output ();
+         target_terminal::ours_for_output ();
          printf_filtered (_("Cannot remove breakpoints because "
                             "program is no longer writable.\nFurther "
                             "execution is probably impossible.\n"));
@@ -8193,8 +8175,6 @@ normal_stop (void)
 {
   struct target_waitstatus last;
   ptid_t last_ptid;
-  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-  ptid_t pid_ptid;
 
   get_last_target_status (&last_ptid, &last);
 
@@ -8204,8 +8184,11 @@ normal_stop (void)
      propagate GDB's knowledge of the executing state to the
      frontend/user running state.  A QUIT is an easy exception to see
      here, so do this before any filtered output.  */
+
+  gdb::optional<scoped_finish_thread_state> maybe_finish_thread_state;
+
   if (!non_stop)
-    make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+    maybe_finish_thread_state.emplace (minus_one_ptid);
   else if (last.kind == TARGET_WAITKIND_SIGNALLED
           || last.kind == TARGET_WAITKIND_EXITED)
     {
@@ -8214,14 +8197,11 @@ normal_stop (void)
         "checkpoint", when the current checkpoint/fork exits,
         linux-fork.c automatically switches to another fork from
         within target_mourn_inferior.  */
-      if (!ptid_equal (inferior_ptid, null_ptid))
-       {
-         pid_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
-         make_cleanup (finish_thread_state_cleanup, &pid_ptid);
-       }
+      if (inferior_ptid != null_ptid)
+       maybe_finish_thread_state.emplace (ptid_t (inferior_ptid.pid ()));
     }
   else if (last.kind != TARGET_WAITKIND_NO_RESUMED)
-    make_cleanup (finish_thread_state_cleanup, &inferior_ptid);
+    maybe_finish_thread_state.emplace (inferior_ptid);
 
   /* As we're presenting a stop, and potentially removing breakpoints,
      update the thread list so we can tell whether there are threads
@@ -8234,7 +8214,7 @@ normal_stop (void)
   update_thread_list ();
 
   if (last.kind == TARGET_WAITKIND_STOPPED && stopped_by_random_signal)
-    observer_notify_signal_received (inferior_thread ()->suspend.stop_signal);
+    gdb::observers::signal_received.notify (inferior_thread ()->suspend.stop_signal);
 
   /* As with the notification of thread events, we want to delay
      notifying the user that we've switched thread context until
@@ -8253,7 +8233,7 @@ normal_stop (void)
      after this event is handled, so we're not really switching, only
      informing of a stop.  */
   if (!non_stop
-      && !ptid_equal (previous_inferior_ptid, inferior_ptid)
+      && previous_inferior_ptid != inferior_ptid
       && target_has_execution
       && last.kind != TARGET_WAITKIND_SIGNALLED
       && last.kind != TARGET_WAITKIND_EXITED
@@ -8261,7 +8241,7 @@ normal_stop (void)
     {
       SWITCH_THRU_ALL_UIS ()
        {
-         target_terminal_ours_for_output ();
+         target_terminal::ours_for_output ();
          printf_filtered (_("[Switching to %s]\n"),
                           target_pid_to_str (inferior_ptid));
          annotate_thread_changed ();
@@ -8274,7 +8254,7 @@ normal_stop (void)
       SWITCH_THRU_ALL_UIS ()
        if (current_ui->prompt_state == PROMPT_BLOCKED)
          {
-           target_terminal_ours_for_output ();
+           target_terminal::ours_for_output ();
            printf_filtered (_("No unwaited-for children left.\n"));
          }
     }
@@ -8294,7 +8274,7 @@ normal_stop (void)
     }
 
   /* Let the user/frontend see the threads as stopped.  */
-  do_cleanups (old_chain);
+  maybe_finish_thread_state.reset ();
 
   /* Select innermost stack frame - i.e., current frame is frame 0,
      and current location is based on that.  Handle the case where the
@@ -8332,8 +8312,16 @@ normal_stop (void)
       struct cleanup *old_chain
        = make_cleanup (release_stop_context_cleanup, saved_context);
 
-      catch_errors (hook_stop_stub, stop_command,
-                   "Error while running hook_stop:\n", RETURN_MASK_ALL);
+      TRY
+       {
+         execute_cmd_pre_hook (stop_command);
+       }
+      CATCH (ex, RETURN_MASK_ALL)
+       {
+         exception_fprintf (gdb_stderr, ex,
+                            "Error while running hook_stop:\n");
+       }
+      END_CATCH
 
       /* If the stop hook resumes the target, then there's no point in
         trying to notify about the previous stop; its context is
@@ -8351,10 +8339,10 @@ normal_stop (void)
   /* Notify observers about the stop.  This is where the interpreters
      print the stop event.  */
   if (!ptid_equal (inferior_ptid, null_ptid))
-    observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat,
+    gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat,
                                 stop_print_frame);
   else
-    observer_notify_normal_stop (NULL, stop_print_frame);
+    gdb::observers::normal_stop.notify (NULL, stop_print_frame);
 
   annotate_stopped ();
 
@@ -8374,13 +8362,6 @@ normal_stop (void)
 
   return 0;
 }
-
-static int
-hook_stop_stub (void *cmd)
-{
-  execute_cmd_pre_hook ((struct cmd_list_element *) cmd);
-  return (0);
-}
 \f
 int
 signal_stop_state (int signo)
@@ -8488,7 +8469,7 @@ sig_print_info (enum gdb_signal oursig)
 /* Specify how various signals in the inferior should be handled.  */
 
 static void
-handle_command (char *args, int from_tty)
+handle_command (const char *args, int from_tty)
 {
   int digits, wordlen;
   int sigfirst, signum, siglast;
@@ -8701,7 +8682,7 @@ Use \"info signals\" for a list of symbolic signals."));
    targets, all signals should be in the signal tables).  */
 
 static void
-info_signals_command (char *signum_exp, int from_tty)
+info_signals_command (const char *signum_exp, int from_tty)
 {
   enum gdb_signal oursig;
 
@@ -8761,7 +8742,7 @@ siginfo_value_read (struct value *v)
   validate_registers_access ();
 
   transferred =
-    target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO,
+    target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO,
                 NULL,
                 value_contents_all_raw (v),
                 value_offset (v),
@@ -8783,7 +8764,7 @@ siginfo_value_write (struct value *v, struct value *fromval)
      vice versa.  */
   validate_registers_access ();
 
-  transferred = target_write (&current_target,
+  transferred = target_write (current_top_target (),
                              TARGET_OBJECT_SIGNAL_INFO,
                              NULL,
                              value_contents_all_raw (fromval),
@@ -8832,8 +8813,7 @@ struct infcall_suspend_state
   struct thread_suspend_state thread_suspend;
 
   /* Other fields:  */
-  CORE_ADDR stop_pc;
-  struct regcache *registers;
+  readonly_detached_regcache *registers;
 
   /* Format of SIGINFO_DATA or NULL if it is not present.  */
   struct gdbarch *siginfo_gdbarch;
@@ -8850,7 +8830,7 @@ save_infcall_suspend_state (void)
   struct infcall_suspend_state *inf_state;
   struct thread_info *tp = inferior_thread ();
   struct regcache *regcache = get_current_regcache ();
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   gdb_byte *siginfo_data = NULL;
 
   if (gdbarch_get_siginfo_type_p (gdbarch))
@@ -8862,7 +8842,7 @@ save_infcall_suspend_state (void)
       siginfo_data = (gdb_byte *) xmalloc (len);
       back_to = make_cleanup (xfree, siginfo_data);
 
-      if (target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+      if (target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
                       siginfo_data, 0, len) == len)
        discard_cleanups (back_to);
       else
@@ -8887,9 +8867,7 @@ save_infcall_suspend_state (void)
      GDB_SIGNAL_0 anyway.  */
   tp->suspend.stop_signal = GDB_SIGNAL_0;
 
-  inf_state->stop_pc = stop_pc;
-
-  inf_state->registers = regcache_dup (regcache);
+  inf_state->registers = new readonly_detached_regcache (*regcache);
 
   return inf_state;
 }
@@ -8901,18 +8879,16 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
   struct thread_info *tp = inferior_thread ();
   struct regcache *regcache = get_current_regcache ();
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
 
   tp->suspend = inf_state->thread_suspend;
 
-  stop_pc = inf_state->stop_pc;
-
   if (inf_state->siginfo_gdbarch == gdbarch)
     {
       struct type *type = gdbarch_get_siginfo_type (gdbarch);
 
       /* Errors ignored.  */
-      target_write (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+      target_write (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
                    inf_state->siginfo_data, 0, TYPE_LENGTH (type));
     }
 
@@ -8920,7 +8896,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
      (and perhaps other times).  */
   if (target_has_execution)
     /* NB: The register write goes through to the target.  */
-    regcache_cpy (regcache, inf_state->registers);
+    regcache->restore (inf_state->registers);
 
   discard_infcall_suspend_state (inf_state);
 }
@@ -8941,12 +8917,12 @@ make_cleanup_restore_infcall_suspend_state
 void
 discard_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
-  regcache_xfree (inf_state->registers);
+  delete inf_state->registers;
   xfree (inf_state->siginfo_data);
   xfree (inf_state);
 }
 
-struct regcache *
+readonly_detached_regcache *
 get_infcall_suspend_state_regcache (struct infcall_suspend_state *inf_state)
 {
   return inf_state->registers;
@@ -9001,25 +8977,20 @@ save_infcall_control_state (void)
   return inf_status;
 }
 
-static int
-restore_selected_frame (void *args)
+static void
+restore_selected_frame (const frame_id &fid)
 {
-  struct frame_id *fid = (struct frame_id *) args;
-  struct frame_info *frame;
-
-  frame = frame_find_by_id (*fid);
+  frame_info *frame = frame_find_by_id (fid);
 
   /* If inf_status->selected_frame_id is NULL, there was no previously
      selected frame.  */
   if (frame == NULL)
     {
       warning (_("Unable to restore previously selected frame."));
-      return 0;
+      return;
     }
 
   select_frame (frame);
-
-  return (1);
 }
 
 /* Restore inferior session state to INF_STATUS.  */
@@ -9049,16 +9020,22 @@ restore_infcall_control_state (struct infcall_control_state *inf_status)
 
   if (target_has_stack)
     {
-      /* The point of catch_errors is that if the stack is clobbered,
+      /* The point of the try/catch is that if the stack is clobbered,
          walking the stack might encounter a garbage pointer and
          error() trying to dereference it.  */
-      if (catch_errors
-         (restore_selected_frame, &inf_status->selected_frame_id,
-          "Unable to restore previously selected frame:\n",
-          RETURN_MASK_ERROR) == 0)
-       /* Error in restoring the selected frame.  Select the innermost
-          frame.  */
-       select_frame (get_current_frame ());
+      TRY
+       {
+         restore_selected_frame (inf_status->selected_frame_id);
+       }
+      CATCH (ex, RETURN_MASK_ERROR)
+       {
+         exception_fprintf (gdb_stderr, ex,
+                            "Unable to restore previously selected frame:\n");
+         /* Error in restoring the selected frame.  Select the
+            innermost frame.  */
+         select_frame (get_current_frame ());
+       }
+      END_CATCH
     }
 
   xfree (inf_status);
@@ -9119,7 +9096,7 @@ static const char *const exec_direction_names[] = {
 };
 
 static void
-set_exec_direction_func (char *args, int from_tty,
+set_exec_direction_func (const char *args, int from_tty,
                         struct cmd_list_element *cmd)
 {
   if (target_can_execute_reverse)
@@ -9465,10 +9442,10 @@ enabled by default on some platforms."),
   inferior_ptid = null_ptid;
   target_last_wait_ptid = minus_one_ptid;
 
-  observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
-  observer_attach_thread_stop_requested (infrun_thread_stop_requested);
-  observer_attach_thread_exit (infrun_thread_thread_exit);
-  observer_attach_inferior_exit (infrun_inferior_exit);
+  gdb::observers::thread_ptid_changed.attach (infrun_thread_ptid_changed);
+  gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested);
+  gdb::observers::thread_exit.attach (infrun_thread_thread_exit);
+  gdb::observers::inferior_exit.attach (infrun_inferior_exit);
 
   /* Explicitly create without lookup, since that tries to create a
      value with a void typed value, and when we get here, gdbarch
This page took 0.074428 seconds and 4 git commands to generate.