gdb: add inferior::{arch, set_arch}
[binutils-gdb.git] / gdb / infrun.c
index 5c9babb910462ac8cb4aeebf4a4c7e7a803393db..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"
@@ -74,6 +75,8 @@
 #include "gdbsupport/common-debug.h"
 #include "gdbsupport/buildargv.h"
 #include "extension.h"
+#include "disasm.h"
+#include "interps.h"
 
 /* Prototypes for local functions */
 
@@ -432,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);
@@ -497,7 +505,7 @@ 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;
+         child_inf->set_arch (parent_inf->arch ());
          child_inf->tdesc_info = parent_inf->tdesc_info;
 
          child_inf->symfile_flags = SYMFILE_NO_READ;
@@ -540,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
@@ -565,7 +580,7 @@ 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;
+      child_inf->set_arch (parent_inf->arch ());
       child_inf->tdesc_info = parent_inf->tdesc_info;
 
       if (has_vforked)
@@ -623,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);
@@ -645,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 ();
 
@@ -696,7 +713,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
         (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 ());
@@ -722,6 +739,8 @@ set_last_target_status_stopped (thread_info *tp)
 static bool
 follow_fork ()
 {
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
   bool follow_child = (follow_fork_mode_string == follow_fork_mode_child);
   bool should_resume = true;
 
@@ -875,7 +894,7 @@ follow_fork ()
            /* If we followed the child, switch to it...  */
            if (follow_child)
              {
-               tp = find_thread_ptid (parent_targ, child);
+               tp = parent_targ->find_thread (child);
                switch_to_thread (tp);
 
                /* ... and preserve the stepping state, in case the
@@ -946,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
@@ -991,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)
@@ -1122,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.
@@ -1137,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.
@@ -1292,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)
     {
@@ -1303,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
@@ -1323,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
@@ -1344,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 ();
 
@@ -1621,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
@@ -1637,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
@@ -1724,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
@@ -1807,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);
 
@@ -1845,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;
 }
 
@@ -1895,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;
 
@@ -1917,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
@@ -2496,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;
            }
@@ -2711,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
@@ -2854,6 +2910,16 @@ clear_proceed_status_thread (struct thread_info *tp)
   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)
 {
@@ -2896,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
@@ -3218,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.
@@ -3235,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 ())
     {
@@ -3258,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);
 
@@ -3314,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 ();
 
@@ -3406,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 ();
   }
@@ -3729,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;
@@ -4167,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 ();
     }
 }
@@ -4321,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);
@@ -4341,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);
 
@@ -4368,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 ();
 
@@ -5084,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
@@ -5105,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);
 
@@ -5128,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.  */
@@ -5143,7 +5276,6 @@ handle_one (const wait_one_event &event)
        }
       else
        {
-         enum gdb_signal sig;
          struct regcache *regcache;
 
          infrun_debug_printf
@@ -5154,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.  */
@@ -5510,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);
@@ -5659,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
@@ -5688,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))
            {
@@ -5715,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);
@@ -5759,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 ();
@@ -5772,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);
@@ -5846,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.  */
@@ -5999,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;
     }
@@ -6124,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 ();
 
@@ -6225,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
@@ -6648,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 ();
        }
 
@@ -6970,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);
@@ -7424,7 +7579,7 @@ process_event_stop_test (struct execution_control_state *ecs)
     {
       /* 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 singe-step
+        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.  */
@@ -8162,6 +8317,9 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
          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 ();
@@ -8169,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)
@@ -8200,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
@@ -8457,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)
 {
@@ -8798,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
@@ -8915,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 ())
@@ -9702,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.  */
   {