* value.h (struct internalvar): Remove.
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 5473c998d453a69b2e5285e2087298fd37ca9a05..3540acf9d7796c6a06df4a96d73ca075095bb16e 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
    1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008 Free Software Foundation, Inc.
+   2008, 2009 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "language.h"
 #include "solib.h"
 #include "main.h"
-
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
 #include "event-top.h"
+#include "record.h"
 
 /* Prototypes for local functions */
 
@@ -73,9 +73,10 @@ static int follow_fork (void);
 static void set_schedlock_func (char *args, int from_tty,
                                struct cmd_list_element *c);
 
-struct thread_stepping_state;
+static int currently_stepping (struct thread_info *tp);
 
-static int currently_stepping (struct thread_stepping_state *tss);
+static int currently_stepping_or_nexting_callback (struct thread_info *tp,
+                                                  void *data);
 
 static void xdb_handle_command (char *args, int from_tty);
 
@@ -83,6 +84,8 @@ static int prepare_to_proceed (int);
 
 void _initialize_infrun (void);
 
+void nullify_last_target_wait_ptid (void);
+
 /* When set, stop the 'step' command if we enter a function which has
    no line number information.  The normal behavior is that we step
    over such function.  */
@@ -140,13 +143,13 @@ show_debug_infrun (struct ui_file *file, int from_tty,
    past the dynamic linker, as if we were using "next" to step over a
    function call.
 
-   IN_SOLIB_DYNSYM_RESOLVE_CODE says whether we're in the dynamic
+   in_solib_dynsym_resolve_code() says whether we're in the dynamic
    linker code or not.  Normally, this means we single-step.  However,
    if SKIP_SOLIB_RESOLVER then returns non-zero, then its value is an
    address where we can place a step-resume breakpoint to get past the
    linker's symbol resolution function.
 
-   IN_SOLIB_DYNSYM_RESOLVE_CODE can generally be implemented in a
+   in_solib_dynsym_resolve_code() can generally be implemented in a
    pretty portable way, by comparing the PC against the address ranges
    of the dynamic linker's sections.
 
@@ -216,31 +219,6 @@ static struct cmd_list_element *stop_command;
 
 static struct symbol *step_start_function;
 
-/* Nonzero if we are presently stepping over a breakpoint.
-
-   If we hit a breakpoint or watchpoint, and then continue,
-   we need to single step the current thread with breakpoints
-   disabled, to avoid hitting the same breakpoint or
-   watchpoint again.  And we should step just a single
-   thread and keep other threads stopped, so that 
-   other threads don't miss breakpoints while they are removed.
-
-   So, this variable simultaneously means that we need to single
-   step the current thread, keep other threads stopped, and that
-   breakpoints should be removed while we step.
-
-   This variable is set either:
-   - in proceed, when we resume inferior on user's explicit request
-   - in keep_going, if handle_inferior_event decides we need to
-   step over breakpoint.  
-
-   The variable is cleared in clear_proceed_status, called every
-   time before we call proceed.  The proceed calls wait_for_inferior,
-   which calls handle_inferior_event in a loop, and until 
-   wait_for_inferior exits, this variable is changed only by keep_going.  */
-
-static int stepping_over_breakpoint;
-
 /* Nonzero if we want to give control to the user when we're notified
    of shared library events by the dynamic linker.  */
 static int stop_on_solib_events;
@@ -257,20 +235,8 @@ show_stop_on_solib_events (struct ui_file *file, int from_tty,
 
 int stop_after_trap;
 
-/* Nonzero means expecting a trap and caller will handle it themselves.
-   It is used after attach, due to attaching to a process;
-   when running in the shell before the child program has been exec'd;
-   and when running some kinds of remote stuff (FIXME?).  */
-
-enum stop_kind stop_soon;
-
-/* Nonzero if proceed is being used for a "finish" command or a similar
-   situation when stop_registers should be saved.  */
-
-int proceed_to_finish;
-
-/* Save register contents here when about to pop a stack dummy frame,
-   if-and-only-if proceed_to_finish is set.
+/* Save register contents here when executing a "finish" command or are
+   about to pop a stack dummy frame, if-and-only-if proceed_to_finish is set.
    Thus this contains the return value from the called function (assuming
    values are returned in a register).  */
 
@@ -280,55 +246,18 @@ struct regcache *stop_registers;
 
 static int stop_print_frame;
 
-/* Step-resume or longjmp-resume breakpoint.  */
-static struct breakpoint *step_resume_breakpoint = NULL;
-
 /* This is a cached copy of the pid/waitstatus of the last event
    returned by target_wait()/deprecated_target_wait_hook().  This
    information is returned by get_last_target_status().  */
 static ptid_t target_last_wait_ptid;
 static struct target_waitstatus target_last_waitstatus;
 
-/* Context-switchable data.  */
-struct thread_stepping_state
-{
-  /* Should we step over breakpoint next time keep_going
-     is called?  */
-  int stepping_over_breakpoint;
-  struct symtab_and_line sal;
-  int current_line;
-  struct symtab *current_symtab;
-  int step_after_step_resume_breakpoint;
-  int stepping_through_solib_after_catch;
-  bpstat stepping_through_solib_catchpoints;
-};
-
-struct thread_stepping_state gtss;
-struct thread_stepping_state *tss = &gtss;
-
 static void context_switch (ptid_t ptid);
 
-void init_thread_stepping_state (struct thread_stepping_state *tss);
+void init_thread_stepping_state (struct thread_info *tss);
 
 void init_infwait_state (void);
 
-/* This is used to remember when a fork, vfork or exec event
-   was caught by a catchpoint, and thus the event is to be
-   followed at the next resume of the inferior, and not
-   immediately. */
-static struct
-{
-  enum target_waitkind kind;
-  struct
-  {
-    ptid_t parent_pid;
-    ptid_t child_pid;
-  }
-  fork_event;
-  char *execd_pathname;
-}
-pending_follow;
-
 static const char follow_fork_mode_child[] = "child";
 static const char follow_fork_mode_parent[] = "parent";
 
@@ -349,17 +278,164 @@ Debugger response to a program call of fork or vfork is \"%s\".\n"),
 }
 \f
 
+/* 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.  */
+
 static int
 follow_fork (void)
 {
   int follow_child = (follow_fork_mode_string == follow_fork_mode_child);
+  int should_resume = 1;
+  struct thread_info *tp;
+
+  /* Copy user stepping state to the new inferior thread.  FIXME: the
+     followed fork child thread should have a copy of most of the
+     parent thread structure's run control related fields, not just these.
+     Initialized to avoid "may be used uninitialized" warnings from gcc.  */
+  struct breakpoint *step_resume_breakpoint = NULL;
+  CORE_ADDR step_range_start = 0;
+  CORE_ADDR step_range_end = 0;
+  struct frame_id step_frame_id = { 0 };
+
+  if (!non_stop)
+    {
+      ptid_t wait_ptid;
+      struct target_waitstatus wait_status;
+
+      /* Get the last target status returned by target_wait().  */
+      get_last_target_status (&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;
+
+      /* Check if we switched over from WAIT_PTID, since the event was
+        reported.  */
+      if (!ptid_equal (wait_ptid, minus_one_ptid)
+         && !ptid_equal (inferior_ptid, wait_ptid))
+       {
+         /* We did.  Switch back to WAIT_PTID thread, to tell the
+            target to follow it (in either direction).  We'll
+            afterwards refuse to resume, and inform the user what
+            happened.  */
+         switch_to_thread (wait_ptid);
+         should_resume = 0;
+       }
+    }
+
+  tp = inferior_thread ();
+
+  /* If there were any forks/vforks that were caught and are now to be
+     followed, then do so now.  */
+  switch (tp->pending_follow.kind)
+    {
+    case TARGET_WAITKIND_FORKED:
+    case TARGET_WAITKIND_VFORKED:
+      {
+       ptid_t parent, child;
+
+       /* If the user did a next/step, etc, over a fork call,
+          preserve the stepping state in the fork child.  */
+       if (follow_child && should_resume)
+         {
+           step_resume_breakpoint
+             = clone_momentary_breakpoint (tp->step_resume_breakpoint);
+           step_range_start = tp->step_range_start;
+           step_range_end = tp->step_range_end;
+           step_frame_id = tp->step_frame_id;
+
+           /* For now, delete the parent's sr breakpoint, otherwise,
+              parent/child sr breakpoints are considered duplicates,
+              and the child version will not be installed.  Remove
+              this when the breakpoints module becomes aware of
+              inferiors and address spaces.  */
+           delete_step_resume_breakpoint (tp);
+           tp->step_range_start = 0;
+           tp->step_range_end = 0;
+           tp->step_frame_id = null_frame_id;
+         }
+
+       parent = inferior_ptid;
+       child = tp->pending_follow.value.related_pid;
+
+       /* Tell the target to do whatever is necessary to follow
+          either parent or child.  */
+       if (target_follow_fork (follow_child))
+         {
+           /* Target refused to follow, or there's some other reason
+              we shouldn't resume.  */
+           should_resume = 0;
+         }
+       else
+         {
+           /* This pending follow fork event is now handled, one way
+              or another.  The previous selected thread may be gone
+              from the lists by now, but if it is still around, need
+              to clear the pending follow request.  */
+           tp = find_thread_ptid (parent);
+           if (tp)
+             tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
+
+           /* 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)
+             {
+               switch_to_thread (child);
+
+               /* ... and preserve the stepping state, in case the
+                  user was stepping over the fork call.  */
+               if (should_resume)
+                 {
+                   tp = inferior_thread ();
+                   tp->step_resume_breakpoint = step_resume_breakpoint;
+                   tp->step_range_start = step_range_start;
+                   tp->step_range_end = step_range_end;
+                   tp->step_frame_id = step_frame_id;
+                 }
+               else
+                 {
+                   /* If we get here, it was because we're trying to
+                      resume from a fork catchpoint, but, the user
+                      has switched threads away from the thread that
+                      forked.  In that case, the resume command
+                      issued is most likely not applicable to the
+                      child, so just warn, and refuse to resume.  */
+                   warning (_("\
+Not resuming: switched threads before following fork child.\n"));
+                 }
+
+               /* Reset breakpoints in the child as appropriate.  */
+               follow_inferior_reset_breakpoints ();
+             }
+           else
+             switch_to_thread (parent);
+         }
+      }
+      break;
+    case TARGET_WAITKIND_SPURIOUS:
+      /* Nothing to follow.  */
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+                     "Unexpected pending_follow.kind %d\n",
+                     tp->pending_follow.kind);
+      break;
+    }
 
-  return target_follow_fork (follow_child);
+  return should_resume;
 }
 
 void
 follow_inferior_reset_breakpoints (void)
 {
+  struct thread_info *tp = inferior_thread ();
+
   /* Was there a step_resume breakpoint?  (There was if the user
      did a "next" at the fork() call.)  If so, explicitly reset its
      thread number.
@@ -371,8 +447,8 @@ follow_inferior_reset_breakpoints (void)
      "threads".  We must update the bp's notion of which thread
      it is for, or it'll be ignored when it triggers.  */
 
-  if (step_resume_breakpoint)
-    breakpoint_re_set_thread (step_resume_breakpoint);
+  if (tp->step_resume_breakpoint)
+    breakpoint_re_set_thread (tp->step_resume_breakpoint);
 
   /* Reinsert all breakpoints in the child.  The user may have set
      breakpoints after catching the fork, in which case those
@@ -388,8 +464,8 @@ follow_inferior_reset_breakpoints (void)
 static void
 follow_exec (ptid_t pid, char *execd_pathname)
 {
-  ptid_t saved_pid = pid;
   struct target_ops *tgt;
+  struct thread_info *th = inferior_thread ();
 
   /* This is an exec event that we actually wish to pay attention to.
      Refresh our symbol table to the newly exec'd program, remove any
@@ -415,9 +491,17 @@ follow_exec (ptid_t pid, char *execd_pathname)
 
   /* If there was one, it's gone now.  We cannot truly step-to-next
      statement through an exec(). */
-  step_resume_breakpoint = NULL;
-  step_range_start = 0;
-  step_range_end = 0;
+  th->step_resume_breakpoint = NULL;
+  th->step_range_start = 0;
+  th->step_range_end = 0;
+
+  /* The target reports the exec event to the main thread, even if
+     some other thread does the exec, and even if the main thread was
+     already stopped --- if debugging in non-stop mode, it's possible
+     the user had the main thread held stopped in the previous image
+     --- release it now.  This is the same behavior as step-over-exec
+     with scheduler-locking on in all-stop mode.  */
+  th->stop_requested = 0;
 
   /* What is this a.out's name? */
   printf_unfiltered (_("Executing new program: %s\n"), execd_pathname);
@@ -426,9 +510,8 @@ follow_exec (ptid_t pid, char *execd_pathname)
      inferior has essentially been killed & reborn. */
 
   gdb_flush (gdb_stdout);
-  generic_mourn_inferior ();
-  /* Because mourn_inferior resets inferior_ptid. */
-  inferior_ptid = saved_pid;
+
+  breakpoint_init_inferior (inf_execd);
 
   if (gdb_sysroot && *gdb_sysroot)
     {
@@ -611,27 +694,57 @@ static CORE_ADDR displaced_step_original, displaced_step_copy;
 /* Saved contents of copy area.  */
 static gdb_byte *displaced_step_saved_copy;
 
-/* When this is non-zero, we are allowed to use displaced stepping, if
-   the architecture supports it.  When this is zero, we use
-   traditional the hold-and-step approach.  */
-int can_use_displaced_stepping = 1;
+/* Enum strings for "set|show displaced-stepping".  */
+
+static const char can_use_displaced_stepping_auto[] = "auto";
+static const char can_use_displaced_stepping_on[] = "on";
+static const char can_use_displaced_stepping_off[] = "off";
+static const char *can_use_displaced_stepping_enum[] =
+{
+  can_use_displaced_stepping_auto,
+  can_use_displaced_stepping_on,
+  can_use_displaced_stepping_off,
+  NULL,
+};
+
+/* If ON, and the architecture supports it, GDB will use displaced
+   stepping to step over breakpoints.  If OFF, or if the architecture
+   doesn't support it, GDB will instead use the traditional
+   hold-and-step approach.  If AUTO (which is the default), GDB will
+   decide which technique to use to step over breakpoints depending on
+   which of all-stop or non-stop mode is active --- displaced stepping
+   in non-stop mode; hold-and-step in all-stop mode.  */
+
+static const char *can_use_displaced_stepping =
+  can_use_displaced_stepping_auto;
+
 static void
 show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
                                 struct cmd_list_element *c,
                                 const char *value)
 {
-  fprintf_filtered (file, _("\
-Debugger's willingness to use displaced stepping to step over "
-"breakpoints is %s.\n"), value);
+  if (can_use_displaced_stepping == can_use_displaced_stepping_auto)
+    fprintf_filtered (file, _("\
+Debugger's willingness to use displaced stepping to step over \
+breakpoints is %s (currently %s).\n"),
+                     value, non_stop ? "on" : "off");
+  else
+    fprintf_filtered (file, _("\
+Debugger's willingness to use displaced stepping to step over \
+breakpoints is %s.\n"), value);
 }
 
-/* Return non-zero if displaced stepping is enabled, and can be used
-   with GDBARCH.  */
+/* Return non-zero if displaced stepping can/should be used to step
+   over breakpoints.  */
+
 static int
 use_displaced_stepping (struct gdbarch *gdbarch)
 {
-  return (can_use_displaced_stepping
-         && gdbarch_displaced_step_copy_insn_p (gdbarch));
+  return (((can_use_displaced_stepping == can_use_displaced_stepping_auto
+           && non_stop)
+          || can_use_displaced_stepping == can_use_displaced_stepping_on)
+         && gdbarch_displaced_step_copy_insn_p (gdbarch)
+         && !RECORD_IS_USED);
 }
 
 /* Clean out any stray displaced stepping state.  */
@@ -687,7 +800,7 @@ displaced_step_dump_bytes (struct ui_file *file,
 static int
 displaced_step_prepare (ptid_t ptid)
 {
-  struct cleanup *old_cleanups;
+  struct cleanup *old_cleanups, *ignore_cleanups;
   struct regcache *regcache = get_thread_regcache (ptid);
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   CORE_ADDR original, copy;
@@ -739,6 +852,9 @@ displaced_step_prepare (ptid_t ptid)
 
   displaced_step_clear ();
 
+  old_cleanups = save_inferior_ptid ();
+  inferior_ptid = ptid;
+
   original = regcache_read_pc (regcache);
 
   copy = gdbarch_displaced_step_location (gdbarch);
@@ -746,8 +862,8 @@ displaced_step_prepare (ptid_t ptid)
 
   /* Save the original contents of the copy area.  */
   displaced_step_saved_copy = xmalloc (len);
-  old_cleanups = make_cleanup (free_current_contents,
-                               &displaced_step_saved_copy);
+  ignore_cleanups = make_cleanup (free_current_contents,
+                                 &displaced_step_saved_copy);
   read_memory (copy, displaced_step_saved_copy, len);
   if (debug_displaced)
     {
@@ -757,7 +873,7 @@ displaced_step_prepare (ptid_t ptid)
     };
 
   closure = gdbarch_displaced_step_copy_insn (gdbarch,
-                                              original, copy, regcache);
+                                             original, copy, regcache);
 
   /* We don't support the fully-simulated case at present.  */
   gdb_assert (closure);
@@ -767,11 +883,13 @@ displaced_step_prepare (ptid_t ptid)
   /* Resume execution at the copy.  */
   regcache_write_pc (regcache, copy);
 
-  discard_cleanups (old_cleanups);
+  discard_cleanups (ignore_cleanups);
+
+  do_cleanups (old_cleanups);
 
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: displaced pc to 0x%s\n",
-                        paddr_nz (copy));
+                       paddr_nz (copy));
 
   /* Save the information we need to fix things up if the step
      succeeds.  */
