gdb: add inferior::{arch, set_arch}
[binutils-gdb.git] / gdb / infrun.c
index 05b150b1b63c0b9824270459a0e7ad8c30f1e30f..784f0b96ebf566d26af5ed6ee502c1283d879b85 100644 (file)
@@ -34,6 +34,7 @@
 #include "annotate.h"
 #include "symfile.h"
 #include "top.h"
+#include "ui.h"
 #include "inf-loop.h"
 #include "regcache.h"
 #include "value.h"
@@ -73,6 +74,9 @@
 #include "test-target.h"
 #include "gdbsupport/common-debug.h"
 #include "gdbsupport/buildargv.h"
+#include "extension.h"
+#include "disasm.h"
+#include "interps.h"
 
 /* Prototypes for local functions */
 
@@ -149,10 +153,29 @@ show_step_stop_if_no_debug (struct ui_file *file, int from_tty,
 }
 
 /* proceed and normal_stop use this to notify the user when the
-   inferior stopped in a different thread than it had been running
-   in.  */
+   inferior stopped in a different thread than it had been running in.
+   It can also be used to find for which thread normal_stop last
+   reported a stop.  */
+static thread_info_ref previous_thread;
 
-static ptid_t previous_inferior_ptid;
+/* See infrun.h.  */
+
+void
+update_previous_thread ()
+{
+  if (inferior_ptid == null_ptid)
+    previous_thread = nullptr;
+  else
+    previous_thread = thread_info_ref::new_reference (inferior_thread ());
+}
+
+/* See infrun.h.  */
+
+thread_info *
+get_previous_thread ()
+{
+  return previous_thread.get ();
+}
 
 /* If set (default for legacy reasons), when following a fork, GDB
    will detach from one of the fork branches, child or parent.
@@ -412,6 +435,11 @@ show_follow_fork_mode_string (struct ui_file *file, int from_tty,
 static bool
 follow_fork_inferior (bool follow_child, bool detach_fork)
 {
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
+  infrun_debug_printf ("follow_child = %d, detach_fork = %d",
+                      follow_child, detach_fork);
+
   target_waitkind fork_kind = inferior_thread ()->pending_follow.kind ();
   gdb_assert (fork_kind == TARGET_WAITKIND_FORKED
              || fork_kind == TARGET_WAITKIND_VFORKED);
@@ -477,8 +505,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
          child_inf->attach_flag = parent_inf->attach_flag;
          copy_terminal_info (child_inf, parent_inf);
-         child_inf->gdbarch = parent_inf->gdbarch;
-         copy_inferior_target_desc_info (child_inf, parent_inf);
+         child_inf->set_arch (parent_inf->arch ());
+         child_inf->tdesc_info = parent_inf->tdesc_info;
 
          child_inf->symfile_flags = SYMFILE_NO_READ;
 
@@ -520,6 +548,13 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          parent_inf->thread_waiting_for_vfork_done
            = detach_fork ? inferior_thread () : nullptr;
          parent_inf->pspace->breakpoints_not_allowed = detach_fork;
+
+         infrun_debug_printf
+           ("parent_inf->thread_waiting_for_vfork_done == %s",
+            (parent_inf->thread_waiting_for_vfork_done == nullptr
+             ? "nullptr"
+             : (parent_inf->thread_waiting_for_vfork_done
+                ->ptid.to_string ().c_str ())));
        }
     }
   else
@@ -545,8 +580,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
       child_inf->attach_flag = parent_inf->attach_flag;
       copy_terminal_info (child_inf, parent_inf);
-      child_inf->gdbarch = parent_inf->gdbarch;
-      copy_inferior_target_desc_info (child_inf, parent_inf);
+      child_inf->set_arch (parent_inf->arch ());
+      child_inf->tdesc_info = parent_inf->tdesc_info;
 
       if (has_vforked)
        {
@@ -603,6 +638,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
   target_follow_fork (child_inf, child_ptid, fork_kind, follow_child,
                      detach_fork);
 
+  gdb::observers::inferior_forked.notify (parent_inf, child_inf, fork_kind);
+
   /* target_follow_fork must leave the parent as the current inferior.  If we
      want to follow the child, we make it the current one below.  */
   gdb_assert (current_inferior () == parent_inf);
@@ -625,7 +662,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
      The former case will have pending_follow cleared, the later will have
      pending_follow set.  */
-  thread_info *parent_thread = find_thread_ptid (parent_inf, parent_ptid);
+  thread_info *parent_thread = parent_inf->find_thread (parent_ptid);
   gdb_assert (parent_thread != nullptr);
   parent_thread->pending_follow.set_spurious ();
 
@@ -673,10 +710,10 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
   if (child_inf != nullptr)
     {
       /* If FOLLOW_CHILD, we leave CHILD_INF as the current inferior
-         (do not restore the parent as the current inferior).  */
+        (do not restore the parent as the current inferior).  */
       gdb::optional<scoped_restore_current_thread> maybe_restore;
 
-      if (!follow_child)
+      if (!follow_child && !sched_multi)
        maybe_restore.emplace ();
 
       switch_to_thread (*child_inf->threads ().begin ());
@@ -686,6 +723,15 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
   return false;
 }
 
+/* Set the last target status as TP having stopped.  */
+
+static void
+set_last_target_status_stopped (thread_info *tp)
+{
+  set_last_target_status (tp->inf->process_target (), tp->ptid,
+                         target_waitstatus {}.set_stopped (GDB_SIGNAL_0));
+}
+
 /* Tell the target to follow the fork we're stopped at.  Returns true
    if the inferior should be resumed; false, if the target for some
    reason decided it's best not to resume.  */