@@ -842,30 +960,98 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
 
   do_cleanups (old_cleanups);
 
+  displaced_step_ptid = null_ptid;
+
   /* Are there any pending displaced stepping requests?  If so, run
      one now.  */
-  if (displaced_step_request_queue)
+  while (displaced_step_request_queue)
     {
       struct displaced_step_request *head;
       ptid_t ptid;
+      CORE_ADDR actual_pc;
 
       head = displaced_step_request_queue;
       ptid = head->ptid;
       displaced_step_request_queue = head->next;
       xfree (head);
 
-      if (debug_displaced)
-       fprintf_unfiltered (gdb_stdlog,
-                           "displaced: stepping queued %s now\n",
-                           target_pid_to_str (ptid));
+      context_switch (ptid);
+
+      actual_pc = regcache_read_pc (get_thread_regcache (ptid));
+
+      if (breakpoint_here_p (actual_pc))
+       {
+         if (debug_displaced)
+           fprintf_unfiltered (gdb_stdlog,
+                               "displaced: stepping queued %s now\n",
+                               target_pid_to_str (ptid));
+
+         displaced_step_prepare (ptid);
+
+         if (debug_displaced)
+           {
+             gdb_byte buf[4];
 
+             fprintf_unfiltered (gdb_stdlog, "displaced: run 0x%s: ",
+                                 paddr_nz (actual_pc));
+             read_memory (actual_pc, buf, sizeof (buf));
+             displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
+           }
+
+         target_resume (ptid, 1, TARGET_SIGNAL_0);
+
+         /* Done, we're stepping a thread.  */
+         break;
+       }
+      else
+       {
+         int step;
+         struct thread_info *tp = inferior_thread ();
+
+         /* The breakpoint we were sitting under has since been
+            removed.  */
+         tp->trap_expected = 0;
 
-      displaced_step_ptid = null_ptid;
-      displaced_step_prepare (ptid);
-      target_resume (ptid, 1, TARGET_SIGNAL_0);
+         /* Go back to what we were trying to do.  */
+         step = currently_stepping (tp);
+
+         if (debug_displaced)
+           fprintf_unfiltered (gdb_stdlog, "breakpoint is gone %s: step(%d)\n",
+                               target_pid_to_str (tp->ptid), step);
+
+         target_resume (ptid, step, TARGET_SIGNAL_0);
+         tp->stop_signal = TARGET_SIGNAL_0;
+
+         /* This request was discarded.  See if there's any other
+            thread waiting for its turn.  */
+       }
     }
 }
 
+/* Update global variables holding ptids to hold NEW_PTID if they were
+   holding OLD_PTID.  */
+static void
+infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
+{
+  struct displaced_step_request *it;
+
+  if (ptid_equal (inferior_ptid, old_ptid))
+    inferior_ptid = new_ptid;
+
+  if (ptid_equal (singlestep_ptid, old_ptid))
+    singlestep_ptid = new_ptid;
+
+  if (ptid_equal (displaced_step_ptid, old_ptid))
+    displaced_step_ptid = new_ptid;
+
+  if (ptid_equal (deferred_step_ptid, old_ptid))
+    deferred_step_ptid = new_ptid;
+
+  for (it = displaced_step_request_queue; it; it = it->next)
+    if (ptid_equal (it->ptid, old_ptid))
+      it->ptid = new_ptid;
+}
+
 \f
 /* Resuming.  */
 
@@ -905,6 +1091,29 @@ set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
     }
 }
 
+/* Try to setup for software single stepping over the specified location.
+   Return 1 if target_resume() should use hardware single step.
+
+   GDBARCH the current gdbarch.
+   PC the location to step over.  */
+
+static int
+maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  int hw_step = 1;
+
+  if (gdbarch_software_single_step_p (gdbarch)
+      && gdbarch_software_single_step (gdbarch, get_current_frame ()))
+    {
+      hw_step = 0;
+      /* Do not pull these breakpoints until after a `wait' in
+        `wait_for_inferior' */
+      singlestep_breakpoints_inserted_p = 1;
+      singlestep_ptid = inferior_ptid;
+      singlestep_pc = pc;
+    }
+  return hw_step;
+}
 
 /* Resume the inferior, but allow a QUIT.  This is useful if the user
    wants to interrupt some lengthy single-stepping operation
@@ -921,14 +1130,16 @@ resume (int step, enum target_signal sig)
   struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct thread_info *tp = inferior_thread ();
   CORE_ADDR pc = regcache_read_pc (regcache);
+
   QUIT;
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
                         "infrun: resume (step=%d, signal=%d), "
-                        "stepping_over_breakpoint=%d\n",
-                       step, sig, stepping_over_breakpoint);
+                       "trap_expected=%d\n",
+                       step, sig, tp->trap_expected);
 
   /* Some targets (e.g. Solaris x86) have a kernel bug when stepping
      over an instruction that causes a page fault without triggering
@@ -965,53 +1176,26 @@ a command like `return' or `jump' to continue execution."));
      comments in the handle_inferior event for dealing with 'random
      signals' explain what we do instead.  */
   if (use_displaced_stepping (gdbarch)
-      && stepping_over_breakpoint
+      && tp->trap_expected
       && sig == TARGET_SIGNAL_0)
     {
       if (!displaced_step_prepare (inferior_ptid))
-       /* Got placed in displaced stepping queue.  Will be resumed
-          later when all the currently queued displaced stepping
-          requests finish.  */
-       return;
-    }
-
-  if (step && gdbarch_software_single_step_p (gdbarch))
-    {
-      /* Do it the hard way, w/temp breakpoints */
-      if (gdbarch_software_single_step (gdbarch, get_current_frame ()))
-        {
-          /* ...and don't ask hardware to do it.  */
-          step = 0;
-          /* and do not pull these breakpoints until after a `wait' in
-          `wait_for_inferior' */
-          singlestep_breakpoints_inserted_p = 1;
-          singlestep_ptid = inferior_ptid;
-          singlestep_pc = pc;
-        }
-    }
-
-  /* If there were any forks/vforks/execs that were caught and are
-     now to be followed, then do so.  */
-  switch (pending_follow.kind)
-    {
-    case TARGET_WAITKIND_FORKED:
-    case TARGET_WAITKIND_VFORKED:
-      pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
-      if (follow_fork ())
-       should_resume = 0;
-      break;
-
-    case TARGET_WAITKIND_EXECD:
-      /* follow_exec is called as soon as the exec event is seen. */
-      pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
-      break;
-
-    default:
-      break;
+       {
+         /* Got placed in displaced stepping queue.  Will be resumed
+            later when all the currently queued displaced stepping
+            requests finish.  The thread is not executing at this point,
+            and the call to set_executing will be made later.  But we
+            need to call set_running here, since from frontend point of view,
+            the thread is running.  */
+         set_running (inferior_ptid, 1);
+         discard_cleanups (old_cleanups);
+         return;
+       }
     }
 
-  /* Install inferior's terminal modes.  */
-  target_terminal_inferior ();
+  /* Do we need to do it the hard way, w/temp breakpoints?  */
+  if (step)
+    step = maybe_software_singlestep (gdbarch, pc);
 
   if (should_resume)
     {
@@ -1042,7 +1226,7 @@ a command like `return' or `jump' to continue execution."));
        }
 
       if ((step || singlestep_breakpoints_inserted_p)
-         && stepping_over_breakpoint)
+         && tp->trap_expected)
        {
          /* We're allowing a thread to run past a breakpoint it has
             hit, by single-stepping the thread with the breakpoint
@@ -1082,7 +1266,7 @@ a command like `return' or `jump' to continue execution."));
 
       if (debug_displaced
           && use_displaced_stepping (gdbarch)
-          && stepping_over_breakpoint)
+          && tp->trap_expected)
         {
          struct regcache *resume_regcache = get_thread_regcache (resume_ptid);
           CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
@@ -1094,6 +1278,13 @@ a command like `return' or `jump' to continue execution."));
           displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
         }
 
+      /* Install inferior's terminal modes.  */
+      target_terminal_inferior ();
+
+      /* Avoid confusing the next resume, if the next stop/resume
+        happens to apply to another thread.  */
+      tp->stop_signal = TARGET_SIGNAL_0;
+
       target_resume (resume_ptid, step, sig);
     }
 
@@ -1105,36 +1296,89 @@ a command like `return' or `jump' to continue execution."));
 /* Clear out all variables saying what to do when inferior is continued.
    First do this, then set the ones you want, then call `proceed'.  */
 
+static void
+clear_proceed_status_thread (struct thread_info *tp)
+{
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+                       "infrun: clear_proceed_status_thread (%s)\n",
+                       target_pid_to_str (tp->ptid));
+
+  tp->trap_expected = 0;
+  tp->step_range_start = 0;
+  tp->step_range_end = 0;
+  tp->step_frame_id = null_frame_id;
+  tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
+  tp->stop_requested = 0;
+
+  tp->stop_step = 0;
+
+  tp->proceed_to_finish = 0;
+
+  /* Discard any remaining commands or status from previous stop.  */
+  bpstat_clear (&tp->stop_bpstat);
+}
+
+static int
+clear_proceed_status_callback (struct thread_info *tp, void *data)
+{
+  if (is_exited (tp->ptid))
+    return 0;
+
+  clear_proceed_status_thread (tp);
+  return 0;
+}
+
 void
 clear_proceed_status (void)
 {
-  stepping_over_breakpoint = 0;
-  step_range_start = 0;
-  step_range_end = 0;
-  step_frame_id = null_frame_id;
-  step_over_calls = STEP_OVER_UNDEBUGGABLE;
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    {
+      struct inferior *inferior;
+
+      if (non_stop)
+       {
+         /* If in non-stop mode, only delete the per-thread status
+            of the current thread.  */
+         clear_proceed_status_thread (inferior_thread ());
+       }
+      else
+       {
+         /* In all-stop mode, delete the per-thread status of
+            *all* threads.  */
+         iterate_over_threads (clear_proceed_status_callback, NULL);
+       }
+  
+      inferior = current_inferior ();
+      inferior->stop_soon = NO_STOP_QUIETLY;
+    }
+
   stop_after_trap = 0;
-  stop_soon = NO_STOP_QUIETLY;
-  proceed_to_finish = 0;
-  breakpoint_proceeded = 1;    /* We're about to proceed... */
+
+  observer_notify_about_to_proceed ();
 
   if (stop_registers)
     {
       regcache_xfree (stop_registers);
       stop_registers = NULL;
     }
-
-  /* Discard any remaining commands or status from previous stop.  */
-  bpstat_clear (&stop_bpstat);
 }
 
-/* This should be suitable for any targets that support threads. */
+/* Check the current thread against the thread that reported the most recent
+   event.  If a step-over is required return TRUE and set the current thread
+   to the old thread.  Otherwise return FALSE.
+
+   This should be suitable for any targets that support threads. */
 
 static int
 prepare_to_proceed (int step)
 {
   ptid_t wait_ptid;
   struct target_waitstatus wait_status;
+  int schedlock_enabled;
+
+  /* With non-stop mode on, threads are always handled individually.  */
+  gdb_assert (! non_stop);
 
   /* Get the last target status returned by target_wait().  */
   get_last_target_status (&wait_ptid, &wait_status);
@@ -1146,9 +1390,15 @@ prepare_to_proceed (int step)
       return 0;
     }
 
+  schedlock_enabled = (scheduler_mode == schedlock_on
+                      || (scheduler_mode == schedlock_step
+                          && step));
+
   /* Switched over from WAIT_PID.  */
   if (!ptid_equal (wait_ptid, minus_one_ptid)
-      && !ptid_equal (inferior_ptid, wait_ptid))
+      && !ptid_equal (inferior_ptid, wait_ptid)
+      /* Don't single step WAIT_PID if scheduler locking is on.  */
+      && !schedlock_enabled)
     {
       struct regcache *regcache = get_thread_regcache (wait_ptid);
 
@@ -1171,11 +1421,6 @@ prepare_to_proceed (int step)
   return 0;
 }
 
-/* Record the pc of the program the last time it stopped.  This is
-   just used internally by wait_for_inferior, but need to be preserved
-   over calls to it and cleared when the inferior is started.  */
-static CORE_ADDR prev_pc;
-
 /* Basic routine for continuing the program in various fashions.
 
    ADDR is the address to resume at, or -1 for resume where stopped.
@@ -1191,11 +1436,26 @@ static CORE_ADDR prev_pc;
 void
 proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
 {
-  struct regcache *regcache = get_current_regcache ();
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  CORE_ADDR pc = regcache_read_pc (regcache);
+  struct regcache *regcache;
+  struct gdbarch *gdbarch;
+  struct thread_info *tp;
+  CORE_ADDR pc;
   int oneproc = 0;
 
+  /* If we're stopped at a fork/vfork, follow the branch set by the
+     "set follow-fork-mode" command; otherwise, we'll just proceed
+     resuming the current thread.  */
+  if (!follow_fork ())
+    {
+      /* The target for some reason decided not to resume.  */
+      normal_stop ();
+      return;
+    }
+
+  regcache = get_current_regcache ();
+  gdbarch = get_regcache_arch (regcache);
+  pc = regcache_read_pc (regcache);
+
   if (step > 0)
     step_start_function = find_pc_function (pc);
   if (step < 0)
@@ -1203,11 +1463,17 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
 
   if (addr == (CORE_ADDR) -1)
     {
-      if (pc == stop_pc && breakpoint_here_p (pc))
+      if (pc == stop_pc && breakpoint_here_p (pc) 
+         && execution_direction != EXEC_REVERSE)
        /* There is a breakpoint at the address we will resume at,
           step one instruction before inserting breakpoints so that
           we do not stop right away (and report a second hit at this
-          breakpoint).  */
+          breakpoint).
+
+          Note, we don't do this in reverse, because we won't
+          actually be executing the breakpoint insn anyway.
+          We'll be (un-)executing the previous instruction.  */
+
        oneproc = 1;
       else if (gdbarch_single_step_through_delay_p (gdbarch)
               && gdbarch_single_step_through_delay (gdbarch,
@@ -1248,9 +1514,12 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
        oneproc = 1;
     }
 
+  /* prepare_to_proceed may change the current thread.  */
+  tp = inferior_thread ();
+
   if (oneproc)
     {
-      stepping_over_breakpoint = 1;
+      tp->trap_expected = 1;
       /* If displaced stepping is enabled, we can step over the
         breakpoint without hitting it, so leave all breakpoints
         inserted.  Otherwise we need to disable all breakpoints, step
@@ -1263,15 +1532,40 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   /* We can insert breakpoints if we're not trying to step over one,
      or if we are stepping over one but we're using displaced stepping
      to do so.  */
-  if (! stepping_over_breakpoint || use_displaced_stepping (gdbarch))
+  if (! tp->trap_expected || use_displaced_stepping (gdbarch))
     insert_breakpoints ();
 
+  if (!non_stop)
+    {
+      /* Pass the last stop signal to the thread we're resuming,
+        irrespective of whether the current thread is the thread that
+        got the last event or not.  This was historically GDB's
+        behaviour before keeping a stop_signal per thread.  */
+
+      struct thread_info *last_thread;
+      ptid_t last_ptid;
+      struct target_waitstatus last_status;
+
+      get_last_target_status (&last_ptid, &last_status);
+      if (!ptid_equal (inferior_ptid, last_ptid)
+         && !ptid_equal (last_ptid, null_ptid)
+         && !ptid_equal (last_ptid, minus_one_ptid))
+       {
+         last_thread = find_thread_ptid (last_ptid);
+         if (last_thread)
+           {
+             tp->stop_signal = last_thread->stop_signal;
+             last_thread->stop_signal = TARGET_SIGNAL_0;
+           }
+       }
+    }
+
   if (siggnal != TARGET_SIGNAL_DEFAULT)
-    stop_signal = siggnal;
+    tp->stop_signal = siggnal;
   /* If this signal should not be seen by program,
      give it zero.  Used for debugging signals.  */
-  else if (!signal_program[stop_signal])
-    stop_signal = TARGET_SIGNAL_0;
+  else if (!signal_program[tp->stop_signal])
+    tp->stop_signal = TARGET_SIGNAL_0;
 
   annotate_starting ();
 
@@ -1301,19 +1595,16 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
      are not guaranteed the inferior is stopped and so the regcache_read_pc ()
      call can fail.  Setting the prev_pc value here ensures the value is 
      updated correctly when the inferior is stopped.  */
-  prev_pc = regcache_read_pc (get_current_regcache ());
+  tp->prev_pc = regcache_read_pc (get_current_regcache ());
 
   /* Fill in with reasonable starting values.  */
-  init_thread_stepping_state (tss);
-
-  /* We'll update this if & when we switch to a new thread. */
-  previous_inferior_ptid = inferior_ptid;
+  init_thread_stepping_state (tp);
 
   /* Reset to normal state.  */
   init_infwait_state ();
 
   /* Resume inferior.  */
-  resume (oneproc || step || bpstat_should_step (), stop_signal);
+  resume (oneproc || step || bpstat_should_step (), tp->stop_signal);
 
   /* Wait for it to stop (if not standalone)
      and in any case decode why it stopped, and act accordingly.  */
@@ -1332,9 +1623,11 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
 void
 start_remote (int from_tty)
 {
+  struct inferior *inferior;
   init_wait_for_inferior ();
-  stop_soon = STOP_QUIETLY_REMOTE;
-  stepping_over_breakpoint = 0;
+
+  inferior = current_inferior ();
+  inferior->stop_soon = STOP_QUIETLY_REMOTE;
 
   /* Always go on waiting for the target, regardless of the mode. */
   /* FIXME: cagney/1999-09-23: At present it isn't possible to
@@ -1366,16 +1659,9 @@ void
 init_wait_for_inferior (void)
 {
   /* These are meaningless until the first time through wait_for_inferior.  */
-  prev_pc = 0;
 
   breakpoint_init_inferior (inf_starting);
 
-  /* Don't confuse first call to proceed(). */
-  stop_signal = TARGET_SIGNAL_0;
-
-  /* The first resume is not following a fork/vfork/exec. */
-  pending_follow.kind = TARGET_WAITKIND_SPURIOUS;      /* I.e., none. */
-
   clear_proceed_status ();
 
   stepping_past_singlestep_breakpoint = 0;
@@ -1383,7 +1669,6 @@ init_wait_for_inferior (void)
 
   target_last_wait_ptid = minus_one_ptid;
 
-  init_thread_stepping_state (tss);
   previous_inferior_ptid = null_ptid;
   init_infwait_state ();
 
@@ -1414,7 +1699,9 @@ enum inferior_stop_reason
   /* Inferior exited. */
   EXITED,
   /* Inferior received signal, and user asked to be notified. */
-  SIGNAL_RECEIVED
+  SIGNAL_RECEIVED,
+  /* Reverse execution -- target ran out of history info.  */
+  NO_HISTORY
 };
 
 /* The PTID we'll do a target_wait on.*/
@@ -1428,6 +1715,10 @@ enum infwait_states infwait_state;
 struct execution_control_state
 {
   ptid_t ptid;
+  /* The thread that got the event, if this was a thread event; NULL
+     otherwise.  */
+  struct thread_info *event_thread;
+
   struct target_waitstatus ws;
   int random_signal;
   CORE_ADDR stop_func_start;
@@ -1441,7 +1732,8 @@ void init_execution_control_state (struct execution_control_state *ecs);
 
 void handle_inferior_event (struct execution_control_state *ecs);
 
-static void step_into_function (struct execution_control_state *ecs);
+static void handle_step_into_function (struct execution_control_state *ecs);
+static void handle_step_into_function_backward (struct execution_control_state *ecs);
 static void insert_step_resume_breakpoint_at_frame (struct frame_info *step_frame);
 static void insert_step_resume_breakpoint_at_caller (struct frame_info *);
 static void insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal,
@@ -1454,6 +1746,194 @@ static void keep_going (struct execution_control_state *ecs);
 static void print_stop_reason (enum inferior_stop_reason stop_reason,
                               int stop_info);
 
+/* Callback for iterate over threads.  If the thread is stopped, but
+   the user/frontend doesn't know about that yet, go through
+   normal_stop, as if the thread had just stopped now.  ARG points at
+   a ptid.  If PTID is MINUS_ONE_PTID, applies to all threads.  If
+   ptid_is_pid(PTID) is true, applies to all threads of the process
+   pointed at by PTID.  Otherwise, apply only to the thread pointed by
+   PTID.  */
+
+static int
+infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
+{
+  ptid_t ptid = * (ptid_t *) arg;
+
+  if ((ptid_equal (info->ptid, ptid)
+       || ptid_equal (minus_one_ptid, ptid)
+       || (ptid_is_pid (ptid)
+          && ptid_get_pid (ptid) == ptid_get_pid (info->ptid)))
+      && is_running (info->ptid)
+      && !is_executing (info->ptid))
+    {
+      struct cleanup *old_chain;
+      struct execution_control_state ecss;
+      struct execution_control_state *ecs = &ecss;
+
+      memset (ecs, 0, sizeof (*ecs));
+
+      old_chain = make_cleanup_restore_current_thread ();
+
+      switch_to_thread (info->ptid);
+
+      /* Go through handle_inferior_event/normal_stop, so we always
+        have consistent output as if the stop event had been
+        reported.  */
+      ecs->ptid = info->ptid;
+      ecs->event_thread = find_thread_ptid (info->ptid);
+      ecs->ws.kind = TARGET_WAITKIND_STOPPED;
+      ecs->ws.value.sig = TARGET_SIGNAL_0;
+
+      handle_inferior_event (ecs);
+
+      if (!ecs->wait_some_more)
+       {
+         struct thread_info *tp;
+
+         normal_stop ();
+
+         /* Finish off the continuations.  The continations
+            themselves are responsible for realising the thread
+            didn't finish what it was supposed to do.  */
+         tp = inferior_thread ();
+         do_all_intermediate_continuations_thread (tp);
+         do_all_continuations_thread (tp);
+       }
+
+      do_cleanups (old_chain);
+    }
+
+  return 0;
+}
+
+/* This function is attached as a "thread_stop_requested" observer.
+   Cleanup local state that assumed the PTID was to be resumed, and
+   report the stop to the frontend.  */
+
+static void
+infrun_thread_stop_requested (ptid_t ptid)
+{
+  struct displaced_step_request *it, *next, *prev = NULL;
+
+  /* PTID was requested to stop.  Remove it from the displaced
+     stepping queue, so we don't try to resume it automatically.  */
+  for (it = displaced_step_request_queue; it; it = next)
+    {
+      next = it->next;
+
+      if (ptid_equal (it->ptid, ptid)
+         || ptid_equal (minus_one_ptid, ptid)
+         || (ptid_is_pid (ptid)
+             && ptid_get_pid (ptid) == ptid_get_pid (it->ptid)))
+       {
+         if (displaced_step_request_queue == it)
+           displaced_step_request_queue = it->next;
+         else
+           prev->next = it->next;
+
+         xfree (it);
+       }
+      else
+       prev = it;
+    }
+
+  iterate_over_threads (infrun_thread_stop_requested_callback, &ptid);
+}
+
+static void
+infrun_thread_thread_exit (struct thread_info *tp, int silent)
+{
+  if (ptid_equal (target_last_wait_ptid, tp->ptid))
+    nullify_last_target_wait_ptid ();
+}
+
+/* Callback for iterate_over_threads.  */
+
+static int
+delete_step_resume_breakpoint_callback (struct thread_info *info, void *data)
+{
+  if (is_exited (info->ptid))
+    return 0;
+
+  delete_step_resume_breakpoint (info);
+  return 0;
+}
+
+/* In all-stop, delete the step resume breakpoint of any thread that
+   had one.  In non-stop, delete the step resume breakpoint of the
+   thread that just stopped.  */
+
+static void
+delete_step_thread_step_resume_breakpoint (void)
+{
+  if (!target_has_execution
+      || ptid_equal (inferior_ptid, null_ptid))
+    /* If the inferior has exited, we have already deleted the step
+       resume breakpoints out of GDB's lists.  */
+    return;
+
+  if (non_stop)
+    {
+      /* If in non-stop mode, only delete the step-resume or
+        longjmp-resume breakpoint of the thread that just stopped
+        stepping.  */
+      struct thread_info *tp = inferior_thread ();
+      delete_step_resume_breakpoint (tp);
+    }
+  else
+    /* In all-stop mode, delete all step-resume and longjmp-resume
+       breakpoints of any thread that had them.  */
+    iterate_over_threads (delete_step_resume_breakpoint_callback, NULL);
+}
+
+/* A cleanup wrapper. */
+
+static void
+delete_step_thread_step_resume_breakpoint_cleanup (void *arg)
+{
+  delete_step_thread_step_resume_breakpoint ();
+}
+
+/* Pretty print the results of target_wait, for debugging purposes.  */
+
+static void
+print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
+                          const struct target_waitstatus *ws)
+{
+  char *status_string = target_waitstatus_to_string (ws);
+  struct ui_file *tmp_stream = mem_fileopen ();
+  char *text;
+  long len;
+
+  /* The text is split over several lines because it was getting too long.
+     Call fprintf_unfiltered (gdb_stdlog) once so that the text is still
+     output as a unit; we want only one timestamp printed if debug_timestamp
+     is set.  */
+
+  fprintf_unfiltered (tmp_stream,
+                     "infrun: target_wait (%d", PIDGET (waiton_ptid));
+  if (PIDGET (waiton_ptid) != -1)
+    fprintf_unfiltered (tmp_stream,
+                       " [%s]", target_pid_to_str (waiton_ptid));
+  fprintf_unfiltered (tmp_stream, ", status) =\n");
+  fprintf_unfiltered (tmp_stream,
+                     "infrun:   %d [%s],\n",
+                     PIDGET (result_ptid), target_pid_to_str (result_ptid));
+  fprintf_unfiltered (tmp_stream,
+                     "infrun:   %s\n",
+                     status_string);
+
+  text = ui_file_xstrdup (tmp_stream, &len);
+
+  /* This uses %s in part to handle %'s in the text, but also to avoid
+     a gcc error: the format attribute requires a string literal.  */
+  fprintf_unfiltered (gdb_stdlog, "%s", text);
+
+  xfree (status_string);
+  xfree (text);
+  ui_file_delete (tmp_stream);
+}
+
 /* Wait for control to return from inferior to debugger.
 
    If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals
@@ -1478,14 +1958,17 @@ wait_for_inferior (int treat_exec_as_sigtrap)
       (gdb_stdlog, "infrun: wait_for_inferior (treat_exec_as_sigtrap=%d)\n",
        treat_exec_as_sigtrap);
 
-  old_cleanups = make_cleanup (delete_step_resume_breakpoint,
-                              &step_resume_breakpoint);
+  old_cleanups =
+    make_cleanup (delete_step_thread_step_resume_breakpoint_cleanup, NULL);
 
   ecs = &ecss;
   memset (ecs, 0, sizeof (*ecs));
 
   overlay_cache_invalid = 1;
 
+  /* We'll update this if & when we switch to a new thread.  */
+  previous_inferior_ptid = inferior_ptid;
+
   /* We have to invalidate the registers BEFORE calling target_wait
      because they can be loaded from the target while in target_wait.
      This makes remote debugging a bit more efficient for those
@@ -1496,10 +1979,15 @@ wait_for_inferior (int treat_exec_as_sigtrap)
 
   while (1)
     {
+      struct cleanup *old_chain;
+
       if (deprecated_target_wait_hook)
-       ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws);
+       ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws, 0);
       else
-       ecs->ptid = target_wait (waiton_ptid, &ecs->ws);
+       ecs->ptid = target_wait (waiton_ptid, &ecs->ws, 0);
+
+      if (debug_infrun)
+       print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
 
       if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD)
         {
@@ -1508,12 +1996,21 @@ wait_for_inferior (int treat_exec_as_sigtrap)
           ecs->ws.value.sig = TARGET_SIGNAL_TRAP;
         }
 
+      /* If an error happens while handling the event, propagate GDB's
+        knowledge of the executing state to the frontend/user running
+        state.  */
+      old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+
       /* Now figure out what to do with the result of the result.  */
       handle_inferior_event (ecs);
 
+      /* No error, don't finish the state yet.  */
+      discard_cleanups (old_chain);
+
       if (!ecs->wait_some_more)
        break;
     }
+
   do_cleanups (old_cleanups);
 }
 
@@ -1532,12 +2029,20 @@ fetch_inferior_event (void *client_data)
   struct execution_control_state ecss;
   struct execution_control_state *ecs = &ecss;
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+  struct cleanup *ts_old_chain;
   int was_sync = sync_execution;
 
   memset (ecs, 0, sizeof (*ecs));
 
   overlay_cache_invalid = 1;
 
+  /* We can only rely on wait_for_more being correct before handling
+     the event in all-stop, but previous_inferior_ptid isn't used in
+     non-stop.  */
+  if (!ecs->wait_some_more)
+    /* We'll update this if & when we switch to a new thread.  */
+    previous_inferior_ptid = inferior_ptid;
+
   if (non_stop)
     /* In non-stop mode, the user/frontend should not notice a thread
        switch due to internal events.  Make sure we reverse to the
@@ -1555,9 +2060,12 @@ fetch_inferior_event (void *client_data)
 
   if (deprecated_target_wait_hook)
     ecs->ptid =
-      deprecated_target_wait_hook (waiton_ptid, &ecs->ws);
+      deprecated_target_wait_hook (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
   else
-    ecs->ptid = target_wait (waiton_ptid, &ecs->ws);
+    ecs->ptid = target_wait (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
+
+  if (debug_infrun)
+    print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
 
   if (non_stop
       && ecs->ws.kind != TARGET_WAITKIND_IGNORE
@@ -1568,20 +2076,40 @@ fetch_inferior_event (void *client_data)
        thread.  */
     context_switch (ecs->ptid);
 
+  /* If an error happens while handling the event, propagate GDB's
+     knowledge of the executing state to the frontend/user running
+     state.  */
+  if (!non_stop)
+    ts_old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+  else
+    ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
+
   /* Now figure out what to do with the result of the result.  */
   handle_inferior_event (ecs);
 
   if (!ecs->wait_some_more)
     {
-      delete_step_resume_breakpoint (&step_resume_breakpoint);
+      struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
 
-      normal_stop ();
-      if (step_multi && stop_step)
+      delete_step_thread_step_resume_breakpoint ();
+
+      /* We may not find an inferior if this was a process exit.  */
+      if (inf == NULL || inf->stop_soon == NO_STOP_QUIETLY)
+       normal_stop ();
+
+      if (target_has_execution
+         && ecs->ws.kind != TARGET_WAITKIND_EXITED
+         && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+         && ecs->event_thread->step_multi
+         && ecs->event_thread->stop_step)
        inferior_event_handler (INF_EXEC_CONTINUE, NULL);
       else
        inferior_event_handler (INF_EXEC_COMPLETE, NULL);
     }
 
+  /* No error, don't finish the thread states yet.  */
+  discard_cleanups (ts_old_chain);
+
   /* Revert thread and frame.  */
   do_cleanups (old_chain);
 
@@ -1603,15 +2131,18 @@ init_execution_control_state (struct execution_control_state *ecs)
 /* Clear context switchable stepping state.  */
 
 void
-init_thread_stepping_state (struct thread_stepping_state *tss)
+init_thread_stepping_state (struct thread_info *tss)
 {
+  struct symtab_and_line sal;
+
   tss->stepping_over_breakpoint = 0;
   tss->step_after_step_resume_breakpoint = 0;
   tss->stepping_through_solib_after_catch = 0;
   tss->stepping_through_solib_catchpoints = NULL;
-  tss->sal = find_pc_line (prev_pc, 0);
-  tss->current_line = tss->sal.line;
-  tss->current_symtab = tss->sal.symtab;
+
+  sal = find_pc_line (tss->prev_pc, 0);
+  tss->current_line = sal.line;
+  tss->current_symtab = sal.symtab;
 }
 
 /* Return the cached copy of the last pid/waitstatus returned by
@@ -1632,17 +2163,11 @@ nullify_last_target_wait_ptid (void)
   target_last_wait_ptid = minus_one_ptid;
 }
 
-/* Switch thread contexts, maintaining "infrun state". */
+/* Switch thread contexts */
 
 static void
 context_switch (ptid_t ptid)
 {
-  /* Caution: it may happen that the new thread (or the old one!)
-     is not in the thread list.  In this case we must not attempt
-     to "switch context", or we run the risk that our context may
-     be lost.  This may happen as a result of the target module
-     mishandling thread creation.  */
-
   if (debug_infrun)
     {
       fprintf_unfiltered (gdb_stdlog, "infrun: Switching context from %s ",
@@ -1651,72 +2176,16 @@ context_switch (ptid_t ptid)
                          target_pid_to_str (ptid));
     }
 
-  if (in_thread_list (inferior_ptid) && in_thread_list (ptid))
-    {                          /* Perform infrun state context switch: */
-      /* Save infrun state for the old thread.  */
-      save_infrun_state (inferior_ptid, prev_pc,
-                        stepping_over_breakpoint, step_resume_breakpoint,
-                        step_range_start,
-                        step_range_end, &step_frame_id,
-                        tss->stepping_over_breakpoint,
-                        tss->stepping_through_solib_after_catch,
-                        tss->stepping_through_solib_catchpoints,
-                        tss->current_line, tss->current_symtab,
-                        cmd_continuation, intermediate_continuation,
-                        proceed_to_finish,
-                        step_over_calls,
-                        stop_step,
-                        step_multi,
-                        stop_signal,
-                        stop_bpstat);
-
-      /* Load infrun state for the new thread.  */
-      load_infrun_state (ptid, &prev_pc,
-                        &stepping_over_breakpoint, &step_resume_breakpoint,
-                        &step_range_start,
-                        &step_range_end, &step_frame_id,
-                        &tss->stepping_over_breakpoint,
-                        &tss->stepping_through_solib_after_catch,
-                        &tss->stepping_through_solib_catchpoints,
-                        &tss->current_line, &tss->current_symtab,
-                        &cmd_continuation, &intermediate_continuation,
-                        &proceed_to_finish,
-                        &step_over_calls,
-                        &stop_step,
-                        &step_multi,
-                        &stop_signal,
-                        &stop_bpstat);
-    }
-
   switch_to_thread (ptid);
 }
 