@@ -693,6 +739,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 static bool
 follow_fork ()
 {
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
   bool follow_child = (follow_fork_mode_string == follow_fork_mode_child);
   bool should_resume = true;
 
@@ -710,32 +758,76 @@ follow_fork ()
 
   if (!non_stop)
     {
-      process_stratum_target *wait_target;
-      ptid_t wait_ptid;
-      struct target_waitstatus wait_status;
+      thread_info *cur_thr = inferior_thread ();
 
-      /* Get the last target status returned by target_wait().  */
-      get_last_target_status (&wait_target, &wait_ptid, &wait_status);
-
-      /* If not stopped at a fork event, then there's nothing else to
-        do.  */
-      if (wait_status.kind () != TARGET_WAITKIND_FORKED
-         && wait_status.kind () != TARGET_WAITKIND_VFORKED)
-       return 1;
+      ptid_t resume_ptid
+       = user_visible_resume_ptid (cur_thr->control.stepping_command);
+      process_stratum_target *resume_target
+       = user_visible_resume_target (resume_ptid);
 
-      /* Check if we switched over from WAIT_PTID, since the event was
-        reported.  */
-      if (wait_ptid != minus_one_ptid
-         && (current_inferior ()->process_target () != wait_target
-             || inferior_ptid != wait_ptid))
+      /* Check if there's a thread that we're about to resume, other
+        than the current, with an unfollowed fork/vfork.  If so,
+        switch back to it, to tell the target to follow it (in either
+        direction).  We'll afterwards refuse to resume, and inform
+        the user what happened.  */
+      for (thread_info *tp : all_non_exited_threads (resume_target,
+                                                    resume_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.  */
-         thread_info *wait_thread = find_thread_ptid (wait_target, wait_ptid);
-         switch_to_thread (wait_thread);
-         should_resume = false;
+         if (tp == cur_thr)
+           continue;
+
+         /* follow_fork_inferior clears tp->pending_follow, and below
+            we'll need the value after the follow_fork_inferior
+            call.  */
+         target_waitkind kind = tp->pending_follow.kind ();
+
+         if (kind != TARGET_WAITKIND_SPURIOUS)
+           {
+             infrun_debug_printf ("need to follow-fork [%s] first",
+                                  tp->ptid.to_string ().c_str ());
+
+             switch_to_thread (tp);
+
+             /* Set up inferior(s) as specified by the caller, and
+                tell the target to do whatever is necessary to follow
+                either parent or child.  */
+             if (follow_child)
+               {
+                 /* The thread that started the execution command
+                    won't exist in the child.  Abort the command and
+                    immediately stop in this thread, in the child,
+                    inside fork.  */
+                 should_resume = false;
+               }
+             else
+               {
+                 /* Following the parent, so let the thread fork its
+                    child freely, it won't influence the current
+                    execution command.  */
+                 if (follow_fork_inferior (follow_child, detach_fork))
+                   {
+                     /* Target refused to follow, or there's some
+                        other reason we shouldn't resume.  */
+                     switch_to_thread (cur_thr);
+                     set_last_target_status_stopped (cur_thr);
+                     return false;
+                   }
+
+                 /* If we're following a vfork, when we need to leave
+                    the just-forked thread as selected, as we need to
+                    solo-resume it to collect the VFORK_DONE event.
+                    If we're following a fork, however, switch back
+                    to the original thread that we continue stepping
+                    it, etc.  */
+                 if (kind != TARGET_WAITKIND_VFORKED)
+                   {
+                     gdb_assert (kind == TARGET_WAITKIND_FORKED);
+                     switch_to_thread (cur_thr);
+                   }
+               }
+
+             break;
+           }
        }
     }
 
@@ -799,21 +891,16 @@ follow_fork ()
          }
        else
          {
-           /* This makes sure we don't try to apply the "Switched
-              over from WAIT_PID" logic above.  */
-           nullify_last_target_wait_ptid ();
-
            /* If we followed the child, switch to it...  */
            if (follow_child)
              {
-               thread_info *child_thr = find_thread_ptid (parent_targ, child);
-               switch_to_thread (child_thr);
+               tp = parent_targ->find_thread (child);
+               switch_to_thread (tp);
 
                /* ... and preserve the stepping state, in case the
                   user was stepping over the fork call.  */
                if (should_resume)
                  {
-                   tp = inferior_thread ();
                    tp->control.step_resume_breakpoint
                      = step_resume_breakpoint;
                    tp->control.step_range_start = step_range_start;
@@ -852,6 +939,8 @@ follow_fork ()
       break;
     }
 
+  if (!should_resume)
+    set_last_target_status_stopped (tp);
   return should_resume;
 }
 
@@ -876,14 +965,14 @@ follow_inferior_reset_breakpoints (void)
   if (tp->control.step_resume_breakpoint)
     {
       breakpoint_re_set_thread (tp->control.step_resume_breakpoint);
-      tp->control.step_resume_breakpoint->loc->enabled = 1;
+      tp->control.step_resume_breakpoint->first_loc ().enabled = 1;
     }
 
   /* Treat exception_resume breakpoints like step_resume breakpoints.  */
   if (tp->control.exception_resume_breakpoint)
     {
       breakpoint_re_set_thread (tp->control.exception_resume_breakpoint);
-      tp->control.exception_resume_breakpoint->loc->enabled = 1;
+      tp->control.exception_resume_breakpoint->first_loc ().enabled = 1;
     }
 
   /* Reinsert all breakpoints in the child.  The user may have set
@@ -921,6 +1010,8 @@ proceed_after_vfork_done (thread_info *thread)
 static void
 handle_vfork_child_exec_or_exit (int exec)
 {
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
   struct inferior *inf = current_inferior ();
 
   if (inf->vfork_parent)
@@ -1052,6 +1143,8 @@ handle_vfork_child_exec_or_exit (int exec)
 static void
 handle_vfork_done (thread_info *event_thread)
 {
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
   /* We only care about this event if inferior::thread_waiting_for_vfork_done is
      set, that is if we are waiting for a vfork child not under our control
      (because we detached it) to exec or exit.
@@ -1067,8 +1160,6 @@ handle_vfork_done (thread_info *event_thread)
       return;
     }
 
-  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
-
   /* We stopped all threads (other than the vforking thread) of the inferior in
      follow_fork and kept them stopped until now.  It should therefore not be
      possible for another thread to have reported a vfork during that window.
@@ -1222,7 +1313,8 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
      previous incarnation of this process.  */
   no_shared_libraries (nullptr, 0);
 
-  struct inferior *inf = current_inferior ();
+  inferior *execing_inferior = current_inferior ();
+  inferior *following_inferior;
 
   if (follow_exec_mode_string == follow_exec_mode_new)
     {
@@ -1233,19 +1325,19 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
         inferior's pid.  Having two inferiors with the same pid would confuse
         find_inferior_p(t)id.  Transfer the terminal state and info from the
          old to the new inferior.  */
-      inferior *new_inferior = add_inferior_with_spaces ();
+      following_inferior = add_inferior_with_spaces ();
 
-      swap_terminal_info (new_inferior, inf);
-      exit_inferior_silent (inf);
+      swap_terminal_info (following_inferior, execing_inferior);
+      exit_inferior (execing_inferior);
 
-      new_inferior->pid = pid;
-      target_follow_exec (new_inferior, ptid, exec_file_target);
-
-      /* We continue with the new inferior.  */
-      inf = new_inferior;
+      following_inferior->pid = pid;
     }
   else
     {
+      /* follow-exec-mode is "same", we continue execution in the execing
+        inferior.  */
+      following_inferior = execing_inferior;
+
       /* The old description may no longer be fit for the new image.
         E.g, a 64-bit process exec'ed a 32-bit process.  Clear the
         old description; we'll read a new one below.  No need to do
@@ -1253,18 +1345,20 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
         around (its description is later cleared/refetched on
         restart).  */
       target_clear_description ();
-      target_follow_exec (inf, ptid, exec_file_target);
     }
 
-  gdb_assert (current_inferior () == inf);
-  gdb_assert (current_program_space == inf->pspace);
+  target_follow_exec (following_inferior, ptid, exec_file_target);
+
+  gdb_assert (current_inferior () == following_inferior);
+  gdb_assert (current_program_space == following_inferior->pspace);
 
   /* Attempt to open the exec file.  SYMFILE_DEFER_BP_RESET is used
      because the proper displacement for a PIE (Position Independent
      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.get (), inf, SYMFILE_DEFER_BP_RESET);
+  try_open_exec_file (exec_file_host.get (), following_inferior,
+                     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
@@ -1274,7 +1368,7 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
      registers.  */
   target_find_description ();
 
-  gdb::observers::inferior_execd.notify (inf);
+  gdb::observers::inferior_execd.notify (execing_inferior, following_inferior);
 
   breakpoint_re_set ();
 
@@ -1551,15 +1645,15 @@ infrun_inferior_exit (struct inferior *inf)
 }
 
 static void
-infrun_inferior_execd (inferior *inf)
+infrun_inferior_execd (inferior *exec_inf, inferior *follow_inf)
 {
   /* If some threads where was doing a displaced step in this inferior at the
      moment of the exec, they no longer exist.  Even if the exec'ing thread
      doing a displaced step, we don't want to to any fixup nor restore displaced
      stepping buffer bytes.  */
-  inf->displaced_step_state.reset ();
+  follow_inf->displaced_step_state.reset ();
 
-  for (thread_info *thread : inf->threads ())
+  for (thread_info *thread : follow_inf->threads ())
     thread->displaced_step_state.reset ();
 
   /* Since an in-line step is done with everything else stopped, if there was
@@ -1567,7 +1661,7 @@ infrun_inferior_execd (inferior *inf)
      thread.  */
   clear_step_over_info ();
 
-  inf->thread_waiting_for_vfork_done = nullptr;
+  follow_inf->thread_waiting_for_vfork_done = nullptr;
 }
 
 /* If ON, and the architecture supports it, GDB will use displaced
@@ -1654,24 +1748,6 @@ displaced_step_reset (displaced_step_thread_state *displaced)
 
 using displaced_step_reset_cleanup = FORWARD_SCOPE_EXIT (displaced_step_reset);
 
-/* See infrun.h.  */
-
-std::string
-displaced_step_dump_bytes (const gdb_byte *buf, size_t len)
-{
-  std::string ret;
-
-  for (size_t i = 0; i < len; i++)
-    {
-      if (i == 0)
-       ret += string_printf ("%02x", buf[i]);
-      else
-       ret += string_printf (" %02x", buf[i]);
-    }
-
-  return ret;
-}
-
 /* Prepare to single-step, using displaced stepping.
 
    Note that we cannot use displaced stepping when we have a signal to
@@ -1737,6 +1813,30 @@ displaced_step_prepare_throw (thread_info *tp)
   CORE_ADDR original_pc = regcache_read_pc (regcache);
   CORE_ADDR displaced_pc;
 
+  /* Display the instruction we are going to displaced step.  */
+  if (debug_displaced)
+    {
+      string_file tmp_stream;
+      int dislen = gdb_print_insn (gdbarch, original_pc, &tmp_stream,
+                                  nullptr);
+
+      if (dislen > 0)
+       {
+         gdb::byte_vector insn_buf (dislen);
+         read_memory (original_pc, insn_buf.data (), insn_buf.size ());
+
+         std::string insn_bytes = bytes_to_string (insn_buf);
+
+         displaced_debug_printf ("original insn %s: %s \t %s",
+                                 paddress (gdbarch, original_pc),
+                                 insn_bytes.c_str (),
+                                 tmp_stream.string ().c_str ());
+       }
+      else
+       displaced_debug_printf ("original insn %s: invalid length: %d",
+                               paddress (gdbarch, original_pc), dislen);
+    }
+
   displaced_step_prepare_status status
     = gdbarch_displaced_step_prepare (gdbarch, tp, displaced_pc);
 
@@ -1775,6 +1875,47 @@ displaced_step_prepare_throw (thread_info *tp)
                          paddress (gdbarch, original_pc),
                          paddress (gdbarch, displaced_pc));
 