-/* Context switch to thread PTID.  */
-ptid_t
-context_switch_to (ptid_t ptid)
-{
-  ptid_t current_ptid = inferior_ptid;
-
-  /* Context switch to the new thread. */
-  if (!ptid_equal (ptid, inferior_ptid))
-    {
-      context_switch (ptid);
-    }
-  return current_ptid;
-}
-
 static void
 adjust_pc_after_break (struct execution_control_state *ecs)
 {
-  struct regcache *regcache = get_thread_regcache (ecs->ptid);
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct regcache *regcache;
+  struct gdbarch *gdbarch;
   CORE_ADDR breakpoint_pc;
 
-  /* If this target does not decrement the PC after breakpoints, then
-     we have nothing to do.  */
-  if (gdbarch_decr_pc_after_break (gdbarch) == 0)
-    return;
-
   /* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP.  If
      we aren't, just return.
 
@@ -1744,15 +2213,62 @@ adjust_pc_after_break (struct execution_control_state *ecs)
   if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
     return;
 
+  /* In reverse execution, when a breakpoint is hit, the instruction
+     under it has already been de-executed.  The reported PC always
+     points at the breakpoint address, so adjusting it further would
+     be wrong.  E.g., consider this case on a decr_pc_after_break == 1
+     architecture:
+
+       B1         0x08000000 :   INSN1
+       B2         0x08000001 :   INSN2
+                 0x08000002 :   INSN3
+           PC -> 0x08000003 :   INSN4
+
+     Say you're stopped at 0x08000003 as above.  Reverse continuing
+     from that point should hit B2 as below.  Reading the PC when the
+     SIGTRAP is reported should read 0x08000001 and INSN2 should have
+     been de-executed already.
+
+       B1         0x08000000 :   INSN1
+       B2   PC -> 0x08000001 :   INSN2
+                 0x08000002 :   INSN3
+                 0x08000003 :   INSN4
+
+     We can't apply the same logic as for forward execution, because
+     we would wrongly adjust the PC to 0x08000000, since there's a
+     breakpoint at PC - 1.  We'd then report a hit on B1, although
+     INSN1 hadn't been de-executed yet.  Doing nothing is the correct
+     behaviour.  */
+  if (execution_direction == EXEC_REVERSE)
+    return;
+
+  /* If this target does not decrement the PC after breakpoints, then
+     we have nothing to do.  */
+  regcache = get_thread_regcache (ecs->ptid);
+  gdbarch = get_regcache_arch (regcache);
+  if (gdbarch_decr_pc_after_break (gdbarch) == 0)
+    return;
+
   /* Find the location where (if we've hit a breakpoint) the
      breakpoint would be.  */
   breakpoint_pc = regcache_read_pc (regcache)
                  - gdbarch_decr_pc_after_break (gdbarch);
 
-  /* Check whether there actually is a software breakpoint inserted
-     at that location.  */
-  if (software_breakpoint_inserted_here_p (breakpoint_pc))
+  /* Check whether there actually is a software breakpoint inserted at
+     that location.
+
+     If in non-stop mode, a race condition is possible where we've
+     removed a breakpoint, but stop events for that breakpoint were
+     already queued and arrive later.  To suppress those spurious
+     SIGTRAPs, we keep a list of such breakpoint locations for a bit,
+     and retire them after a number of stop events are reported.  */
+  if (software_breakpoint_inserted_here_p (breakpoint_pc)
+      || (non_stop && moribund_breakpoint_here_p (breakpoint_pc)))
     {
+      struct cleanup *old_cleanups = NULL;
+      if (RECORD_IS_USED)
+       old_cleanups = record_gdb_operation_disable_set ();
+
       /* When using hardware single-step, a SIGTRAP is reported for both
         a completed single-step and a software breakpoint.  Need to
         differentiate between the two, as the latter needs adjusting
@@ -1773,9 +2289,12 @@ adjust_pc_after_break (struct execution_control_state *ecs)
 
       if (singlestep_breakpoints_inserted_p
          || !ptid_equal (ecs->ptid, inferior_ptid)
-         || !currently_stepping (tss)
-         || prev_pc == breakpoint_pc)
+         || !currently_stepping (ecs->event_thread)
+         || ecs->event_thread->prev_pc == breakpoint_pc)
        regcache_write_pc (regcache, breakpoint_pc);
+
+      if (RECORD_IS_USED)
+       do_cleanups (old_cleanups);
     }
 }
 
@@ -1810,8 +2329,19 @@ handle_inferior_event (struct execution_control_state *ecs)
   int sw_single_step_trap_p = 0;
   int stopped_by_watchpoint;
   int stepped_after_stopped_by_watchpoint = 0;
+  struct symtab_and_line stop_pc_sal;
+  enum stop_kind stop_soon;
 
-  breakpoint_retire_moribund ();
+  if (ecs->ws.kind != TARGET_WAITKIND_EXITED
+      && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+      && ecs->ws.kind != TARGET_WAITKIND_IGNORE)
+    {
+      struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
+      gdb_assert (inf);
+      stop_soon = inf->stop_soon;
+    }
+  else
+    stop_soon = NO_STOP_QUIETLY;
 
   /* Cache the last pid/waitstatus. */
   target_last_wait_ptid = ecs->ptid;
@@ -1820,8 +2350,41 @@ handle_inferior_event (struct execution_control_state *ecs)
   /* Always clear state belonging to the previous time we stopped.  */
   stop_stack_dummy = 0;
 
+  /* If it's a new process, add it to the thread database */
+
+  ecs->new_thread_event = (!ptid_equal (ecs->ptid, inferior_ptid)
+                          && !ptid_equal (ecs->ptid, minus_one_ptid)
+                          && !in_thread_list (ecs->ptid));
+
+  if (ecs->ws.kind != TARGET_WAITKIND_EXITED
+      && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED && ecs->new_thread_event)
+    add_thread (ecs->ptid);
+
+  ecs->event_thread = find_thread_ptid (ecs->ptid);
+
+  /* Dependent on valid ECS->EVENT_THREAD.  */
   adjust_pc_after_break (ecs);
 
+  /* Dependent on the current PC value modified by adjust_pc_after_break.  */
+  reinit_frame_cache ();
+
+  if (ecs->ws.kind != TARGET_WAITKIND_IGNORE)
+    {
+      breakpoint_retire_moribund ();
+
+      /* Mark the non-executing threads accordingly.  In all-stop, all
+        threads of all processes are stopped when we get any event
+        reported.  In non-stop mode, only the event thread stops.  If
+        we're handling a process exit in non-stop mode, there's
+        nothing to do, as threads of the dead process are gone, and
+        threads of any other process were left running.  */
+      if (!non_stop)
+       set_executing (minus_one_ptid, 0);
+      else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+              && ecs->ws.kind != TARGET_WAITKIND_EXITED)
+       set_executing (inferior_ptid, 0);
+    }
+
   switch (infwait_state)
     {
     case infwait_thread_hop_state:
@@ -1861,29 +2424,6 @@ handle_inferior_event (struct execution_control_state *ecs)
     }
   infwait_state = infwait_normal_state;
 
-  reinit_frame_cache ();
-
-  /* If it's a new process, add it to the thread database */
-
-  ecs->new_thread_event = (!ptid_equal (ecs->ptid, inferior_ptid)
-                          && !ptid_equal (ecs->ptid, minus_one_ptid)
-                          && !in_thread_list (ecs->ptid));
-
-  if (ecs->ws.kind != TARGET_WAITKIND_EXITED
-      && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED && ecs->new_thread_event)
-    add_thread (ecs->ptid);
-
-  if (ecs->ws.kind != TARGET_WAITKIND_IGNORE)
-    {
-      /* Mark the non-executing threads accordingly.  */
-      if (!non_stop
-         || ecs->ws.kind == TARGET_WAITKIND_EXITED
-         || ecs->ws.kind == TARGET_WAITKIND_SIGNALLED)
-       set_executing (pid_to_ptid (-1), 0);
-      else
-       set_executing (ecs->ptid, 0);
-    }
-
   switch (ecs->ws.kind)
     {
     case TARGET_WAITKIND_LOADED:
@@ -1966,14 +2506,14 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_EXITED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\n");
+      inferior_ptid = ecs->ptid;
       target_terminal_ours (); /* Must do this before mourn anyway */
       print_stop_reason (EXITED, ecs->ws.value.integer);
 
       /* Record the exit code in the convenience variable $_exitcode, so
          that the user can inspect this again later.  */
-      set_internalvar (lookup_internalvar ("_exitcode"),
-                      value_from_longest (builtin_type_int,
-                                          (LONGEST) ecs->ws.value.integer));
+      set_internalvar_integer (lookup_internalvar ("_exitcode"),
+                              (LONGEST) ecs->ws.value.integer);
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
       singlestep_breakpoints_inserted_p = 0;
@@ -1984,8 +2524,8 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_SIGNALLED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n");
+      inferior_ptid = ecs->ptid;
       stop_print_frame = 0;
-      stop_signal = ecs->ws.value.sig;
       target_terminal_ours (); /* Must do this before mourn anyway */
 
       /* Note: By definition of TARGET_WAITKIND_SIGNALLED, we shouldn't
@@ -1995,7 +2535,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          may be needed. */
       target_mourn_inferior ();
 
-      print_stop_reason (SIGNAL_EXITED, stop_signal);
+      print_stop_reason (SIGNAL_EXITED, ecs->ws.value.sig);
       singlestep_breakpoints_inserted_p = 0;
       stop_stepping (ecs);
       return;
@@ -2006,11 +2546,6 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_VFORKED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
-      stop_signal = TARGET_SIGNAL_TRAP;
-      pending_follow.kind = ecs->ws.kind;
-
-      pending_follow.fork_event.parent_pid = ecs->ptid;
-      pending_follow.fork_event.child_pid = ecs->ws.value.related_pid;
 
       if (!ptid_equal (ecs->ptid, inferior_ptid))
        {
@@ -2018,49 +2553,62 @@ handle_inferior_event (struct execution_control_state *ecs)
          reinit_frame_cache ();
        }
 
-      stop_pc = read_pc ();
+      /* Immediately detach breakpoints from the child before there's
+        any chance of letting the user delete breakpoints from the
+        breakpoint lists.  If we don't do this early, it's easy to
+        leave left over traps in the child, vis: "break foo; catch
+        fork; c; <fork>; del; c; <child calls foo>".  We only follow
+        the fork on the last `continue', and by that time the
+        breakpoint at "foo" is long gone from the breakpoint table.
+        If we vforked, then we don't need to unpatch here, since both
+        parent and child are sharing the same memory pages; we'll
+        need to unpatch at follow/detach time instead to be certain
+        that new breakpoints added between catchpoint hit time and
+        vfork follow are detached.  */
+      if (ecs->ws.kind != TARGET_WAITKIND_VFORKED)
+       {
+         int child_pid = ptid_get_pid (ecs->ws.value.related_pid);
+
+         /* This won't actually modify the breakpoint list, but will
+            physically remove the breakpoints from the child.  */
+         detach_breakpoints (child_pid);
+       }
+
+      /* In case the event is caught by a catchpoint, remember that
+        the event is to be followed at the next resume of the thread,
+        and not immediately.  */
+      ecs->event_thread->pending_follow = ecs->ws;
 
-      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
-      ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
+      ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+
+      ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
 
       /* If no catchpoint triggered for this, then keep going.  */
       if (ecs->random_signal)
        {
-         stop_signal = TARGET_SIGNAL_0;
-         keep_going (ecs);
+         int should_resume;
+
+         ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+
+         should_resume = follow_fork ();
+
+         ecs->event_thread = inferior_thread ();
+         ecs->ptid = inferior_ptid;
+
+         if (should_resume)
+           keep_going (ecs);
+         else
+           stop_stepping (ecs);
          return;
        }
+      ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
       goto process_event_stop_test;
 
     case TARGET_WAITKIND_EXECD:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n");
-      stop_signal = TARGET_SIGNAL_TRAP;
-
-      pending_follow.execd_pathname =
-       savestring (ecs->ws.value.execd_pathname,
-                   strlen (ecs->ws.value.execd_pathname));
-
-      /* This causes the eventpoints and symbol table to be reset.  Must
-         do this now, before trying to determine whether to stop. */
-      follow_exec (inferior_ptid, pending_follow.execd_pathname);
-      xfree (pending_follow.execd_pathname);
-
-      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
-
-      {
-       /* The breakpoints module may need to touch the inferior's
-          memory.  Switch to the (stopped) event ptid
-          momentarily.  */
-       ptid_t saved_inferior_ptid = inferior_ptid;
-       inferior_ptid = ecs->ptid;
-
-       stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
-
-       ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
-       inferior_ptid = saved_inferior_ptid;
-      }
 
       if (!ptid_equal (ecs->ptid, inferior_ptid))
        {
@@ -2068,13 +2616,29 @@ handle_inferior_event (struct execution_control_state *ecs)
          reinit_frame_cache ();
        }
 
+      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+
+      /* This causes the eventpoints and symbol table to be reset.
+         Must do this now, before trying to determine whether to
+         stop.  */
+      follow_exec (inferior_ptid, ecs->ws.value.execd_pathname);
+
+      ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+      ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
+
+      /* Note that this may be referenced from inside
+        bpstat_stop_status above, through inferior_has_execd.  */
+      xfree (ecs->ws.value.execd_pathname);
+      ecs->ws.value.execd_pathname = NULL;
+
       /* If no catchpoint triggered for this, then keep going.  */
       if (ecs->random_signal)
        {
-         stop_signal = TARGET_SIGNAL_0;
+         ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
          keep_going (ecs);
          return;
        }
+      ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
       goto process_event_stop_test;
 
       /* Be careful not to try to gather much state about a thread
@@ -2101,9 +2665,16 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_STOPPED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n");
-      stop_signal = ecs->ws.value.sig;
+      ecs->event_thread->stop_signal = ecs->ws.value.sig;
       break;
 
+    case TARGET_WAITKIND_NO_HISTORY:
+      /* Reverse execution: target ran out of history info.  */
+      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+      print_stop_reason (NO_HISTORY, 0);
+      stop_stepping (ecs);
+      return;
+
       /* We had an event in the inferior, but we are not interested
          in handling it at this level. The lower layers have already
          done what needs to be done, if anything.
@@ -2141,10 +2712,21 @@ targets should add new threads to the thread list themselves in non-stop mode.")
       return;
     }
 
-  /* Do we need to clean up the state of a thread that has completed a
-     displaced single-step?  (Doing so usually affects the PC, so do
-     it here, before we set stop_pc.)  */
-  displaced_step_fixup (ecs->ptid, stop_signal);
+  if (ecs->ws.kind == TARGET_WAITKIND_STOPPED)
+    {
+      /* Do we need to clean up the state of a thread that has
+        completed a displaced single-step?  (Doing so usually affects
+        the PC, so do it here, before we set stop_pc.)  */
+      displaced_step_fixup (ecs->ptid, ecs->event_thread->stop_signal);
+
+      /* If we either finished a single-step or hit a breakpoint, but
+        the user wanted this thread to be stopped, pretend we got a
+        SIG0 (generic unsignaled stop).  */
+
+      if (ecs->event_thread->stop_requested
+         && ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
+       ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+    }
 
   stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
@@ -2152,7 +2734,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
     {
       fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = 0x%s\n",
                           paddr_nz (stop_pc));
-      if (STOPPED_BY_WATCHPOINT (&ecs->ws))
+      if (target_stopped_by_watchpoint ())
        {
           CORE_ADDR addr;
          fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
@@ -2178,7 +2760,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
       /* We've either finished single-stepping past the single-step
          breakpoint, or stopped for some other reason.  It would be nice if
          we could tell, but we can't reliably.  */
-      if (stop_signal == TARGET_SIGNAL_TRAP)
+      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
        {
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n");
@@ -2198,8 +2780,6 @@ targets should add new threads to the thread list themselves in non-stop mode.")
        }
     }
 
-  stepping_past_singlestep_breakpoint = 0;
-
   if (!ptid_equal (deferred_step_ptid, null_ptid))
     {
       /* In non-stop mode, there's never a deferred_step_ptid set.  */
@@ -2207,7 +2787,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
 
       /* If we stopped for some other reason than single-stepping, ignore
         the fact that we were supposed to switch back.  */
-      if (stop_signal == TARGET_SIGNAL_TRAP)
+      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
        {
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog,
@@ -2239,7 +2819,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
      another thread.  If so, then step that thread past the breakpoint,
      and continue it.  */
 
-  if (stop_signal == TARGET_SIGNAL_TRAP)
+  if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
     {
       int thread_hop_needed = 0;
 
@@ -2293,6 +2873,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
 
             if (new_singlestep_pc != singlestep_pc)
               {
+                enum target_signal stop_signal;
+
                 if (debug_infrun)
                   fprintf_unfiltered (gdb_stdlog, "infrun: unexpected thread,"
                                       " but expected thread advanced also\n");
@@ -2301,7 +2883,11 @@ targets should add new threads to the thread list themselves in non-stop mode.")
                    singlestep_ptid.  Don't swap here, since that's
                    the context we want to use.  Just fudge our
                    state and continue.  */
+                 stop_signal = ecs->event_thread->stop_signal;
+                 ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
                  ecs->ptid = singlestep_ptid;
+                 ecs->event_thread = find_thread_ptid (ecs->ptid);
+                 ecs->event_thread->stop_signal = stop_signal;
                  stop_pc = new_singlestep_pc;
                }
              else
@@ -2324,6 +2910,11 @@ targets should add new threads to the thread list themselves in non-stop mode.")
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: thread_hop_needed\n");
 
+         /* Switch context before touching inferior memory, the
+            previous thread may have exited.  */
+         if (!ptid_equal (inferior_ptid, ecs->ptid))
+           context_switch (ecs->ptid);
+
          /* Saw a breakpoint, but it was hit by the wrong thread.
             Just continue. */
 
@@ -2350,9 +2941,6 @@ targets should add new threads to the thread list themselves in non-stop mode.")
            error (_("Cannot step over breakpoint hit in wrong thread"));
          else
            {                   /* Single step */
-             if (!ptid_equal (inferior_ptid, ecs->ptid))
-               context_switch (ecs->ptid);
-
              if (!non_stop)
                {
                  /* Only need to require the next event from this
@@ -2361,7 +2949,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
                  infwait_state = infwait_thread_hop_state;
                }
 
-             tss->stepping_over_breakpoint = 1;
+             ecs->event_thread->stepping_over_breakpoint = 1;
              keep_going (ecs);
              registers_changed ();
              return;
@@ -2404,7 +2992,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
   /* If necessary, step over this watchpoint.  We'll be back to display
      it in a moment.  */
   if (stopped_by_watchpoint
-      && (HAVE_STEPPABLE_WATCHPOINT
+      && (target_have_steppable_watchpoint
          || gdbarch_have_nonsteppable_watchpoint (current_gdbarch)))
     {
       /* At this point, we are stopped at an instruction which has
@@ -2427,13 +3015,16 @@ targets should add new threads to the thread list themselves in non-stop mode.")
         the inferior over it.  If we have non-steppable watchpoints,
         we must disable the current watchpoint; it's simplest to
         disable all watchpoints and breakpoints.  */
-        
-      if (!HAVE_STEPPABLE_WATCHPOINT)
+      int hw_step = 1;
+
+      if (!target_have_steppable_watchpoint)
        remove_breakpoints ();
+       /* Single step */
+      hw_step = maybe_software_singlestep (current_gdbarch, stop_pc);
+      target_resume (ecs->ptid, hw_step, TARGET_SIGNAL_0);
       registers_changed ();
-      target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);   /* Single step */
       waiton_ptid = ecs->ptid;
-      if (HAVE_STEPPABLE_WATCHPOINT)
+      if (target_have_steppable_watchpoint)
        infwait_state = infwait_step_watch_state;
       else
        infwait_state = infwait_nonstep_watch_state;
@@ -2450,17 +3041,17 @@ targets should add new threads to the thread list themselves in non-stop mode.")
                            &ecs->stop_func_start, &ecs->stop_func_end);
   ecs->stop_func_start
     += gdbarch_deprecated_function_start_offset (current_gdbarch);
-  tss->stepping_over_breakpoint = 0;
-  bpstat_clear (&stop_bpstat);
-  stop_step = 0;
+  ecs->event_thread->stepping_over_breakpoint = 0;
+  bpstat_clear (&ecs->event_thread->stop_bpstat);
+  ecs->event_thread->stop_step = 0;
   stop_print_frame = 1;
   ecs->random_signal = 0;
   stopped_by_random_signal = 0;
 
-  if (stop_signal == TARGET_SIGNAL_TRAP
-      && stepping_over_breakpoint
+  if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
+      && ecs->event_thread->trap_expected
       && gdbarch_single_step_through_delay_p (current_gdbarch)
-      && currently_stepping (tss))
+      && currently_stepping (ecs->event_thread))
     {
       /* We're trying to step off a breakpoint.  Turns out that we're
         also on an instruction that needs to be stepped multiple
@@ -2472,11 +3063,11 @@ targets should add new threads to the thread list themselves in non-stop mode.")
                                             get_current_frame ());
       if (debug_infrun && step_through_delay)
        fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
-      if (step_range_end == 0 && step_through_delay)
+      if (ecs->event_thread->step_range_end == 0 && step_through_delay)
        {
          /* The user issued a continue when stopped at a breakpoint.
             Set up for another trap and get out of here.  */
-         tss->stepping_over_breakpoint = 1;
+         ecs->event_thread->stepping_over_breakpoint = 1;
          keep_going (ecs);
          return;
        }
@@ -2488,7 +3079,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
             case, don't decide that here, just set 
             ecs->stepping_over_breakpoint, making sure we 
             single-step again before breakpoints are re-inserted.  */
-         tss->stepping_over_breakpoint = 1;
+         ecs->event_thread->stepping_over_breakpoint = 1;
        }
     }
 
@@ -2496,7 +3087,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
      The alternatives are:
      1) stop_stepping and return; to really stop and return to the debugger,
      2) keep_going and return to start up again
-     (set tss->stepping_over_breakpoint to 1 to single step once)
+     (set ecs->event_thread->stepping_over_breakpoint to 1 to single step once)
      3) set ecs->random_signal to 1, and the decision between 1 and 2
      will be made according to the signal handling tables.  */
 
@@ -2514,16 +3105,16 @@ targets should add new threads to the thread list themselves in non-stop mode.")
      If we're doing a displaced step past a breakpoint, then the
      breakpoint is always inserted at the original instruction;
      non-standard signals can't be explained by the breakpoint.  */
-  if (stop_signal == TARGET_SIGNAL_TRAP
-      || (! stepping_over_breakpoint
+  if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
+      || (! ecs->event_thread->trap_expected
           && breakpoint_inserted_here_p (stop_pc)
-         && (stop_signal == TARGET_SIGNAL_ILL
-             || stop_signal == TARGET_SIGNAL_SEGV
-             || stop_signal == TARGET_SIGNAL_EMT))
+         && (ecs->event_thread->stop_signal == TARGET_SIGNAL_ILL
+             || ecs->event_thread->stop_signal == TARGET_SIGNAL_SEGV
+             || ecs->event_thread->stop_signal == TARGET_SIGNAL_EMT))
       || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
       || stop_soon == STOP_QUIETLY_REMOTE)
     {
-      if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
+      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
        {
           if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
@@ -2553,18 +3144,27 @@ targets should add new threads to the thread list themselves in non-stop mode.")
         SIGTRAP.  Some systems (e.g. Windows), and stubs supporting
         target extended-remote report it instead of a SIGSTOP
         (e.g. gdbserver).  We already rely on SIGTRAP being our
-        signal, so this is no exception.  */
+        signal, so this is no exception.
+
+        Also consider that the attach is complete when we see a
+        TARGET_SIGNAL_0.  In non-stop mode, GDB will explicitly tell
+        the target to stop all threads of the inferior, in case the
+        low level attach operation doesn't stop them implicitly.  If
+        they weren't stopped implicitly, then the stub will report a
+        TARGET_SIGNAL_0, meaning: stopped for no particular reason
+        other than GDB's request.  */
       if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
-         && (stop_signal == TARGET_SIGNAL_STOP
-             || stop_signal == TARGET_SIGNAL_TRAP))
+         && (ecs->event_thread->stop_signal == TARGET_SIGNAL_STOP
+             || ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
+             || ecs->event_thread->stop_signal == TARGET_SIGNAL_0))
        {
          stop_stepping (ecs);
-         stop_signal = TARGET_SIGNAL_0;
+         ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
          return;
        }
 
       /* See if there is a breakpoint at the current PC.  */
-      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+      ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
       
       /* Following in case break condition called a
         function.  */
@@ -2579,7 +3179,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
          another signal besides SIGTRAP, so check here as well as
          above.''
 
-         If someone ever tries to get get call dummys on a
+         If someone ever tries to get call dummys on a
          non-executable stack to work (where the target would stop
          with something like a SIGSEGV), then those tests might need
          to be re-instated.  Given, however, that the tests were only
@@ -2590,16 +3190,17 @@ targets should add new threads to the thread list themselves in non-stop mode.")
          be necessary for call dummies on a non-executable stack on
          SPARC.  */
 
-      if (stop_signal == TARGET_SIGNAL_TRAP)
+      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
        ecs->random_signal
-         = !(bpstat_explains_signal (stop_bpstat)
-             || stepping_over_breakpoint
-             || (step_range_end && step_resume_breakpoint == NULL));
+         = !(bpstat_explains_signal (ecs->event_thread->stop_bpstat)
+             || ecs->event_thread->trap_expected
+             || (ecs->event_thread->step_range_end
+                 && ecs->event_thread->step_resume_breakpoint == NULL));
       else
        {
-         ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
+         ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
          if (!ecs->random_signal)
-           stop_signal = TARGET_SIGNAL_TRAP;
+           ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
        }
     }
 
@@ -2620,17 +3221,23 @@ process_event_stop_test:
       int printed = 0;
 
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n", stop_signal);
+        fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n",
+                            ecs->event_thread->stop_signal);
 
       stopped_by_random_signal = 1;
 
-      if (signal_print[stop_signal])
+      if (signal_print[ecs->event_thread->stop_signal])
        {
          printed = 1;
          target_terminal_ours_for_output ();
-         print_stop_reason (SIGNAL_RECEIVED, stop_signal);
+         print_stop_reason (SIGNAL_RECEIVED, ecs->event_thread->stop_signal);
        }
-      if (signal_stop_state (stop_signal))
+      /* Always stop on signals if we're either just gaining control
+        of the program, or the user explicitly requested this thread
+        to remain stopped.  */
+      if (stop_soon != NO_STOP_QUIETLY
+         || ecs->event_thread->stop_requested
+         || signal_stop_state (ecs->event_thread->stop_signal))
        {
          stop_stepping (ecs);
          return;
@@ -2641,12 +3248,12 @@ process_event_stop_test:
        target_terminal_inferior ();
 
       /* Clear the signal if it should not be passed.  */
-      if (signal_program[stop_signal] == 0)
-       stop_signal = TARGET_SIGNAL_0;
+      if (signal_program[ecs->event_thread->stop_signal] == 0)
+       ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
 
-      if (prev_pc == read_pc ()
-         && stepping_over_breakpoint
-         && step_resume_breakpoint == NULL)
+      if (ecs->event_thread->prev_pc == stop_pc
+         && ecs->event_thread->trap_expected
+         && ecs->event_thread->step_resume_breakpoint == NULL)
        {
          /* We were just starting a new sequence, attempting to
             single-step off of a breakpoint and expecting a SIGTRAP.
@@ -2664,17 +3271,18 @@ process_event_stop_test:
                                 "breakpoint\n");
 
          insert_step_resume_breakpoint_at_frame (get_current_frame ());
-         tss->step_after_step_resume_breakpoint = 1;
+         ecs->event_thread->step_after_step_resume_breakpoint = 1;
          keep_going (ecs);
          return;
        }
 
-      if (step_range_end != 0
-         && stop_signal != TARGET_SIGNAL_0
-         && stop_pc >= step_range_start && stop_pc < step_range_end
+      if (ecs->event_thread->step_range_end != 0
+         && ecs->event_thread->stop_signal != TARGET_SIGNAL_0
+         && (ecs->event_thread->step_range_start <= stop_pc
+             && stop_pc < ecs->event_thread->step_range_end)
          && frame_id_eq (get_frame_id (get_current_frame ()),
-                         step_frame_id)
-         && step_resume_breakpoint == NULL)
+                         ecs->event_thread->step_frame_id)
+         && ecs->event_thread->step_resume_breakpoint == NULL)
        {
          /* The inferior is about to take a signal that will take it
             out of the single step range.  Set a breakpoint at the
@@ -2710,7 +3318,7 @@ process_event_stop_test:
     CORE_ADDR jmp_buf_pc;
     struct bpstat_what what;
 
-    what = bpstat_what (stop_bpstat);
+    what = bpstat_what (ecs->event_thread->stop_bpstat);
 
     if (what.call_dummy)
       {
@@ -2728,7 +3336,7 @@ process_event_stop_test:
          fprintf_unfiltered (gdb_stdlog,
                              "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
 
-       tss->stepping_over_breakpoint = 1;
+       ecs->event_thread->stepping_over_breakpoint = 1;
 
        if (!gdbarch_get_longjmp_target_p (current_gdbarch)
            || !gdbarch_get_longjmp_target (current_gdbarch,
@@ -2743,8 +3351,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
 
        /* We're going to replace the current step-resume breakpoint
           with a longjmp-resume breakpoint.  */
-       if (step_resume_breakpoint != NULL)
-         delete_step_resume_breakpoint (&step_resume_breakpoint);
+       delete_step_resume_breakpoint (ecs->event_thread);
 
        /* Insert a breakpoint at resume address.  */
        insert_longjmp_resume_breakpoint (jmp_buf_pc);
@@ -2757,10 +3364,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          fprintf_unfiltered (gdb_stdlog,
                              "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
 
-       gdb_assert (step_resume_breakpoint != NULL);
-       delete_step_resume_breakpoint (&step_resume_breakpoint);
+       gdb_assert (ecs->event_thread->step_resume_breakpoint != NULL);
+       delete_step_resume_breakpoint (ecs->event_thread);
 
-       stop_step = 1;
+       ecs->event_thread->stop_step = 1;
        print_stop_reason (END_STEPPING_RANGE, 0);
        stop_stepping (ecs);
        return;
@@ -2768,7 +3375,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
       case BPSTAT_WHAT_SINGLE:
         if (debug_infrun)
          fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SINGLE\n");
-       tss->stepping_over_breakpoint = 1;
+       ecs->event_thread->stepping_over_breakpoint = 1;
        /* Still need to check other stuff, at least the case
           where we are stepping and step out of the right range.  */
        break;
@@ -2796,46 +3403,34 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
        return;
 
       case BPSTAT_WHAT_STEP_RESUME:
-       /* This proably demands a more elegant solution, but, yeah
-          right...
-
-          This function's use of the simple variable
-          step_resume_breakpoint doesn't seem to accomodate
-          simultaneously active step-resume bp's, although the
-          breakpoint list certainly can.
-
-          If we reach here and step_resume_breakpoint is already
-          NULL, then apparently we have multiple active
-          step-resume bp's.  We'll just delete the breakpoint we
-          stopped at, and carry on.  
-
-          Correction: what the code currently does is delete a
-          step-resume bp, but it makes no effort to ensure that
-          the one deleted is the one currently stopped at.  MVS  */
-
         if (debug_infrun)
          fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n");
 
-       if (step_resume_breakpoint == NULL)
-         {
-           step_resume_breakpoint =
-             bpstat_find_step_resume_breakpoint (stop_bpstat);
-         }
-       delete_step_resume_breakpoint (&step_resume_breakpoint);
-       if (tss->step_after_step_resume_breakpoint)
+       delete_step_resume_breakpoint (ecs->event_thread);
+       if (ecs->event_thread->step_after_step_resume_breakpoint)
          {
            /* Back when the step-resume breakpoint was inserted, we
               were trying to single-step off a breakpoint.  Go back
               to doing that.  */
-           tss->step_after_step_resume_breakpoint = 0;
-           tss->stepping_over_breakpoint = 1;
+           ecs->event_thread->step_after_step_resume_breakpoint = 0;
+           ecs->event_thread->stepping_over_breakpoint = 1;
+           keep_going (ecs);
+           return;
+         }
+       if (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;
          }
        break;
 
       case BPSTAT_WHAT_CHECK_SHLIBS:
-      case BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK:
        {
           if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_SHLIBS\n");
@@ -2876,46 +3471,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
              stop_stepping (ecs);
              return;
            }
-
-         /* If we stopped due to an explicit catchpoint, then the
-            (see above) call to SOLIB_ADD pulled in any symbols
-            from a newly-loaded library, if appropriate.
-
-            We do want the inferior to stop, but not where it is
-            now, which is in the dynamic linker callback.  Rather,
-            we would like it stop in the user's program, just after
-            the call that caused this catchpoint to trigger.  That
-            gives the user a more useful vantage from which to
-            examine their program's state. */
-         else if (what.main_action
-                  == BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK)
-           {
-             /* ??rehrauer: If I could figure out how to get the
-                right return PC from here, we could just set a temp
-                breakpoint and resume.  I'm not sure we can without
-                cracking open the dld's shared libraries and sniffing
-                their unwind tables and text/data ranges, and that's
-                not a terribly portable notion.
-
-                Until that time, we must step the inferior out of the
-                dld callback, and also out of the dld itself (and any
-                code or stubs in libdld.sl, such as "shl_load" and
-                friends) until we reach non-dld code.  At that point,
-                we can stop stepping. */
-             bpstat_get_triggered_catchpoints (stop_bpstat,
-                                               &tss->
-                                               stepping_through_solib_catchpoints);
-             tss->stepping_through_solib_after_catch = 1;
-
-             /* Be sure to lift all breakpoints, so the inferior does
-                actually step past this point... */
-             tss->stepping_over_breakpoint = 1;
-             break;
-           }
          else
            {
              /* We want to step over this breakpoint, then keep going.  */
-             tss->stepping_over_breakpoint = 1;
+             ecs->event_thread->stepping_over_breakpoint = 1;
              break;
            }
        }
@@ -2935,10 +3494,62 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
      test for stepping.  But, if not stepping,
      do not stop.  */
 
+  /* In all-stop mode, if we're currently stepping but have stopped in
+     some other thread, we need to switch back to the stepped thread.  */
+  if (!non_stop)
+    {
+      struct thread_info *tp;
+      tp = iterate_over_threads (currently_stepping_or_nexting_callback,
+                                ecs->event_thread);
+      if (tp)
+       {
+         /* However, if the current thread is blocked on some internal
+            breakpoint, and we simply need to step over that breakpoint
+            to get it going again, do that first.  */
+         if ((ecs->event_thread->trap_expected
+              && ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP)
+             || ecs->event_thread->stepping_over_breakpoint)
+           {
+             keep_going (ecs);
+             return;
+           }
+
+         /* If the stepping thread exited, then don't try reverting
+            back to it, just keep going.  We need to query the target
+            in case it doesn't support thread exit events.  */
+         if (is_exited (tp->ptid)
+             || !target_thread_alive (tp->ptid))
+           {
+             if (debug_infrun)
+               fprintf_unfiltered (gdb_stdlog, "\
+infrun: not switching back to stepped thread, it has vanished\n");
+
+             delete_thread (tp->ptid);
+             keep_going (ecs);
+             return;
+           }
+
+         /* Otherwise, we no longer expect a trap in the current thread.
+            Clear the trap_expected flag before switching back -- this is
+            what keep_going would do as well, if we called it.  */
+         ecs->event_thread->trap_expected = 0;
+
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: switching back to stepped thread\n");
+
+         ecs->event_thread = tp;
+         ecs->ptid = tp->ptid;
+         context_switch (ecs->ptid);
+         keep_going (ecs);
+         return;
+       }
+    }
+
   /* Are we stepping to get the inferior out of the dynamic linker's
      hook (and possibly the dld itself) after catching a shlib
      event?  */
-  if (tss->stepping_through_solib_after_catch)
+  if (ecs->event_thread->stepping_through_solib_after_catch)
     {
 #if defined(SOLIB_ADD)
       /* Have we reached our destination?  If not, keep going. */
@@ -2946,7 +3557,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
        {
           if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: stepping in dynamic linker\n");
-         tss->stepping_over_breakpoint = 1;
+         ecs->event_thread->stepping_over_breakpoint = 1;
          keep_going (ecs);
          return;
        }
@@ -2955,16 +3566,17 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
         fprintf_unfiltered (gdb_stdlog, "infrun: step past dynamic linker\n");
       /* Else, stop and report the catchpoint(s) whose triggering
          caused us to begin stepping. */
-      tss->stepping_through_solib_after_catch = 0;
-      bpstat_clear (&stop_bpstat);
-      stop_bpstat = bpstat_copy (tss->stepping_through_solib_catchpoints);
-      bpstat_clear (&tss->stepping_through_solib_catchpoints);
+      ecs->event_thread->stepping_through_solib_after_catch = 0;
+      bpstat_clear (&ecs->event_thread->stop_bpstat);
+      ecs->event_thread->stop_bpstat
+       = bpstat_copy (ecs->event_thread->stepping_through_solib_catchpoints);
+      bpstat_clear (&ecs->event_thread->stepping_through_solib_catchpoints);
       stop_print_frame = 1;
       stop_stepping (ecs);
       return;
     }
 
-  if (step_resume_breakpoint)
+  if (ecs->event_thread->step_resume_breakpoint)
     {
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog,
@@ -2977,7 +3589,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
       return;
     }
 
-  if (step_range_end == 0)
+  if (ecs->event_thread->step_range_end == 0)
     {
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: no stepping, continue\n");
@@ -2988,16 +3600,31 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
 
   /* If stepping through a line, keep going if still within it.
 
-     Note that step_range_end is the address of the first instruction
-     beyond the step range, and NOT the address of the last instruction
-     within it! */
-  if (stop_pc >= step_range_start && stop_pc < step_range_end)
-    {
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: stepping inside range [0x%s-0x%s]\n",
-                           paddr_nz (step_range_start),
-                           paddr_nz (step_range_end));
-      keep_going (ecs);
+     Note that step_range_end is the address of the first instruction
+     beyond the step range, and NOT the address of the last instruction
+     within it! */
+  if (stop_pc >= ecs->event_thread->step_range_start
+      && stop_pc < ecs->event_thread->step_range_end)
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "infrun: stepping inside range [0x%s-0x%s]\n",
+                           paddr_nz (ecs->event_thread->step_range_start),
+                           paddr_nz (ecs->event_thread->step_range_end));
+
+      /* When stepping backward, stop at beginning of line range
+        (unless it's the function entry point, in which case
+        keep going back to the call point).  */
+      if (stop_pc == ecs->event_thread->step_range_start
+         && stop_pc != ecs->stop_func_start
+         && execution_direction == EXEC_REVERSE)
+       {
+         ecs->event_thread->stop_step = 1;
+         print_stop_reason (END_STEPPING_RANGE, 0);
+         stop_stepping (ecs);
+       }
+      else
+       keep_going (ecs);
+
       return;
     }
 
@@ -3007,13 +3634,8 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
      loader dynamic symbol resolution code, we keep on single stepping
      until we exit the run time loader code and reach the callee's
      address.  */
-  if (step_over_calls == STEP_OVER_UNDEBUGGABLE
-#ifdef IN_SOLIB_DYNSYM_RESOLVE_CODE
-      && IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc)
-#else
-      && in_solib_dynsym_resolve_code (stop_pc)
-#endif
-      )
+  if (ecs->event_thread->step_over_calls == STEP_OVER_UNDEBUGGABLE
+      && in_solib_dynsym_resolve_code (stop_pc))
     {
       CORE_ADDR pc_after_resolver =
        gdbarch_skip_solib_resolver (current_gdbarch, stop_pc);
@@ -3036,9 +3658,9 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
       return;
     }
 