+  /* Display the new displaced instruction(s).  */
+  if (debug_displaced)
+    {
+      string_file tmp_stream;
+      CORE_ADDR addr = displaced_pc;
+
+      /* If displaced stepping is going to use h/w single step then we know
+        that the replacement instruction can only be a single instruction,
+        in that case set the end address at the next byte.
+
+        Otherwise the displaced stepping copy instruction routine could
+        have generated multiple instructions, and all we know is that they
+        must fit within the LEN bytes of the buffer.  */
+      CORE_ADDR end
+       = addr + (gdbarch_displaced_step_hw_singlestep (gdbarch)
+                 ? 1 : gdbarch_displaced_step_buffer_length (gdbarch));
+
+      while (addr < end)
+       {
+         int dislen = gdb_print_insn (gdbarch, addr, &tmp_stream, nullptr);
+         if (dislen <= 0)
+           {
+             displaced_debug_printf
+               ("replacement insn %s: invalid length: %d",
+                paddress (gdbarch, addr), dislen);
+             break;
+           }
+
+         gdb::byte_vector insn_buf (dislen);
+         read_memory (addr, insn_buf.data (), insn_buf.size ());
+
+         std::string insn_bytes = bytes_to_string (insn_buf);
+         std::string insn_str = tmp_stream.release ();
+         displaced_debug_printf ("replacement insn %s: %s \t %s",
+                                 paddress (gdbarch, addr),
+                                 insn_bytes.c_str (),
+                                 insn_str.c_str ());
+         addr += dislen;
+       }
+    }
+
   return DISPLACED_STEP_PREPARE_STATUS_OK;
 }
 
@@ -1825,7 +1966,8 @@ displaced_step_prepare (thread_info *thread)
    DISPLACED_STEP_FINISH_STATUS_OK as well.  */
 
 static displaced_step_finish_status
-displaced_step_finish (thread_info *event_thread, enum gdb_signal signal)
+displaced_step_finish (thread_info *event_thread,
+                      const target_waitstatus &event_status)
 {
   displaced_step_thread_state *displaced = &event_thread->displaced_step_state;
 
@@ -1847,7 +1989,7 @@ displaced_step_finish (thread_info *event_thread, enum gdb_signal signal)
   /* Do the fixup, and release the resources acquired to do the displaced
      step. */
   return gdbarch_displaced_step_finish (displaced->get_original_gdbarch (),
-                                       event_thread, signal);
+                                       event_thread, event_status);
 }
 
 /* Data to be passed around while handling an event.  This data is
@@ -1868,6 +2010,7 @@ struct execution_control_state
 
   struct target_waitstatus ws;
   int stop_func_filled_in = 0;
+  CORE_ADDR stop_func_alt_start = 0;
   CORE_ADDR stop_func_start = 0;
   CORE_ADDR stop_func_end = 0;
   const char *stop_func_name = nullptr;
@@ -2174,6 +2317,29 @@ user_visible_resume_target (ptid_t resume_ptid)
          : current_inferior ()->process_target ());
 }
 
+/* Find a thread from the inferiors that we'll resume that is waiting
+   for a vfork-done event.  */
+
+static thread_info *
+find_thread_waiting_for_vfork_done ()
+{
+  gdb_assert (!target_is_non_stop_p ());
+
+  if (sched_multi)
+    {
+      for (inferior *inf : all_non_exited_inferiors ())
+       if (inf->thread_waiting_for_vfork_done != nullptr)
+         return inf->thread_waiting_for_vfork_done;
+    }
+  else
+    {
+      inferior *cur_inf = current_inferior ();
+      if (cur_inf->thread_waiting_for_vfork_done != nullptr)
+       return cur_inf->thread_waiting_for_vfork_done;
+    }
+  return nullptr;
+}
+
 /* Return a ptid representing the set of threads that we will resume,
    in the perspective of the target, assuming run control handling
    does not require leaving some threads stopped (e.g., stepping past
@@ -2214,14 +2380,18 @@ internal_resume_ptid (int user_step)
      Since we don't have that flexibility (we can only pass one ptid), just
      resume the first thread waiting for a vfork-done event we find (e.g. thread
      2.1).  */