-  if (step_range_end != 1
-      && (step_over_calls == STEP_OVER_UNDEBUGGABLE
-         || step_over_calls == STEP_OVER_ALL)
+  if (ecs->event_thread->step_range_end != 1
+      && (ecs->event_thread->step_over_calls == STEP_OVER_UNDEBUGGABLE
+         || ecs->event_thread->step_over_calls == STEP_OVER_ALL)
       && get_frame_type (get_current_frame ()) == SIGTRAMP_FRAME)
     {
       if (debug_infrun)
@@ -3060,17 +3682,21 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
      NOTE: frame_id_eq will never report two invalid frame IDs as
      being equal, so to get into this block, both the current and
      previous frame must have valid frame IDs.  */
-  if (!frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id)
-      && frame_id_eq (frame_unwind_id (get_current_frame ()), step_frame_id))
+  if (!frame_id_eq (get_frame_id (get_current_frame ()),
+                   ecs->event_thread->step_frame_id)
+      && (frame_id_eq (frame_unwind_id (get_current_frame ()),
+                      ecs->event_thread->step_frame_id)
+         || execution_direction == EXEC_REVERSE))
     {
       CORE_ADDR real_stop_pc;
 
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepped into subroutine\n");
 
-      if ((step_over_calls == STEP_OVER_NONE)
-         || ((step_range_end == 1)
-             && in_prologue (prev_pc, ecs->stop_func_start)))
+      if ((ecs->event_thread->step_over_calls == STEP_OVER_NONE)
+         || ((ecs->event_thread->step_range_end == 1)
+             && in_prologue (ecs->event_thread->prev_pc,
+                             ecs->stop_func_start)))
        {
          /* I presume that step_over_calls is only 0 when we're
             supposed to be stepping at the assembly language level
@@ -3078,18 +3704,51 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          /* Also, maybe we just did a "nexti" inside a prolog, so we
             thought it was a subroutine call but it was not.  Stop as
             well.  FENN */
-         stop_step = 1;
+         ecs->event_thread->stop_step = 1;
          print_stop_reason (END_STEPPING_RANGE, 0);
          stop_stepping (ecs);
          return;
        }
 
-      if (step_over_calls == STEP_OVER_ALL)
+      if (ecs->event_thread->step_over_calls == STEP_OVER_ALL)
        {
-         /* We're doing a "next", set a breakpoint at callee's return
-            address (the address at which the caller will
-            resume).  */
-         insert_step_resume_breakpoint_at_caller (get_current_frame ());
+         /* We're doing a "next".
+
+            Normal (forward) execution: set a breakpoint at the
+            callee's return address (the address at which the caller
+            will resume).
+
+            Reverse (backward) execution.  set the step-resume
+            breakpoint at the start of the function that we just
+            stepped into (backwards), and continue to there.  When we
+            get there, we'll need to single-step back to the caller.  */
+
+         if (execution_direction == EXEC_REVERSE)
+           {
+             struct symtab_and_line sr_sal;
+
+             if (ecs->stop_func_start == 0 
+                 && in_solib_dynsym_resolve_code (stop_pc))
+               {
+                 /* Stepped into runtime loader dynamic symbol
+                    resolution code.  Since we're in reverse, 
+                    we have already backed up through the runtime
+                    loader and the dynamic function.  This is just
+                    the trampoline (jump table).
+
+                    Just keep stepping, we'll soon be home.
+                 */
+                 keep_going (ecs);
+                 return;
+               }
+             /* Normal (staticly linked) function call return.  */
+             init_sal (&sr_sal);
+             sr_sal.pc = ecs->stop_func_start;
+             insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
+           }
+         else
+           insert_step_resume_breakpoint_at_caller (get_current_frame ());
+
          keep_going (ecs);
          return;
        }
@@ -3106,13 +3765,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
       if (real_stop_pc != 0)
        ecs->stop_func_start = real_stop_pc;
 
-      if (
-#ifdef IN_SOLIB_DYNSYM_RESOLVE_CODE
-         IN_SOLIB_DYNSYM_RESOLVE_CODE (ecs->stop_func_start)
-#else
-         in_solib_dynsym_resolve_code (ecs->stop_func_start)
-#endif
-)
+      if (real_stop_pc != 0 && in_solib_dynsym_resolve_code (real_stop_pc))
        {
          struct symtab_and_line sr_sal;
          init_sal (&sr_sal);
@@ -3135,7 +3788,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
        tmp_sal = find_pc_line (ecs->stop_func_start, 0);
        if (tmp_sal.line != 0)
          {
-           step_into_function (ecs);
+           if (execution_direction == EXEC_REVERSE)
+             handle_step_into_function_backward (ecs);
+           else
+             handle_step_into_function (ecs);
            return;
          }
       }
@@ -3143,17 +3799,29 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
       /* If we have no line number and the step-stop-if-no-debug is
          set, we stop the step so that the user has a chance to switch
          in assembly mode.  */
-      if (step_over_calls == STEP_OVER_UNDEBUGGABLE && step_stop_if_no_debug)
+      if (ecs->event_thread->step_over_calls == STEP_OVER_UNDEBUGGABLE
+         && step_stop_if_no_debug)
        {
-         stop_step = 1;
+         ecs->event_thread->stop_step = 1;
          print_stop_reason (END_STEPPING_RANGE, 0);
          stop_stepping (ecs);
          return;
        }
 
-      /* Set a breakpoint at callee's return address (the address at
-         which the caller will resume).  */
-      insert_step_resume_breakpoint_at_caller (get_current_frame ());
+      if (execution_direction == EXEC_REVERSE)
+       {
+         /* Set a breakpoint at callee's start address.
+            From there we can step once and be back in the caller.  */
+         struct symtab_and_line sr_sal;
+         init_sal (&sr_sal);
+         sr_sal.pc = ecs->stop_func_start;
+         insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
+       }
+      else
+       /* Set a breakpoint at callee's return address (the address
+          at which the caller will resume).  */
+       insert_step_resume_breakpoint_at_caller (get_current_frame ());
+
       keep_going (ecs);
       return;
     }
@@ -3193,14 +3861,14 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
        }
     }
 
-  tss->sal = find_pc_line (stop_pc, 0);
+  stop_pc_sal = find_pc_line (stop_pc, 0);
 
   /* NOTE: tausq/2004-05-24: This if block used to be done before all
      the trampoline processing logic, however, there are some trampolines 
      that have no names, so we should do trampoline handling first.  */
-  if (step_over_calls == STEP_OVER_UNDEBUGGABLE
+  if (ecs->event_thread->step_over_calls == STEP_OVER_UNDEBUGGABLE
       && ecs->stop_func_name == NULL
-      && tss->sal.line == 0)
+      && stop_pc_sal.line == 0)
     {
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n");
@@ -3219,7 +3887,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          /* If we have no line number and the step-stop-if-no-debug
             is set, we stop the step so that the user has a chance to
             switch in assembly mode.  */
-         stop_step = 1;
+         ecs->event_thread->stop_step = 1;
          print_stop_reason (END_STEPPING_RANGE, 0);
          stop_stepping (ecs);
          return;
@@ -3234,19 +3902,19 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
        }
     }
 
-  if (step_range_end == 1)
+  if (ecs->event_thread->step_range_end == 1)
     {
       /* It is stepi or nexti.  We always want to stop stepping after
          one instruction.  */
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepi/nexti\n");
-      stop_step = 1;
+      ecs->event_thread->stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
       return;
     }
 
-  if (tss->sal.line == 0)
+  if (stop_pc_sal.line == 0)
     {
       /* We have no line number information.  That means to stop
          stepping (does this always happen right after one instruction,
@@ -3254,15 +3922,15 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          or can this happen as a result of a return or longjmp?).  */
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
-      stop_step = 1;
+      ecs->event_thread->stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
       return;
     }
 
-  if ((stop_pc == tss->sal.pc)
-      && (tss->current_line != tss->sal.line
-         || tss->current_symtab != tss->sal.symtab))
+  if ((stop_pc == stop_pc_sal.pc)
+      && (ecs->event_thread->current_line != stop_pc_sal.line
+         || ecs->event_thread->current_symtab != stop_pc_sal.symtab))
     {
       /* We are at the start of a different line.  So stop.  Note that
          we don't stop if we step into the middle of a different line.
@@ -3270,7 +3938,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          better.  */
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different line\n");
-      stop_step = 1;
+      ecs->event_thread->stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
       return;
@@ -3283,80 +3951,68 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
      new line in mid-statement, we continue stepping.  This makes
      things like for(;;) statements work better.)  */
 
-  step_range_start = tss->sal.pc;
-  step_range_end = tss->sal.end;
-  step_frame_id = get_frame_id (get_current_frame ());
-  tss->current_line = tss->sal.line;
-  tss->current_symtab = tss->sal.symtab;
-
-  /* In the case where we just stepped out of a function into the
-     middle of a line of the caller, continue stepping, but
-     step_frame_id must be modified to current frame */
-#if 0
-  /* NOTE: cagney/2003-10-16: I think this frame ID inner test is too
-     generous.  It will trigger on things like a step into a frameless
-     stackless leaf function.  I think the logic should instead look
-     at the unwound frame ID has that should give a more robust
-     indication of what happened.  */
-  if (step - ID == current - ID)
-    still stepping in same function;
-  else if (step - ID == unwind (current - ID))
-    stepped into a function;
-  else
-    stepped out of a function;
-  /* Of course this assumes that the frame ID unwind code is robust
-     and we're willing to introduce frame unwind logic into this
-     function.  Fortunately, those days are nearly upon us.  */
-#endif
-  {
-    struct frame_info *frame = get_current_frame ();
-    struct frame_id current_frame = get_frame_id (frame);
-    if (!(frame_id_inner (get_frame_arch (frame), current_frame,
-                         step_frame_id)))
-      step_frame_id = current_frame;
-  }
+  ecs->event_thread->step_range_start = stop_pc_sal.pc;
+  ecs->event_thread->step_range_end = stop_pc_sal.end;
+  ecs->event_thread->step_frame_id = get_frame_id (get_current_frame ());
+  ecs->event_thread->current_line = stop_pc_sal.line;
+  ecs->event_thread->current_symtab = stop_pc_sal.symtab;
 
   if (debug_infrun)
      fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n");
   keep_going (ecs);
 }
 
-/* Are we in the middle of stepping?  */
+/* Is thread TP in the middle of single-stepping?  */
+
+static int
+currently_stepping (struct thread_info *tp)
+{
+  return ((tp->step_range_end && tp->step_resume_breakpoint == NULL)
+         || tp->trap_expected
+         || tp->stepping_through_solib_after_catch
+         || bpstat_should_step ());
+}
+
+/* Returns true if any thread *but* the one passed in "data" is in the
+   middle of stepping or of handling a "next".  */
 
 static int
-currently_stepping (struct thread_stepping_state *tss)
+currently_stepping_or_nexting_callback (struct thread_info *tp, void *data)
 {
-  return (((step_range_end && step_resume_breakpoint == NULL)
-          || stepping_over_breakpoint)
-         || tss->stepping_through_solib_after_catch
-         || bpstat_should_step ());
+  if (tp == data)
+    return 0;
+
+  return (tp->step_range_end
+         || tp->trap_expected
+         || tp->stepping_through_solib_after_catch);
 }
 
-/* Subroutine call with source code we should not step over.  Do step
-   to the first line of code in it.  */
+/* Inferior has stepped into a subroutine call with source code that
+   we should not step over.  Do step to the first line of code in
+   it.  */
 
 static void
-step_into_function (struct execution_control_state *ecs)
+handle_step_into_function (struct execution_control_state *ecs)
 {
   struct symtab *s;
-  struct symtab_and_line sr_sal;
+  struct symtab_and_line stop_func_sal, sr_sal;
 
   s = find_pc_symtab (stop_pc);
   if (s && s->language != language_asm)
-    ecs->stop_func_start = gdbarch_skip_prologue
-                            (current_gdbarch, ecs->stop_func_start);
+    ecs->stop_func_start = gdbarch_skip_prologue (current_gdbarch, 
+                                                 ecs->stop_func_start);
 
-  tss->sal = find_pc_line (ecs->stop_func_start, 0);
+  stop_func_sal = find_pc_line (ecs->stop_func_start, 0);
   /* Use the step_resume_break to step until the end of the prologue,
      even if that involves jumps (as it seems to on the vax under
      4.2).  */
   /* If the prologue ends in the middle of a source line, continue to
      the end of that source line (if it is still within the function).
      Otherwise, just go to end of prologue.  */
-  if (tss->sal.end
-      && tss->sal.pc != ecs->stop_func_start
-      && tss->sal.end < ecs->stop_func_end)
-    ecs->stop_func_start = tss->sal.end;
+  if (stop_func_sal.end
+      && stop_func_sal.pc != ecs->stop_func_start
+      && stop_func_sal.end < ecs->stop_func_end)
+    ecs->stop_func_start = stop_func_sal.end;
 
   /* Architectures which require breakpoint adjustment might not be able
      to place a breakpoint at the computed address.  If so, the test
@@ -3384,7 +4040,7 @@ step_into_function (struct execution_control_state *ecs)
   if (ecs->stop_func_start == stop_pc)
     {
       /* We are already there: stop now.  */
-      stop_step = 1;
+      ecs->event_thread->stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
       return;
@@ -3402,11 +4058,48 @@ step_into_function (struct execution_control_state *ecs)
       insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
 
       /* And make sure stepping stops right away then.  */
-      step_range_end = step_range_start;
+      ecs->event_thread->step_range_end = ecs->event_thread->step_range_start;
     }
   keep_going (ecs);
 }
 
+/* Inferior has stepped backward into a subroutine call with source
+   code that we should not step over.  Do step to the beginning of the
+   last line of code in it.  */
+
+static void
+handle_step_into_function_backward (struct execution_control_state *ecs)
+{
+  struct symtab *s;
+  struct symtab_and_line stop_func_sal, sr_sal;
+
+  s = find_pc_symtab (stop_pc);
+  if (s && s->language != language_asm)
+    ecs->stop_func_start = gdbarch_skip_prologue (current_gdbarch, 
+                                                 ecs->stop_func_start);
+
+  stop_func_sal = find_pc_line (stop_pc, 0);
+
+  /* OK, we're just going to keep stepping here.  */
+  if (stop_func_sal.pc == stop_pc)
+    {
+      /* We're there already.  Just stop stepping now.  */
+      ecs->event_thread->stop_step = 1;
+      print_stop_reason (END_STEPPING_RANGE, 0);
+      stop_stepping (ecs);
+    }
+  else
+    {
+      /* Else just reset the step range and keep going.
+        No step-resume breakpoint, they don't work for
+        epilogues, which can have multiple entry paths.  */
+      ecs->event_thread->step_range_start = stop_func_sal.pc;
+      ecs->event_thread->step_range_end = stop_func_sal.end;
+      keep_going (ecs);
+    }
+  return;
+}
+
 /* Insert a "step-resume breakpoint" at SR_SAL with frame ID SR_ID.
    This is used to both functions and to skip over code.  */
 
@@ -3417,15 +4110,15 @@ insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal,
   /* There should never be more than one step-resume or longjmp-resume
      breakpoint per thread, so we should never be setting a new
      step_resume_breakpoint when one is already active.  */
-  gdb_assert (step_resume_breakpoint == NULL);
+  gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL);
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
                        "infrun: inserting step-resume breakpoint at 0x%s\n",
                        paddr_nz (sr_sal.pc));
 
-  step_resume_breakpoint = set_momentary_breakpoint (sr_sal, sr_id,
-                                                    bp_step_resume);
+  inferior_thread ()->step_resume_breakpoint
+    = set_momentary_breakpoint (sr_sal, sr_id, bp_step_resume);
 }
 
 /* Insert a "step-resume breakpoint" at RETURN_FRAME.pc.  This is used
@@ -3494,14 +4187,14 @@ insert_longjmp_resume_breakpoint (CORE_ADDR pc)
   /* There should never be more than one step-resume or longjmp-resume
      breakpoint per thread, so we should never be setting a new
      longjmp_resume_breakpoint when one is already active.  */
-  gdb_assert (step_resume_breakpoint == NULL);
+  gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL);
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
                        "infrun: inserting longjmp-resume breakpoint at 0x%s\n",
                        paddr_nz (pc));
 
-  step_resume_breakpoint =
+  inferior_thread ()->step_resume_breakpoint =
     set_momentary_breakpoint_at_pc (pc, bp_longjmp_resume);
 }
 
@@ -3523,17 +4216,20 @@ static void
 keep_going (struct execution_control_state *ecs)
 {
   /* Save the pc before execution, to compare with pc after stop.  */
-  prev_pc = read_pc ();                /* Might have been DECR_AFTER_BREAK */
+  ecs->event_thread->prev_pc
+    = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
   /* If we did not do break;, it means we should keep running the
      inferior and not return to debugger.  */
 
-  if (stepping_over_breakpoint && stop_signal != TARGET_SIGNAL_TRAP)
+  if (ecs->event_thread->trap_expected
+      && ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP)
     {
       /* We took a signal (which we are supposed to pass through to
-         the inferior, else we'd have done a break above) and we
-         haven't yet gotten our trap.  Simply continue.  */
-      resume (currently_stepping (tss), stop_signal);
+        the inferior, else we'd not get here) and we haven't yet
+        gotten our trap.  Simply continue.  */
+      resume (currently_stepping (ecs->event_thread),
+             ecs->event_thread->stop_signal);
     }
   else
     {
@@ -3550,7 +4246,7 @@ keep_going (struct execution_control_state *ecs)
         already inserted breakpoints.  Therefore, we don't
         care if breakpoints were already inserted, or not.  */
       
-      if (tss->stepping_over_breakpoint)
+      if (ecs->event_thread->stepping_over_breakpoint)
        {
          if (! use_displaced_stepping (current_gdbarch))
            /* Since we can't do a displaced step, we have to remove
@@ -3574,7 +4270,7 @@ keep_going (struct execution_control_state *ecs)
            }
        }
 
-      stepping_over_breakpoint = tss->stepping_over_breakpoint;
+      ecs->event_thread->trap_expected = ecs->event_thread->stepping_over_breakpoint;
 
       /* Do not deliver SIGNAL_TRAP (except when the user explicitly
          specifies that such a signal should be delivered to the
@@ -3588,11 +4284,12 @@ keep_going (struct execution_control_state *ecs)
          simulator; the simulator then delivers the hardware
          equivalent of a SIGNAL_TRAP to the program being debugged. */
 
-      if (stop_signal == TARGET_SIGNAL_TRAP && !signal_program[stop_signal])
-       stop_signal = TARGET_SIGNAL_0;
+      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
+         && !signal_program[ecs->event_thread->stop_signal])
+       ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
 
-
-      resume (currently_stepping (tss), stop_signal);
+      resume (currently_stepping (ecs->event_thread),
+             ecs->event_thread->stop_signal);
     }
 
   prepare_to_wait (ecs);
@@ -3641,7 +4338,8 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
       /* For now print nothing. */
       /* Print a message only if not in the middle of doing a "step n"
          operation for n > 1 */
-      if (!step_multi || !stop_step)
+      if (!inferior_thread ()->step_multi
+         || !inferior_thread ()->stop_step)
        if (ui_out_is_mi_like_p (uiout))
          ui_out_field_string
            (uiout, "reason",
@@ -3692,24 +4390,42 @@ print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
       return_child_result_value = stop_info;
       break;
     case SIGNAL_RECEIVED:
-      /* Signal received. The signal table tells us to print about
-         it. */
+      /* Signal received.  The signal table tells us to print about
+        it. */
       annotate_signal ();
-      ui_out_text (uiout, "\nProgram received signal ");
-      annotate_signal_name ();
-      if (ui_out_is_mi_like_p (uiout))
-       ui_out_field_string
-         (uiout, "reason", async_reason_lookup (EXEC_ASYNC_SIGNAL_RECEIVED));
-      ui_out_field_string (uiout, "signal-name",
-                          target_signal_to_name (stop_info));
-      annotate_signal_name_end ();
-      ui_out_text (uiout, ", ");
-      annotate_signal_string ();
-      ui_out_field_string (uiout, "signal-meaning",
-                          target_signal_to_string (stop_info));
-      annotate_signal_string_end ();
+
+      if (stop_info == TARGET_SIGNAL_0 && !ui_out_is_mi_like_p (uiout))
+       {
+         struct thread_info *t = inferior_thread ();
+
+         ui_out_text (uiout, "\n[");
+         ui_out_field_string (uiout, "thread-name",
+                              target_pid_to_str (t->ptid));
+         ui_out_field_fmt (uiout, "thread-id", "] #%d", t->num);
+         ui_out_text (uiout, " stopped");
+       }
+      else
+       {
+         ui_out_text (uiout, "\nProgram received signal ");
+         annotate_signal_name ();
+         if (ui_out_is_mi_like_p (uiout))
+           ui_out_field_string
+             (uiout, "reason", async_reason_lookup (EXEC_ASYNC_SIGNAL_RECEIVED));
+         ui_out_field_string (uiout, "signal-name",
+                              target_signal_to_name (stop_info));
+         annotate_signal_name_end ();
+         ui_out_text (uiout, ", ");
+         annotate_signal_string ();
+         ui_out_field_string (uiout, "signal-meaning",
+                              target_signal_to_string (stop_info));
+         annotate_signal_string_end ();
+       }
       ui_out_text (uiout, ".\n");
       break;
+    case NO_HISTORY:
+      /* Reverse execution: target ran out of history info.  */
+      ui_out_text (uiout, "\nNo more reverse-execution history.\n");
+      break;
     default:
       internal_error (__FILE__, __LINE__,
                      _("print_stop_reason: unrecognized enum value"));
@@ -3731,9 +4447,23 @@ normal_stop (void)
 {
   struct target_waitstatus last;
   ptid_t last_ptid;
+  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
 
   get_last_target_status (&last_ptid, &last);
 
+  /* If an exception is thrown from this point on, make sure to
+     propagate GDB's knowledge of the executing state to the
+     frontend/user running state.  A QUIT is an easy exception to see
+     here, so do this before any filtered output.  */
+  if (target_has_execution)
+    {
+      if (!non_stop)
+       make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+      else if (last.kind != TARGET_WAITKIND_SIGNALLED
+              && last.kind != TARGET_WAITKIND_EXITED)
+       make_cleanup (finish_thread_state_cleanup, &inferior_ptid);
+    }
+
   /* In non-stop mode, we don't want GDB to switch threads behind the
      user's back, to avoid races where the user is typing a command to
      apply to thread x, but GDB switches to thread y before the user
@@ -3759,17 +4489,6 @@ normal_stop (void)
       previous_inferior_ptid = inferior_ptid;
     }
 
-  /* NOTE drow/2004-01-17: Is this still necessary?  */
-  /* Make sure that the current_frame's pc is correct.  This
-     is a correction for setting up the frame info before doing
-     gdbarch_decr_pc_after_break */
-  if (target_has_execution)
-    /* FIXME: cagney/2002-12-06: Has the PC changed?  Thanks to
-       gdbarch_decr_pc_after_break, the program counter can change.  Ask the
-       frame code to check for this and sort out any resultant mess.
-       gdbarch_decr_pc_after_break needs to just go away.  */
-    deprecated_update_frame_pc_hack (get_current_frame (), read_pc ());
-
   if (!breakpoints_always_inserted_mode () && target_has_execution)
     {
       if (remove_breakpoints ())
@@ -3777,7 +4496,6 @@ normal_stop (void)
          target_terminal_ours_for_output ();
          printf_filtered (_("\
 Cannot remove breakpoints because program is no longer writable.\n\
-It might be running in another process.\n\
 Further execution is probably impossible.\n"));
        }
     }
@@ -3790,7 +4508,11 @@ Further execution is probably impossible.\n"));
 
   /* Don't print a message if in the middle of doing a "step n"
      operation for n > 1 */
-  if (step_multi && stop_step)
+  if (target_has_execution
+      && last.kind != TARGET_WAITKIND_SIGNALLED
+      && last.kind != TARGET_WAITKIND_EXITED
+      && inferior_thread ()->step_multi
+      && inferior_thread ()->stop_step)
     goto done;
 
   target_terminal_ours ();
@@ -3798,20 +4520,24 @@ Further execution is probably impossible.\n"));
   /* Set the current source location.  This will also happen if we
      display the frame below, but the current SAL will be incorrect
      during a user hook-stop function.  */
-  if (target_has_stack && !stop_stack_dummy)
+  if (has_stack_frames () && !stop_stack_dummy)
     set_current_sal_from_frame (get_current_frame (), 1);
 
+  /* Let the user/frontend see the threads as stopped.  */
+  do_cleanups (old_chain);
+
   /* Look up the hook_stop and run it (CLI internally handles problem
      of stop_command's pre-hook not existing).  */
   if (stop_command)
     catch_errors (hook_stop_stub, stop_command,
                  "Error while running hook_stop:\n", RETURN_MASK_ALL);
 
-  if (!target_has_stack)
-    {
+  if (!has_stack_frames ())
+    goto done;
 
-      goto done;
-    }
+  if (last.kind == TARGET_WAITKIND_SIGNALLED
+      || last.kind == TARGET_WAITKIND_EXITED)
+    goto done;
 
   /* Select innermost stack frame - i.e., current frame is frame 0,
      and current location is based on that.
@@ -3836,8 +4562,9 @@ Further execution is probably impossible.\n"));
          int bpstat_ret;
          int source_flag;
          int do_frame_printing = 1;
+         struct thread_info *tp = inferior_thread ();
 
-         bpstat_ret = bpstat_print (stop_bpstat);
+         bpstat_ret = bpstat_print (tp->stop_bpstat);
          switch (bpstat_ret)
            {
            case PRINT_UNKNOWN:
@@ -3856,8 +4583,8 @@ Further execution is probably impossible.\n"));
              /* FIXME: cagney/2002-12-01: Given that a frame ID does
                 (or should) carry around the function and does (or
                 should) use that when doing a frame comparison.  */
-             if (stop_step
-                 && frame_id_eq (step_frame_id,
+             if (tp->stop_step
+                 && frame_id_eq (tp->step_frame_id,
                                  get_frame_id (get_current_frame ()))
                  && step_start_function == find_pc_function (stop_pc))
                source_flag = SRC_LINE; /* finished step, just print source line */
@@ -3878,22 +4605,6 @@ Further execution is probably impossible.\n"));
              internal_error (__FILE__, __LINE__, _("Unknown value."));
            }
 
-         if (ui_out_is_mi_like_p (uiout))
-           {
-
-             ui_out_field_int (uiout, "thread-id",
-                               pid_to_thread_id (inferior_ptid));
-             if (non_stop)
-               {
-                 struct cleanup *back_to = make_cleanup_ui_out_list_begin_end 
-                   (uiout, "stopped-threads");
-                 ui_out_field_int (uiout, NULL,
-                                   pid_to_thread_id (inferior_ptid));                            
-                 do_cleanups (back_to);
-               }
-             else
-               ui_out_field_string (uiout, "stopped-threads", "all");
-           }
          /* The behavior of this routine with respect to the source
             flag is:
             SRC_LINE: Print only source line
@@ -3909,7 +4620,7 @@ Further execution is probably impossible.\n"));
 
   /* Save the function value return registers, if we care.
      We might be about to restore their previous contents.  */
-  if (proceed_to_finish)
+  if (inferior_thread ()->proceed_to_finish)
     {
       /* This should not be necessary.  */
       if (stop_registers)
@@ -3922,33 +4633,60 @@ Further execution is probably impossible.\n"));
 
   if (stop_stack_dummy)
     {
-      /* Pop the empty frame that contains the stack dummy.  POP_FRAME
-         ends with a setting of the current frame, so we can use that
-         next. */
-      frame_pop (get_current_frame ());
-      /* Set stop_pc to what it was before we called the function.
-         Can't rely on restore_inferior_status because that only gets
-         called if we don't stop in the called function.  */
-      stop_pc = read_pc ();
+      /* Pop the empty frame that contains the stack dummy.
+        This also restores inferior state prior to the call
+        (struct inferior_thread_state).  */
+      struct frame_info *frame = get_current_frame ();
+      gdb_assert (get_frame_type (frame) == DUMMY_FRAME);
+      frame_pop (frame);
+      /* frame_pop() calls reinit_frame_cache as the last thing it does
+        which means there's currently no selected frame.  We don't need
+        to re-establish a selected frame if the dummy call returns normally,
+        that will be done by restore_inferior_status.  However, we do have
+        to handle the case where the dummy call is returning after being
+        stopped (e.g. the dummy call previously hit a breakpoint).  We
+        can't know which case we have so just always re-establish a
+        selected frame here.  */
       select_frame (get_current_frame ());
     }
 
 done:
   annotate_stopped ();
-  if (!suppress_stop_observer && !step_multi)
-    observer_notify_normal_stop (stop_bpstat);
-  /* Delete the breakpoint we stopped at, if it wants to be deleted.
-     Delete any breakpoint that is to be deleted at the next stop.  */
-  breakpoint_auto_delete (stop_bpstat);
 
-  if (target_has_execution
-      && last.kind != TARGET_WAITKIND_SIGNALLED
-      && last.kind != TARGET_WAITKIND_EXITED)
+  /* Suppress the stop observer if we're in the middle of:
+
+     - a step n (n > 1), as there still more steps to be done.
+
+     - a "finish" command, as the observer will be called in
+       finish_command_continuation, so it can include the inferior
+       function's return value.
+
+     - calling an inferior function, as we pretend we inferior didn't
+       run at all.  The return value of the call is handled by the
+       expression evaluator, through call_function_by_hand.  */
+
+  if (!target_has_execution
+      || last.kind == TARGET_WAITKIND_SIGNALLED
+      || last.kind == TARGET_WAITKIND_EXITED
+      || (!inferior_thread ()->step_multi
+         && !(inferior_thread ()->stop_bpstat
+              && inferior_thread ()->proceed_to_finish)
+         && !inferior_thread ()->in_infcall))
     {
-      if (!non_stop)
-       set_running (pid_to_ptid (-1), 0);
+      if (!ptid_equal (inferior_ptid, null_ptid))
+       observer_notify_normal_stop (inferior_thread ()->stop_bpstat,
+                                    stop_print_frame);
       else
-       set_running (inferior_ptid, 0);
+       observer_notify_normal_stop (NULL, stop_print_frame);
+    }
+
+  if (target_has_execution)
+    {
+      if (last.kind != TARGET_WAITKIND_SIGNALLED
+         && last.kind != TARGET_WAITKIND_EXITED)
+       /* Delete the breakpoint we stopped at, if it wants to be deleted.
+          Delete any breakpoint that is to be deleted at the next stop.  */
+       breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
     }
 }
 
@@ -3962,9 +4700,7 @@ hook_stop_stub (void *cmd)
 int
 signal_stop_state (int signo)
 {
-  /* Always stop on signals if we're just gaining control of the
-     program.  */
-  return signal_stop[signo] || stop_soon != NO_STOP_QUIETLY;
+  return signal_stop[signo];
 }
 
 int
@@ -4013,7 +4749,7 @@ Signal        Stop\tPrint\tPass to program\tDescription\n"));
 static void
 sig_print_info (enum target_signal oursig)
 {
-  char *name = target_signal_to_name (oursig);
+  const char *name = target_signal_to_name (oursig);
   int name_padding = 13 - strlen (name);
 
   if (name_padding <= 0)
@@ -4054,11 +4790,7 @@ handle_command (char *args, int from_tty)
 
   /* Break the command line up into args. */
 
-  argv = buildargv (args);
-  if (argv == NULL)
-    {
-      nomem (0);
-    }
+  argv = gdb_buildargv (args);
   old_chain = make_cleanup_freeargv (argv);
 
   /* Walk through the args, looking for signal oursigs, signal names, and
@@ -4165,8 +4897,8 @@ handle_command (char *args, int from_tty)
            case TARGET_SIGNAL_INT:
              if (!allsigs && !sigs[signum])
                {
-                 if (query ("%s is used by the debugger.\n\
-Are you sure you want to change it? ", target_signal_to_name ((enum target_signal) signum)))
+                 if (query (_("%s is used by the debugger.\n\
+Are you sure you want to change it? "), target_signal_to_name ((enum target_signal) signum)))
                    {
                      sigs[signum] = 1;
                    }
@@ -4191,20 +4923,22 @@ Are you sure you want to change it? ", target_signal_to_name ((enum target_signa
       argv++;
     }
 
-  target_notice_signals (inferior_ptid);
+  for (signum = 0; signum < nsigs; signum++)
+    if (sigs[signum])
+      {
+       target_notice_signals (inferior_ptid);
 
-  if (from_tty)
-    {
-      /* Show the results.  */
-      sig_print_header ();
-      for (signum = 0; signum < nsigs; signum++)
-       {
-         if (sigs[signum])
-           {
-             sig_print_info (signum);
-           }
-       }
-    }
+       if (from_tty)
+         {
+           /* Show the results.  */
+           sig_print_header ();
+           for (; signum < nsigs; signum++)
+             if (sigs[signum])
+               sig_print_info (signum);
+         }
+
+       break;
+      }
 
   do_cleanups (old_chain);
 }
@@ -4215,13 +4949,12 @@ xdb_handle_command (char *args, int from_tty)
   char **argv;
   struct cleanup *old_chain;
 
+  if (args == NULL)
+    error_no_arg (_("xdb command"));
+
   /* Break the command line up into args. */
 
-  argv = buildargv (args);
-  if (argv == NULL)
-    {
-      nomem (0);
-    }
+  argv = gdb_buildargv (args);
   old_chain = make_cleanup_freeargv (argv);
   if (argv[1] != (char *) NULL)
     {
@@ -4316,11 +5049,167 @@ signals_info (char *signum_exp, int from_tty)
 
   printf_filtered (_("\nUse the \"handle\" command to change these tables.\n"));
 }
+
+/* The $_siginfo convenience variable is a bit special.  We don't know
+   for sure the type of the value until we actually have a chance to
+   fetch the data.  The type can change depending on gdbarch, so it it
+   also dependent on which thread you have selected.
+
+     1. making $_siginfo be an internalvar that creates a new value on
+     access.
+
+     2. making the value of $_siginfo be an lval_computed value.  */
+
+/* This function implements the lval_computed support for reading a
+   $_siginfo value.  */
+
+static void
+siginfo_value_read (struct value *v)
+{
+  LONGEST transferred;
+
+  transferred =
+    target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO,
+                NULL,
+                value_contents_all_raw (v),
+                value_offset (v),
+                TYPE_LENGTH (value_type (v)));
+
+  if (transferred != TYPE_LENGTH (value_type (v)))
+    error (_("Unable to read siginfo"));
+}
+
+/* This function implements the lval_computed support for writing a
+   $_siginfo value.  */
+
+static void
+siginfo_value_write (struct value *v, struct value *fromval)
+{
+  LONGEST transferred;
+
+  transferred = target_write (&current_target,
+                             TARGET_OBJECT_SIGNAL_INFO,
+                             NULL,
+                             value_contents_all_raw (fromval),
+                             value_offset (v),
+                             TYPE_LENGTH (value_type (fromval)));
+
+  if (transferred != TYPE_LENGTH (value_type (fromval)))
+    error (_("Unable to write siginfo"));
+}
+
+static struct lval_funcs siginfo_value_funcs =
+  {
+    siginfo_value_read,
+    siginfo_value_write
+  };
+
+/* Return a new value with the correct type for the siginfo object of
+   the current thread.  Return a void value if there's no object
+   available.  */
+
+static struct value *
+siginfo_make_value (struct internalvar *var)
+{
+  struct type *type;
+  struct gdbarch *gdbarch;
+
+  if (target_has_stack
+      && !ptid_equal (inferior_ptid, null_ptid))
+    {
+      gdbarch = get_frame_arch (get_current_frame ());
+
+      if (gdbarch_get_siginfo_type_p (gdbarch))
+       {
+         type = gdbarch_get_siginfo_type (gdbarch);
+
+         return allocate_computed_value (type, &siginfo_value_funcs, NULL);
+       }
+    }
+
+  return allocate_value (builtin_type_void);
+}
+
 \f