-  if (sched_multi)
+  thread_info *thr = find_thread_waiting_for_vfork_done ();
+  if (thr != nullptr)
     {
-      for (inferior *inf : all_non_exited_inferiors ())
-       if (inf->thread_waiting_for_vfork_done != nullptr)
-         return inf->thread_waiting_for_vfork_done->ptid;
+      /* If we have a thread that is waiting for a vfork-done event,
+        then we should have switched to it earlier.  Calling
+        target_resume with thread scope is only possible when the
+        current thread matches the thread scope.  */
+      gdb_assert (thr->ptid == inferior_ptid);
+      gdb_assert (thr->inf->process_target ()
+                 == inferior_thread ()->inf->process_target ());
+      return thr->ptid;
     }
-  else if (current_inferior ()->thread_waiting_for_vfork_done != nullptr)
-    return current_inferior ()->thread_waiting_for_vfork_done->ptid;
 
   return user_visible_resume_ptid (user_step);
 }
@@ -2398,7 +2568,8 @@ resume_1 (enum gdb_signal sig)
                 user breakpoints at PC to trigger (again) when this
                 hits.  */
              insert_hp_step_resume_breakpoint_at_frame (get_current_frame ());
-             gdb_assert (tp->control.step_resume_breakpoint->loc->permanent);
+             gdb_assert (tp->control.step_resume_breakpoint->first_loc ()
+                         .permanent);
 
              tp->step_after_step_resume_breakpoint = step;
            }
@@ -2613,23 +2784,6 @@ resume_1 (enum gdb_signal sig)
        step = false;
     }
 
-  if (debug_displaced
-      && tp->control.trap_expected
-      && use_displaced_stepping (tp)
-      && !step_over_info_valid_p ())
-    {
-      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];
-
-      read_memory (actual_pc, buf, sizeof (buf));
-      displaced_debug_printf ("run %s: %s",
-                             paddress (resume_gdbarch, actual_pc),
-                             displaced_step_dump_bytes
-                               (buf, sizeof (buf)).c_str ());
-    }
-
   if (tp->control.may_range_step)
     {
       /* If we're resuming a thread with the PC out of the step
@@ -2748,12 +2902,24 @@ clear_proceed_status_thread (struct thread_info *tp)
 
   tp->control.stop_step = 0;
 
+  tp->control.proceed_to_finish = 0;
+
   tp->control.stepping_command = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
   bpstat_clear (&tp->control.stop_bpstat);
 }
 
+/* Notify the current interpreter and observers that the target is about to
+   proceed.  */
+
+static void
+notify_about_to_proceed ()
+{
+  top_level_interpreter ()->on_about_to_proceed ();
+  gdb::observers::about_to_proceed.notify ();
+}
+
 void
 clear_proceed_status (int step)
 {
@@ -2796,7 +2962,7 @@ clear_proceed_status (int step)
       inferior->control.stop_soon = NO_STOP_QUIETLY;
     }
 
-  gdb::observers::about_to_proceed.notify ();
+  notify_about_to_proceed ();
 }
 
 /* Returns true if TP is still stopped at a breakpoint that needs
@@ -2990,7 +3156,7 @@ scoped_disable_commit_resumed::reset ()
   if (m_prev_enable_commit_resumed)
     {
       /* This is the outermost instance, re-enable
-         COMMIT_RESUMED_STATE on the targets where it's possible.  */
+        COMMIT_RESUMED_STATE on the targets where it's possible.  */
       maybe_set_commit_resumed_all_targets ();
     }
   else
@@ -3118,6 +3284,105 @@ check_multi_target_resumption (process_stratum_target *resume_target)
     }
 }
 
+/* Helper function for `proceed`.  Check if thread TP is suitable for
+   resuming, and, if it is, switch to the thread and call
+   `keep_going_pass_signal`.  If TP is not suitable for resuming then this
+   function will just return without switching threads.  */
+
+static void
+proceed_resume_thread_checked (thread_info *tp)
+{
+  if (!tp->inf->has_execution ())
+    {
+      infrun_debug_printf ("[%s] target has no execution",
+                          tp->ptid.to_string ().c_str ());
+      return;
+    }
+
+  if (tp->resumed ())
+    {
+      infrun_debug_printf ("[%s] resumed",
+                          tp->ptid.to_string ().c_str ());
+      gdb_assert (tp->executing () || tp->has_pending_waitstatus ());
+      return;
+    }
+
+  if (thread_is_in_step_over_chain (tp))
+    {
+      infrun_debug_printf ("[%s] needs step-over",
+                          tp->ptid.to_string ().c_str ());
+      return;
+    }
+
+  /* When handling a vfork GDB removes all breakpoints from the program
+     space in which the vfork is being handled.  If we are following the
+     parent then GDB will set the thread_waiting_for_vfork_done member of
+     the parent inferior.  In this case we should take care to only resume
+     the vfork parent thread, the kernel will hold this thread suspended
+     until the vfork child has exited or execd, at which point the parent
+     will be resumed and a VFORK_DONE event sent to GDB.  */
+  if (tp->inf->thread_waiting_for_vfork_done != nullptr)
+    {
+      if (target_is_non_stop_p ())
+       {
+         /* For non-stop targets, regardless of whether GDB is using
+            all-stop or non-stop mode, threads are controlled
+            individually.
+
+            When a thread is handling a vfork, breakpoints are removed
+            from the inferior (well, program space in fact), so it is
+            critical that we don't try to resume any thread other than the
+            vfork parent.  */
+         if (tp != tp->inf->thread_waiting_for_vfork_done)
+           {
+             infrun_debug_printf ("[%s] thread %s of this inferior is "
+                                  "waiting for vfork-done",
+                                  tp->ptid.to_string ().c_str (),
+                                  tp->inf->thread_waiting_for_vfork_done
+                                    ->ptid.to_string ().c_str ());
+             return;
+           }
+       }
+      else
+       {
+         /* For all-stop targets, when we attempt to resume the inferior,
+            we will only resume the vfork parent thread, this is handled
+            in internal_resume_ptid.
+
+            Additionally, we will always be called with the vfork parent
+            thread as the current thread (TP) thanks to follow_fork, as
+            such the following assertion should hold.
+
+            Beyond this there is nothing more that needs to be done
+            here.  */
+         gdb_assert (tp == tp->inf->thread_waiting_for_vfork_done);
+       }
+    }
+
+  /* When handling a vfork GDB removes all breakpoints from the program
+     space in which the vfork is being handled.  If we are following the
+     child then GDB will set vfork_child member of the vfork parent
+     inferior.  Once the child has either exited or execd then GDB will
+     detach from the parent process.  Until that point GDB should not
+     resume any thread in the parent process.  */
+  if (tp->inf->vfork_child != nullptr)
+    {
+      infrun_debug_printf ("[%s] thread is part of a vfork parent, child is %d",
+                          tp->ptid.to_string ().c_str (),
+                          tp->inf->vfork_child->pid);
+      return;
+    }
+
+  infrun_debug_printf ("resuming %s",
+                      tp->ptid.to_string ().c_str ());
+
+  execution_control_state ecs (tp);
+  switch_to_thread (tp);
+  keep_going_pass_signal (&ecs);
+  if (!ecs.wait_some_more)
+    error (_("Command aborted."));
+}
+
 /* Basic routine for continuing the program in various fashions.
 
    ADDR is the address to resume at, or -1 for resume where stopped.
@@ -3135,8 +3400,10 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   struct gdbarch *gdbarch;
   CORE_ADDR pc;
 
-  /* If we're stopped at a fork/vfork, follow the branch set by the
-     "set follow-fork-mode" command; otherwise, we'll just proceed
+  /* If we're stopped at a fork/vfork, switch to either the parent or child
+     thread as defined by the "set follow-fork-mode" command, or, if both
+     the parent and child are controlled by GDB, and schedule-multiple is
+     on, follow the child.  If none of the above apply then we just proceed
      resuming the current thread.  */
   if (!follow_fork ())
     {
@@ -3148,7 +3415,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
     }
 
   /* We'll update this if & when we switch to a new thread.  */
-  previous_inferior_ptid = inferior_ptid;
+  update_previous_thread ();
 
   regcache = get_current_regcache ();
   gdbarch = regcache->arch ();
@@ -3158,6 +3425,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 
   thread_info *cur_thr = inferior_thread ();
 
+  infrun_debug_printf ("cur_thr = %s", cur_thr->ptid.to_string ().c_str ());
+
   /* Fill in with reasonable starting values.  */
   init_thread_stepping_state (cur_thr);
 
@@ -3214,8 +3483,10 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   if (!cur_thr->control.in_infcall)
     set_running (resume_target, resume_ptid, true);
 
-  infrun_debug_printf ("addr=%s, signal=%s", paddress (gdbarch, addr),
-                      gdb_signal_to_symbol_string (siggnal));
+  infrun_debug_printf ("addr=%s, signal=%s, resume_ptid=%s",
+                      paddress (gdbarch, addr),
+                      gdb_signal_to_symbol_string (siggnal),
+                      resume_ptid.to_string ().c_str ());
 
   annotate_starting ();
 
@@ -3306,67 +3577,11 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
                                                       resume_ptid))
          {
            switch_to_thread_no_regs (tp);
-
-           if (!tp->inf->has_execution ())
-             {
-               infrun_debug_printf ("[%s] target has no execution",
-                                    tp->ptid.to_string ().c_str ());
-               continue;
-             }
-
-           if (tp->resumed ())
-             {
-               infrun_debug_printf ("[%s] resumed",
-                                    tp->ptid.to_string ().c_str ());
-               gdb_assert (tp->executing () || tp->has_pending_waitstatus ());
-               continue;
-             }
-
-           if (thread_is_in_step_over_chain (tp))
-             {
-               infrun_debug_printf ("[%s] needs step-over",
-                                    tp->ptid.to_string ().c_str ());
-               continue;
-             }
-
-           /* If a thread of that inferior is waiting for a vfork-done
-              (for a detached vfork child to exec or exit), breakpoints are
-              removed.  We must not resume any thread of that inferior, other
-              than the one waiting for the vfork-done.  */
-           if (tp->inf->thread_waiting_for_vfork_done != nullptr
-               && tp != tp->inf->thread_waiting_for_vfork_done)
-             {
-               infrun_debug_printf ("[%s] another thread of this inferior is "
-                                    "waiting for vfork-done",
-                                    tp->ptid.to_string ().c_str ());
-               continue;
-             }
-
-           infrun_debug_printf ("resuming %s",
-                                tp->ptid.to_string ().c_str ());
-
-           execution_control_state ecs (tp);
-           switch_to_thread (tp);
-           keep_going_pass_signal (&ecs);
-           if (!ecs.wait_some_more)
-             error (_("Command aborted."));
+           proceed_resume_thread_checked (tp);
          }
       }
-    else if (!cur_thr->resumed ()
-            && !thread_is_in_step_over_chain (cur_thr)
-            /* In non-stop, forbid resuming a thread if some other thread of
-               that inferior is waiting for a vfork-done event (this means
-               breakpoints are out for this inferior).  */
-            && !(non_stop
-                 && cur_thr->inf->thread_waiting_for_vfork_done != nullptr))
-      {
-       /* The thread wasn't started, and isn't queued, run it now.  */
-       execution_control_state ecs (cur_thr);
-       switch_to_thread (cur_thr);
-       keep_going_pass_signal (&ecs);
-       if (!ecs.wait_some_more)
-         error (_("Command aborted."));
-      }
+    else
+      proceed_resume_thread_checked (cur_thr);
 
     disable_commit_resumed.reset_and_commit ();
   }
@@ -3431,7 +3646,7 @@ init_wait_for_inferior (void)
 
   nullify_last_target_wait_ptid ();
 
-  previous_inferior_ptid = inferior_ptid;
+  update_previous_thread ();
 }
 
 \f
@@ -3507,14 +3722,6 @@ infrun_thread_stop_requested (ptid_t ptid)
     }
 }
 
-static void
-infrun_thread_thread_exit (struct thread_info *tp, int silent)
-{
-  if (target_last_proc_target == tp->inf->process_target ()
-      && target_last_wait_ptid == tp->ptid)
-    nullify_last_target_wait_ptid ();
-}
-
 /* Delete the step resume, single-step and longjmp/exception resume
    breakpoints of TP.  */
 
@@ -3637,7 +3844,7 @@ do_target_wait_1 (inferior *inf, ptid_t ptid,
                           ptid.to_string ().c_str ());
 
       /* We have a specific thread to check.  */
-      tp = find_thread_ptid (inf, ptid);
+      tp = inf->find_thread (ptid);
       gdb_assert (tp != nullptr);
       if (!tp->has_pending_waitstatus ())
        tp = nullptr;
@@ -4075,7 +4282,7 @@ check_curr_ui_sync_execution_done (void)
       && !gdb_in_secondary_prompt_p (ui))
     {
       target_terminal::ours ();
-      gdb::observers::sync_execution_done.notify ();
+      top_level_interpreter ()->on_sync_execution_done ();
       ui->register_file_handler ();
     }
 }
@@ -4103,6 +4310,44 @@ all_uis_on_sync_execution_starting (void)
     }
 }
 