-struct inferior_status
+/* Inferior thread state.
+   These are details related to the inferior itself, and don't include
+   things like what frame the user had selected or what gdb was doing
+   with the target at the time.
+   For inferior function calls these are things we want to restore
+   regardless of whether the function call successfully completes
+   or the dummy frame has to be manually popped.  */
+
+struct inferior_thread_state
 {
   enum target_signal stop_signal;
   CORE_ADDR stop_pc;
+  struct regcache *registers;
+};
+
+struct inferior_thread_state *
+save_inferior_thread_state (void)
+{
+  struct inferior_thread_state *inf_state = XMALLOC (struct inferior_thread_state);
+  struct thread_info *tp = inferior_thread ();
+
+  inf_state->stop_signal = tp->stop_signal;
+  inf_state->stop_pc = stop_pc;
+
+  inf_state->registers = regcache_dup (get_current_regcache ());
+
+  return inf_state;
+}
+
+/* Restore inferior session state to INF_STATE.  */
+
+void
+restore_inferior_thread_state (struct inferior_thread_state *inf_state)
+{
+  struct thread_info *tp = inferior_thread ();
+
+  tp->stop_signal = inf_state->stop_signal;
+  stop_pc = inf_state->stop_pc;
+
+  /* The inferior can be gone if the user types "print exit(0)"
+     (and perhaps other times).  */
+  if (target_has_execution)
+    /* NB: The register write goes through to the target.  */
+    regcache_cpy (get_current_regcache (), inf_state->registers);
+  regcache_xfree (inf_state->registers);
+  xfree (inf_state);
+}
+
+static void
+do_restore_inferior_thread_state_cleanup (void *state)
+{
+  restore_inferior_thread_state (state);
+}
+
+struct cleanup *
+make_cleanup_restore_inferior_thread_state (struct inferior_thread_state *inf_state)
+{
+  return make_cleanup (do_restore_inferior_thread_state_cleanup, inf_state);
+}
+
+void
+discard_inferior_thread_state (struct inferior_thread_state *inf_state)
+{
+  regcache_xfree (inf_state->registers);
+  xfree (inf_state);
+}
+
+struct regcache *
+get_inferior_thread_state_regcache (struct inferior_thread_state *inf_state)
+{
+  return inf_state->registers;
+}
+
+/* Session related state for inferior function calls.
+   These are the additional bits of state that need to be restored
+   when an inferior function call successfully completes.  */
+
+struct inferior_status
+{
   bpstat stop_bpstat;
   int stop_step;
   int stop_stack_dummy;
@@ -4334,63 +5223,44 @@ struct inferior_status
   int stop_after_trap;
   int stop_soon;
 
-  /* These are here because if call_function_by_hand has written some
-     registers and then decides to call error(), we better not have changed
-     any registers.  */
-  struct regcache *registers;
-
-  /* A frame unique identifier.  */
+  /* ID if the selected frame when the inferior function call was made.  */
   struct frame_id selected_frame_id;
 
-  int breakpoint_proceeded;
-  int restore_stack_info;
   int proceed_to_finish;
+  int in_infcall;
 };
 
-void
-write_inferior_status_register (struct inferior_status *inf_status, int regno,
-                               LONGEST val)
-{
-  int size = register_size (current_gdbarch, regno);
-  void *buf = alloca (size);
-  store_signed_integer (buf, size, val);
-  regcache_raw_write (inf_status->registers, regno, buf);
-}
-
 /* Save all of the information associated with the inferior<==>gdb
-   connection.  INF_STATUS is a pointer to a "struct inferior_status"
-   (defined in inferior.h).  */
+   connection.  */
 
 struct inferior_status *
-save_inferior_status (int restore_stack_info)
+save_inferior_status (void)
 {
   struct inferior_status *inf_status = XMALLOC (struct inferior_status);
+  struct thread_info *tp = inferior_thread ();
+  struct inferior *inf = current_inferior ();
 
-  inf_status->stop_signal = stop_signal;
-  inf_status->stop_pc = stop_pc;
-  inf_status->stop_step = stop_step;
+  inf_status->stop_step = tp->stop_step;
   inf_status->stop_stack_dummy = stop_stack_dummy;
   inf_status->stopped_by_random_signal = stopped_by_random_signal;
-  inf_status->stepping_over_breakpoint = stepping_over_breakpoint;
-  inf_status->step_range_start = step_range_start;
-  inf_status->step_range_end = step_range_end;
-  inf_status->step_frame_id = step_frame_id;
-  inf_status->step_over_calls = step_over_calls;
+  inf_status->stepping_over_breakpoint = tp->trap_expected;
+  inf_status->step_range_start = tp->step_range_start;
+  inf_status->step_range_end = tp->step_range_end;
+  inf_status->step_frame_id = tp->step_frame_id;
+  inf_status->step_over_calls = tp->step_over_calls;
   inf_status->stop_after_trap = stop_after_trap;
-  inf_status->stop_soon = stop_soon;
+  inf_status->stop_soon = inf->stop_soon;
   /* Save original bpstat chain here; replace it with copy of chain.
      If caller's caller is walking the chain, they'll be happier if we
      hand them back the original chain when restore_inferior_status is
      called.  */
-  inf_status->stop_bpstat = stop_bpstat;
-  stop_bpstat = bpstat_copy (stop_bpstat);
-  inf_status->breakpoint_proceeded = breakpoint_proceeded;
-  inf_status->restore_stack_info = restore_stack_info;
-  inf_status->proceed_to_finish = proceed_to_finish;
-
-  inf_status->registers = regcache_dup (get_current_regcache ());
+  inf_status->stop_bpstat = tp->stop_bpstat;
+  tp->stop_bpstat = bpstat_copy (tp->stop_bpstat);
+  inf_status->proceed_to_finish = tp->proceed_to_finish;
+  inf_status->in_infcall = tp->in_infcall;
 
   inf_status->selected_frame_id = get_frame_id (get_selected_frame (NULL));
+
   return inf_status;
 }
 
@@ -4415,41 +5285,31 @@ restore_selected_frame (void *args)
   return (1);
 }
 
+/* Restore inferior session state to INF_STATUS.  */
+
 void
 restore_inferior_status (struct inferior_status *inf_status)
 {
-  stop_signal = inf_status->stop_signal;
-  stop_pc = inf_status->stop_pc;
-  stop_step = inf_status->stop_step;
+  struct thread_info *tp = inferior_thread ();
+  struct inferior *inf = current_inferior ();
+
+  tp->stop_step = inf_status->stop_step;
   stop_stack_dummy = inf_status->stop_stack_dummy;
   stopped_by_random_signal = inf_status->stopped_by_random_signal;
-  stepping_over_breakpoint = inf_status->stepping_over_breakpoint;
-  step_range_start = inf_status->step_range_start;
-  step_range_end = inf_status->step_range_end;
-  step_frame_id = inf_status->step_frame_id;
-  step_over_calls = inf_status->step_over_calls;
+  tp->trap_expected = inf_status->stepping_over_breakpoint;
+  tp->step_range_start = inf_status->step_range_start;
+  tp->step_range_end = inf_status->step_range_end;
+  tp->step_frame_id = inf_status->step_frame_id;
+  tp->step_over_calls = inf_status->step_over_calls;
   stop_after_trap = inf_status->stop_after_trap;
-  stop_soon = inf_status->stop_soon;
-  bpstat_clear (&stop_bpstat);
-  stop_bpstat = inf_status->stop_bpstat;
-  breakpoint_proceeded = inf_status->breakpoint_proceeded;
-  proceed_to_finish = inf_status->proceed_to_finish;
-
-  /* The inferior can be gone if the user types "print exit(0)"
-     (and perhaps other times).  */
-  if (target_has_execution)
-    /* NB: The register write goes through to the target.  */
-    regcache_cpy (get_current_regcache (), inf_status->registers);
-  regcache_xfree (inf_status->registers);
-
-  /* FIXME: If we are being called after stopping in a function which
-     is called from gdb, we should not be trying to restore the
-     selected frame; it just prints a spurious error message (The
-     message is useful, however, in detecting bugs in gdb (like if gdb
-     clobbers the stack)).  In fact, should we be restoring the
-     inferior status at all in that case?  .  */
-
-  if (target_has_stack && inf_status->restore_stack_info)
+  inf->stop_soon = inf_status->stop_soon;
+  bpstat_clear (&tp->stop_bpstat);
+  tp->stop_bpstat = inf_status->stop_bpstat;
+  inf_status->stop_bpstat = NULL;
+  tp->proceed_to_finish = inf_status->proceed_to_finish;
+  tp->in_infcall = inf_status->in_infcall;
+
+  if (target_has_stack)
     {
       /* The point of catch_errors is that if the stack is clobbered,
          walking the stack might encounter a garbage pointer and
@@ -4461,7 +5321,6 @@ restore_inferior_status (struct inferior_status *inf_status)
        /* Error in restoring the selected frame.  Select the innermost
           frame.  */
        select_frame (get_current_frame ());
-
     }
 
   xfree (inf_status);
@@ -4484,10 +5343,9 @@ discard_inferior_status (struct inferior_status *inf_status)
 {
   /* See save_inferior_status for info on stop_bpstat. */
   bpstat_clear (&inf_status->stop_bpstat);
-  regcache_xfree (inf_status->registers);
   xfree (inf_status);
 }
-
+\f
 int
 inferior_has_forked (ptid_t pid, ptid_t *child_pid)
 {
@@ -4600,6 +5458,19 @@ ptid_equal (ptid_t ptid1, ptid_t ptid2)
          && ptid1.tid == ptid2.tid);
 }
 
+/* Returns true if PTID represents a process.  */
+
+int
+ptid_is_pid (ptid_t ptid)
+{
+  if (ptid_equal (minus_one_ptid, ptid))
+    return 0;
+  if (ptid_equal (null_ptid, ptid))
+    return 0;
+
+  return (ptid_get_lwp (ptid) == 0 && ptid_get_tid (ptid) == 0);
+}
+
 /* restore_inferior_ptid() will be used by the cleanup machinery
    to restore the inferior_ptid value saved in a call to
    save_inferior_ptid().  */
@@ -4627,6 +5498,55 @@ save_inferior_ptid (void)
 }
 \f
 
+/* User interface for reverse debugging:
+   Set exec-direction / show exec-direction commands
+   (returns error unless target implements to_set_exec_direction method).  */
+
+enum exec_direction_kind execution_direction = EXEC_FORWARD;
+static const char exec_forward[] = "forward";
+static const char exec_reverse[] = "reverse";
+static const char *exec_direction = exec_forward;
+static const char *exec_direction_names[] = {
+  exec_forward,
+  exec_reverse,
+  NULL
+};
+
+static void
+set_exec_direction_func (char *args, int from_tty,
+                        struct cmd_list_element *cmd)
+{
+  if (target_can_execute_reverse)
+    {
+      if (!strcmp (exec_direction, exec_forward))
+       execution_direction = EXEC_FORWARD;
+      else if (!strcmp (exec_direction, exec_reverse))
+       execution_direction = EXEC_REVERSE;
+    }
+}
+
+static void
+show_exec_direction_func (struct ui_file *out, int from_tty,
+                         struct cmd_list_element *cmd, const char *value)
+{
+  switch (execution_direction) {
+  case EXEC_FORWARD:
+    fprintf_filtered (out, _("Forward.\n"));
+    break;
+  case EXEC_REVERSE:
+    fprintf_filtered (out, _("Reverse.\n"));
+    break;
+  case EXEC_ERROR:
+  default:
+    fprintf_filtered (out, 
+                     _("Forward (target `%s' does not support exec-direction).\n"),
+                     target_shortname);
+    break;
+  }
+}
+
+/* User interface for non-stop mode.  */
+
 int non_stop = 0;
 static int non_stop_1 = 0;
 
@@ -4841,16 +5761,28 @@ function is skipped and the step command stops at a different source line."),
                           show_step_stop_if_no_debug,
                           &setlist, &showlist);
 
-  add_setshow_boolean_cmd ("can-use-displaced-stepping", class_maintenance,
-                          &can_use_displaced_stepping, _("\
+  add_setshow_enum_cmd ("displaced-stepping", class_run,
+                       can_use_displaced_stepping_enum,
+                       &can_use_displaced_stepping, _("\
 Set debugger's willingness to use displaced stepping."), _("\
 Show debugger's willingness to use displaced stepping."), _("\
-If zero, gdb will not use displaced stepping to step over\n\
-breakpoints, even if such is supported by the target."),
-                          NULL,
-                          show_can_use_displaced_stepping,
-                          &maintenance_set_cmdlist,
-                          &maintenance_show_cmdlist);
+If on, gdb will use displaced stepping to step over breakpoints if it is\n\
+supported by the target architecture.  If off, gdb will not use displaced\n\
+stepping to step over breakpoints, even if such is supported by the target\n\
+architecture.  If auto (which is the default), gdb will use displaced stepping\n\
+if the target architecture supports it and non-stop mode is active, but will not\n\
+use it in all-stop mode (see help set non-stop)."),
+                       NULL,
+                       show_can_use_displaced_stepping,
+                       &setlist, &showlist);
+
+  add_setshow_enum_cmd ("exec-direction", class_run, exec_direction_names,
+                       &exec_direction, _("Set direction of execution.\n\
+Options are 'forward' or 'reverse'."),
+                       _("Show direction of execution (forward/reverse)."),
+                       _("Tells gdb whether to execute forward or backward."),
+                       set_exec_direction_func, show_exec_direction_func,
+                       &setlist, &showlist);
 
   /* ptid initializations */
   null_ptid = ptid_build (0, 0, 0);
@@ -4858,4 +5790,14 @@ breakpoints, even if such is supported by the target."),
   inferior_ptid = null_ptid;
   target_last_wait_ptid = minus_one_ptid;
   displaced_step_ptid = null_ptid;
+
+  observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
+  observer_attach_thread_stop_requested (infrun_thread_stop_requested);
+  observer_attach_thread_exit (infrun_thread_thread_exit);
+
+  /* Explicitly create without lookup, since that tries to create a
+     value with a void typed value, and when we get here, gdbarch
+     isn't initialized yet.  At this point, we're quite sure there
+     isn't another convenience variable of the same name.  */
+  create_internalvar_type_lazy ("_siginfo", siginfo_make_value);
 }
This page took 0.071435 seconds and 4 git commands to generate.