+/* A quit_handler callback installed while we're handling inferior
+   events.  */
+
+static void
+infrun_quit_handler ()
+{
+  if (target_terminal::is_ours ())
+    {
+      /* Do nothing.
+
+        default_quit_handler would throw a quit in this case, but if
+        we're handling an event while we have the terminal, it means
+        the target is running a background execution command, and
+        thus when users press Ctrl-C, they're wanting to interrupt
+        whatever command they were executing in the command line.
+        E.g.:
+
+         (gdb) c&
+         (gdb) foo bar whatever<ctrl-c>
+
+        That Ctrl-C should clear the input line, not interrupt event
+        handling if it happens that the user types Ctrl-C at just the
+        "wrong" time!
+
+        It's as-if background event handling was handled by a
+        separate background thread.
+
+        To be clear, the Ctrl-C is not lost -- it will be processed
+        by the next QUIT call once we're out of fetch_inferior_event
+        again.  */
+    }
+  else
+    {
+      if (check_quit_flag ())
+       target_pass_ctrlc ();
+    }
+}
+
 /* Asynchronous version of wait_for_inferior.  It is called by the
    event loop whenever a change of state is detected on the file
    descriptor corresponding to the target.  It can be called more than
@@ -4131,6 +4376,21 @@ fetch_inferior_event ()
   scoped_restore save_pagination
     = make_scoped_restore (&pagination_enabled, false);
 
+  /* Install a quit handler that does nothing if we have the terminal
+     (meaning the target is running a background execution command),
+     so that Ctrl-C never interrupts GDB before the event is fully
+     handled.  */
+  scoped_restore restore_quit_handler
+    = make_scoped_restore (&quit_handler, infrun_quit_handler);
+
+  /* Make sure a SIGINT does not interrupt an extension language while
+     we're handling an event.  That could interrupt a Python unwinder
+     or a Python observer or some such.  A Ctrl-C should either be
+     forwarded to the inferior if the inferior has the terminal, or,
+     if GDB has the terminal, should interrupt the command the user is
+     typing in the CLI.  */
+  scoped_disable_cooperative_sigint_handling restore_coop_sigint;
+
   /* End up with readline processing input, if necessary.  */
   {
     SCOPE_EXIT { reinstall_readline_callback_handler_cleanup (); };
@@ -4176,9 +4436,13 @@ fetch_inferior_event ()
 
     gdb_assert (ecs.ws.kind () != TARGET_WAITKIND_IGNORE);
 
-    /* Switch to the target that generated the event, so we can do
-       target calls.  */
-    switch_to_target_no_thread (ecs.target);
+    /* Switch to the inferior that generated the event, so we can do
+       target calls.  If the event was not associated to a ptid,  */
+    if (ecs.ptid != null_ptid
+       && ecs.ptid != minus_one_ptid)
+      switch_to_inferior_no_thread (find_inferior_ptid (ecs.target, ecs.ptid));
+    else
+      switch_to_target_no_thread (ecs.target);
 
     if (debug_infrun)
       print_target_wait_results (minus_one_ptid, ecs.ptid, ecs.ws);
@@ -4196,6 +4460,8 @@ fetch_inferior_event ()
     auto defer_delete_threads
       = make_scope_exit (delete_just_stopped_threads_infrun_breakpoints);
 
+    int stop_id = get_stop_id ();
+
     /* Now figure out what to do with the result of the result.  */
     handle_inferior_event (&ecs);
 
@@ -4223,7 +4489,19 @@ fetch_inferior_event ()
 
            clean_up_just_stopped_threads_fsms (&ecs);
 
-           if (thr != nullptr && thr->thread_fsm () != nullptr)
+           if (stop_id != get_stop_id ())
+             {
+               /* If the stop-id has changed then a stop has already been
+                  presented to the user in handle_inferior_event, this is
+                  likely a failed inferior call.  As the stop has already
+                  been announced then we should not notify again.
+
+                  Also, if the prompt state is not PROMPT_NEEDED then GDB
+                  will not be ready for user input after this function.  */
+               should_notify_stop = false;
+               gdb_assert (current_ui->prompt_state == PROMPT_NEEDED);
+             }
+           else if (thr != nullptr && thr->thread_fsm () != nullptr)
              should_notify_stop
               = thr->thread_fsm ()->should_notify_stop ();
 
@@ -4678,6 +4956,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
          ecs->stop_func_start
            += gdbarch_deprecated_function_start_offset (gdbarch);
 
+         /* PowerPC functions have a Local Entry Point (LEP) and a Global
+            Entry Point (GEP).  There is only one Entry Point (GEP = LEP) for
+            other architectures.  */
+         ecs->stop_func_alt_start = ecs->stop_func_start;
+
          if (gdbarch_skip_entrypoint_p (gdbarch))
            ecs->stop_func_start
              = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
@@ -4934,7 +5217,7 @@ handle_one (const wait_one_event &event)
        }
       else
        {
-         t = find_thread_ptid (event.target, event.ptid);
+         t = event.target->find_thread (event.ptid);
          /* Check if this is the first time we see this thread.
             Don't bother adding if it individually exited.  */
          if (t == nullptr
@@ -4955,7 +5238,7 @@ handle_one (const wait_one_event &event)
     }
   else
     {
-      thread_info *t = find_thread_ptid (event.target, event.ptid);
+      thread_info *t = event.target->find_thread (event.ptid);
       if (t == nullptr)
        t = add_thread (event.target, event.ptid);
 
@@ -4978,7 +5261,7 @@ handle_one (const wait_one_event &event)
          /* We caught the event that we intended to catch, so
             there's no event to save as pending.  */
 
-         if (displaced_step_finish (t, GDB_SIGNAL_0)
+         if (displaced_step_finish (t, event.ws)
              == DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
            {
              /* Add it back to the step-over queue.  */
@@ -4993,7 +5276,6 @@ handle_one (const wait_one_event &event)
        }
       else
        {
-         enum gdb_signal sig;
          struct regcache *regcache;
 
          infrun_debug_printf
@@ -5004,10 +5286,7 @@ handle_one (const wait_one_event &event)
          /* Record for later.  */
          save_waitstatus (t, event.ws);
 
-         sig = (event.ws.kind () == TARGET_WAITKIND_STOPPED
-                ? event.ws.sig () : GDB_SIGNAL_0);
-
-         if (displaced_step_finish (t, sig)
+         if (displaced_step_finish (t, event.ws)
              == DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
            {
              /* Add it back to the step-over queue.  */
@@ -5360,7 +5639,7 @@ handle_inferior_event (struct execution_control_state *ecs)
   if (ecs->ws.kind () != TARGET_WAITKIND_EXITED
       && ecs->ws.kind () != TARGET_WAITKIND_SIGNALLED)
     {
-      ecs->event_thread = find_thread_ptid (ecs->target, ecs->ptid);
+      ecs->event_thread = ecs->target->find_thread (ecs->ptid);
       /* If it's a new thread, add it to the thread database.  */
       if (ecs->event_thread == nullptr)
        ecs->event_thread = add_thread (ecs->target, ecs->ptid);
@@ -5509,7 +5788,7 @@ handle_inferior_event (struct execution_control_state *ecs)
           need to have access to the just-exited thread.  That is the
           case of GNU/Linux's "checkpoint" support, for example.
           Call the switch_to_xxx routine as appropriate.  */
-       thread_info *thr = find_thread_ptid (ecs->target, ecs->ptid);
+       thread_info *thr = ecs->target->find_thread (ecs->ptid);
        if (thr != nullptr)
          switch_to_thread (thr);
        else
@@ -5538,11 +5817,11 @@ handle_inferior_event (struct execution_control_state *ecs)
          /* Support the --return-child-result option.  */
          return_child_result_value = ecs->ws.exit_status ();
 
-         gdb::observers::exited.notify (ecs->ws.exit_status ());
+         interps_notify_exited (ecs->ws.exit_status ());
        }
       else
        {
-         struct gdbarch *gdbarch = current_inferior ()->gdbarch;
+         struct gdbarch *gdbarch = current_inferior ()->arch ();
 
          if (gdbarch_gdb_signal_to_target_p (gdbarch))
            {
@@ -5565,7 +5844,7 @@ handle_inferior_event (struct execution_control_state *ecs)
                                   "signal number.");
            }
 
-         gdb::observers::signal_exited.notify (ecs->ws.sig ());
+         interps_notify_signal_exited (ecs->ws.sig ());
        }
 
       gdb_flush (gdb_stdout);
@@ -5609,7 +5888,7 @@ handle_inferior_event (struct execution_control_state *ecs)
               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_finish (ecs->event_thread, GDB_SIGNAL_TRAP);
+           displaced_step_finish (ecs->event_thread, ecs->ws);
            /* Start a new step-over in another thread if there's one
               that needs it.  */
            start_step_over ();
@@ -5622,7 +5901,7 @@ handle_inferior_event (struct execution_control_state *ecs)
               list yet at this point.  */
 
            child_regcache
-             = get_thread_arch_aspace_regcache (parent_inf->process_target (),
+             = get_thread_arch_aspace_regcache (parent_inf,
                                                 ecs->ws.child_ptid (),
                                                 gdbarch,
                                                 parent_inf->aspace);
@@ -5696,7 +5975,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          /* Note that one of these may be an invalid pointer,
             depending on detach_fork.  */
          thread_info *parent = ecs->event_thread;
-         thread_info *child = find_thread_ptid (targ, ecs->ws.child_ptid ());
+         thread_info *child = targ->find_thread (ecs->ws.child_ptid ());
 
          /* At this point, the parent is marked running, and the
             child is marked stopped.  */
@@ -5734,7 +6013,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          if (should_resume)
            {
              /* Never call switch_back_to_stepped_thread if we are waiting for
-                vfork-done (waiting for an external vfork child to exec or
+                vfork-done (waiting for an external vfork child to exec or
                 exit).  We will resume only the vforking thread for the purpose
                 of collecting the vfork-done event, and we will restart any
                 step once the critical shared address space window is done.  */
@@ -5849,7 +6128,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       if (handle_stop_requested (ecs))
        return;
 
-      gdb::observers::no_history.notify ();
+      interps_notify_no_history ();
       stop_waiting (ecs);
       return;
     }
@@ -5974,7 +6253,7 @@ resumed_thread_with_pending_status (struct thread_info *tp,
 static int
 finish_step_over (struct execution_control_state *ecs)
 {
-  displaced_step_finish (ecs->event_thread, ecs->event_thread->stop_signal ());
+  displaced_step_finish (ecs->event_thread, ecs->ws);
 
   bool had_step_over_info = step_over_info_valid_p ();
 
@@ -6075,6 +6354,32 @@ finish_step_over (struct execution_control_state *ecs)
   return 0;
 }
 
+/* See infrun.h.  */
+
+void
+notify_signal_received (gdb_signal sig)
+{
+  interps_notify_signal_received (sig);
+  gdb::observers::signal_received.notify (sig);
+}
+
+/* See infrun.h.  */
+
+void
+notify_normal_stop (bpstat *bs, int print_frame)
+{
+  interps_notify_normal_stop (bs, print_frame);
+  gdb::observers::normal_stop.notify (bs, print_frame);
+}
+
+/* See infrun.h.  */
+
+void notify_user_selected_context_changed (user_selected_what selection)
+{
+  interps_notify_user_selected_context_changed (selection);
+  gdb::observers::user_selected_context_changed.notify (selection);
+}
+
 /* Come here when the program has stopped with a signal.  */
 
 static void
@@ -6498,7 +6803,7 @@ handle_signal_stop (struct execution_control_state *ecs)
        {
          /* The signal table tells us to print about this signal.  */
          target_terminal::ours_for_output ();
-         gdb::observers::signal_received.notify (ecs->event_thread->stop_signal ());
+         notify_signal_received (ecs->event_thread->stop_signal ());
          target_terminal::inferior ();
        }
 
@@ -6735,27 +7040,31 @@ process_event_stop_test (struct execution_control_state *ecs)
 
     case BPSTAT_WHAT_STEP_RESUME:
       infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
-      delete_step_resume_breakpoint (ecs->event_thread);
-      fill_in_stop_func (gdbarch, ecs);
 
-      if (execution_direction == EXEC_REVERSE)
+      delete_step_resume_breakpoint (ecs->event_thread);
+      if (ecs->event_thread->control.proceed_to_finish
+         && execution_direction == EXEC_REVERSE)
        {
          struct thread_info *tp = ecs->event_thread;
-         /* We are finishing a function in reverse or stepping over a function
-            call in reverse, and just hit the step-resume breakpoint at the
-            start address of the function, and we're almost there -- just need
-            to back up to the function call.  */
-
-         stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
 
-         /* When setting a step range, need to call set_step_info
-            to setup the current_line/symtab fields as well.  */
-         set_step_info (tp, frame, stop_pc_sal);
-
-         /* Return using a step range so we will keep stepping back to the
-            first instruction in the source code line.  */
-         tp->control.step_range_start = ecs->stop_func_start;
-         tp->control.step_range_end = ecs->stop_func_start;
+         /* We are finishing a function in reverse, and just hit the
+            step-resume breakpoint at the start address of the
+            function, and we're almost there -- just need to back up
+            by one more single-step, which should take us back to the
+            function call.  */
+         tp->control.step_range_start = tp->control.step_range_end = 1;
+         keep_going (ecs);
+         return;
+       }
+      fill_in_stop_func (gdbarch, ecs);
+      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
+         && execution_direction == EXEC_REVERSE)
+       {
+         /* We are stepping over a function call in reverse, and just
+            hit the step-resume breakpoint at the start address of
+            the function.  Go back to single-stepping, which should
+            take us back to the function call.  */
+         ecs->event_thread->stepping_over_breakpoint = 1;
          keep_going (ecs);
          return;
        }
@@ -6816,9 +7125,9 @@ process_event_stop_test (struct execution_control_state *ecs)
        = ecs->event_thread->control.step_resume_breakpoint;
 
       if (sr_bp != nullptr
-         && sr_bp->loc->permanent
+         && sr_bp->first_loc ().permanent
          && sr_bp->type == bp_hp_step_resume
-         && sr_bp->loc->address == ecs->event_thread->prev_pc)
+         && sr_bp->first_loc ().address == ecs->event_thread->prev_pc)
        {
          infrun_debug_printf ("stepped permanent breakpoint, stopped in handler");
          delete_step_resume_breakpoint (ecs->event_thread);
@@ -7263,6 +7572,24 @@ process_event_stop_test (struct execution_control_state *ecs)
        }
     }
 
+  if (execution_direction == EXEC_REVERSE
+      && ecs->event_thread->control.proceed_to_finish
+      && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
+      && ecs->event_thread->stop_pc () < ecs->stop_func_start)
+    {
+      /* We are executing the reverse-finish command.
+        If the system supports multiple entry points and we are finishing a
+        function in reverse.   If we are between the entry points single-step
+        back to the alternate entry point.  If we are at the alternate entry
+        point -- just   need to back up by one more single-step, which
+        should take us back to the function call.  */
+      ecs->event_thread->control.step_range_start
+       = ecs->event_thread->control.step_range_end = 1;
+      keep_going (ecs);
+      return;
+
+    }
+
   if (ecs->event_thread->control.step_range_end == 1)
     {
       /* It is stepi or nexti.  We always want to stop stepping after
@@ -7370,7 +7697,7 @@ process_event_stop_test (struct execution_control_state *ecs)
          return;
        }
       else if (get_frame_id (get_current_frame ())
-               == ecs->event_thread->control.step_frame_id)
+              == ecs->event_thread->control.step_frame_id)
        {
          /* We are not at the start of a statement, and we have not changed
             frame.
@@ -7983,13 +8310,16 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
                                        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))
+      if (! value->optimized_out ())
        {
          handler = value_as_address (value);
 
          infrun_debug_printf ("exception resume at %lx",
                               (unsigned long) handler);
 
+         /* set_momentary_breakpoint_at_pc creates a thread-specific
+            breakpoint for the current inferior thread.  */
+         gdb_assert (tp == inferior_thread ());
          bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
                                               handler,
                                               bp_exception_resume).release ();
@@ -7997,8 +8327,7 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
          /* set_momentary_breakpoint_at_pc invalidates FRAME.  */
          frame = nullptr;
 
-         bp->thread = tp->global_num;
-         inferior_thread ()->control.exception_resume_breakpoint = bp;
+         tp->control.exception_resume_breakpoint = bp;
        }
     }
   catch (const gdb_exception_error &e)
@@ -8028,10 +8357,12 @@ insert_exception_resume_from_probe (struct thread_info *tp,
   infrun_debug_printf ("exception resume at %s",
                       paddress (probe->objfile->arch (), handler));
 
+  /* set_momentary_breakpoint_at_pc creates a thread-specific breakpoint
+     for the current inferior thread.  */
+  gdb_assert (tp == inferior_thread ());
   bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
                                       handler, bp_exception_resume).release ();
-  bp->thread = tp->global_num;
-  inferior_thread ()->control.exception_resume_breakpoint = bp;
+  tp->control.exception_resume_breakpoint = bp;
 }
 
 /* This is called when an exception has been intercepted.  Check to
@@ -8063,8 +8394,6 @@ check_exception_resume (struct execution_control_state *ecs,
   try
     {
       const struct block *b;
-      struct block_iterator iter;
-      struct symbol *sym;
       int argno = 0;
 
       /* The exception breakpoint is a thread-specific breakpoint on
@@ -8082,7 +8411,7 @@ check_exception_resume (struct execution_control_state *ecs,
         handler.  */
 
       b = func->value_block ();
-      ALL_BLOCK_SYMBOLS (b, iter, sym)
+      for (struct symbol *sym : block_iterator_range (b))
        {
          if (!sym->is_argument ())
            continue;
@@ -8287,18 +8616,6 @@ end_stepping_range (struct execution_control_state *ecs)
    the interpreters, through observers.  Interpreters then call these
    with whatever uiout is right.  */
 
-void
-print_end_stepping_range_reason (struct ui_out *uiout)
-{
-  /* For CLI-like interpreters, print nothing.  */
-
-  if (uiout->is_mi_like_p ())
-    {
-      uiout->field_string ("reason",
-                          async_reason_lookup (EXEC_ASYNC_END_STEPPING_RANGE));
-    }
-}
-
 void
 print_signal_exited_reason (struct ui_out *uiout, enum gdb_signal siggnal)
 {
@@ -8628,7 +8945,7 @@ normal_stop ()
   update_thread_list ();
 
   if (last.kind () == TARGET_WAITKIND_STOPPED && stopped_by_random_signal)
-    gdb::observers::signal_received.notify (inferior_thread ()->stop_signal ());
+    notify_signal_received (inferior_thread ()->stop_signal ());
 
   /* As with the notification of thread events, we want to delay
      notifying the user that we've switched thread context until
@@ -8646,21 +8963,24 @@ normal_stop ()
      the current thread back to the thread the user had selected right
      after this event is handled, so we're not really switching, only
      informing of a stop.  */
-  if (!non_stop
-      && previous_inferior_ptid != inferior_ptid
-      && target_has_execution ()
-      && last.kind () != TARGET_WAITKIND_SIGNALLED
-      && last.kind () != TARGET_WAITKIND_EXITED
-      && last.kind () != TARGET_WAITKIND_NO_RESUMED)
+  if (!non_stop)
     {
-      SWITCH_THRU_ALL_UIS ()
+      if ((last.kind () != TARGET_WAITKIND_SIGNALLED
+          && last.kind () != TARGET_WAITKIND_EXITED
+          && last.kind () != TARGET_WAITKIND_NO_RESUMED)
+         && target_has_execution ()
+         && previous_thread != inferior_thread ())
        {
-         target_terminal::ours_for_output ();
-         gdb_printf (_("[Switching to %s]\n"),
-                     target_pid_to_str (inferior_ptid).c_str ());
-         annotate_thread_changed ();
+         SWITCH_THRU_ALL_UIS ()
+           {
+             target_terminal::ours_for_output ();
+             gdb_printf (_("[Switching to %s]\n"),
+                         target_pid_to_str (inferior_ptid).c_str ());
+             annotate_thread_changed ();
+           }
        }
-      previous_inferior_ptid = inferior_ptid;
+
+      update_previous_thread ();
     }
 
   if (last.kind () == TARGET_WAITKIND_NO_RESUMED)
@@ -8726,7 +9046,7 @@ normal_stop ()
     {
       execute_cmd_pre_hook (stop_command);
     }
-  catch (const gdb_exception &ex)
+  catch (const gdb_exception_error &ex)
     {
       exception_fprintf (gdb_stderr, ex,
                         "Error while running hook_stop:\n");
@@ -8742,12 +9062,10 @@ normal_stop ()
 
   /* Notify observers about the stop.  This is where the interpreters
      print the stop event.  */
-  if (inferior_ptid != null_ptid)
-    gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat,
-                                       stop_print_frame);
-  else
-    gdb::observers::normal_stop.notify (nullptr, stop_print_frame);
-
+  notify_normal_stop ((inferior_ptid != null_ptid
+                      ? inferior_thread ()->control.stop_bpstat
+                      : nullptr),
+                     stop_print_frame);
   annotate_stopped ();
 
   if (target_has_execution ())
@@ -9137,11 +9455,11 @@ siginfo_value_read (struct value *v)
     target_read (current_inferior ()->top_target (),
                 TARGET_OBJECT_SIGNAL_INFO,
                 nullptr,
-                value_contents_all_raw (v).data (),
-                value_offset (v),
-                value_type (v)->length ());
+                v->contents_all_raw ().data (),
+                v->offset (),
+                v->type ()->length ());
 
-  if (transferred != value_type (v)->length ())
+  if (transferred != v->type ()->length ())
     error (_("Unable to read siginfo"));
 }
 
@@ -9160,11 +9478,11 @@ siginfo_value_write (struct value *v, struct value *fromval)
   transferred = target_write (current_inferior ()->top_target (),
                              TARGET_OBJECT_SIGNAL_INFO,
                              nullptr,
-                             value_contents_all_raw (fromval).data (),
-                             value_offset (v),
-                             value_type (fromval)->length ());
+                             fromval->contents_all_raw ().data (),
+                             v->offset (),
+                             fromval->type ()->length ());
 
-  if (transferred != value_type (fromval)->length ())
+  if (transferred != fromval->type ()->length ())
     error (_("Unable to write siginfo"));
 }
 
@@ -9188,10 +9506,10 @@ siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var,
     {
       struct type *type = gdbarch_get_siginfo_type (gdbarch);
 
-      return allocate_computed_value (type, &siginfo_value_funcs, nullptr);
+      return value::allocate_computed (type, &siginfo_value_funcs, nullptr);
     }
 
-  return allocate_value (builtin_type (gdbarch)->builtin_void);
+  return value::allocate (builtin_type (gdbarch)->builtin_void);
 }
 
 \f
@@ -9529,7 +9847,7 @@ namespace selftests
 static void
 infrun_thread_ptid_changed ()
 {
-  gdbarch *arch = current_inferior ()->gdbarch;
+  gdbarch *arch = current_inferior ()->arch ();
 
   /* The thread which inferior_ptid represents changes ptid.  */
   {
@@ -9866,7 +10184,6 @@ enabled by default on some platforms."),
                                              "infrun");
   gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested,
                                                "infrun");
-  gdb::observers::thread_exit.attach (infrun_thread_thread_exit, "infrun");
   gdb::observers::inferior_exit.attach (infrun_inferior_exit, "infrun");
   gdb::observers::inferior_execd.attach (infrun_inferior_execd, "infrun");