Honour software single step in fallback of displaced stepping
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 7e59f558b44c54b4c6f025aa2fd73878b24ef5d3..7870f703e6c76041d0c831b28545f3a5536e1513 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-struct-independent code to start (run) and stop an inferior
    process.
 
-   Copyright (C) 1986-2014 Free Software Foundation, Inc.
+   Copyright (C) 1986-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -88,8 +88,6 @@ static void set_schedlock_func (char *args, int from_tty,
 
 static int currently_stepping (struct thread_info *tp);
 
-static void xdb_handle_command (char *args, int from_tty);
-
 void _initialize_infrun (void);
 
 void nullify_last_target_wait_ptid (void);
@@ -100,6 +98,8 @@ static void insert_step_resume_breakpoint_at_caller (struct frame_info *);
 
 static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
 
+static int maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc);
+
 /* 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.  */
@@ -326,10 +326,6 @@ update_signals_program_target (void)
 
 static struct cmd_list_element *stop_command;
 
-/* Function inferior was in as of last step command.  */
-
-static struct symbol *step_start_function;
-
 /* Nonzero if we want to give control to the user when we're notified
    of shared library events by the dynamic linker.  */
 int stop_on_solib_events;
@@ -408,15 +404,12 @@ static int
 follow_fork_inferior (int follow_child, int detach_fork)
 {
   int has_vforked;
-  int parent_pid, child_pid;
+  ptid_t parent_ptid, child_ptid;
 
   has_vforked = (inferior_thread ()->pending_follow.kind
                 == TARGET_WAITKIND_VFORKED);
-  parent_pid = ptid_get_lwp (inferior_ptid);
-  if (parent_pid == 0)
-    parent_pid = ptid_get_pid (inferior_ptid);
-  child_pid
-    = ptid_get_pid (inferior_thread ()->pending_follow.value.related_pid);
+  parent_ptid = inferior_ptid;
+  child_ptid = inferior_thread ()->pending_follow.value.related_pid;
 
   if (has_vforked
       && !non_stop /* Non-stop always resumes both branches.  */
@@ -460,10 +453,9 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
            {
              target_terminal_ours_for_output ();
              fprintf_filtered (gdb_stdlog,
-                               _("Detaching after %s from "
-                                 "child process %d.\n"),
+                               _("Detaching after %s from child %s.\n"),
                                has_vforked ? "vfork" : "fork",
-                               child_pid);
+                               target_pid_to_str (child_ptid));
            }
        }
       else
@@ -472,7 +464,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          struct cleanup *old_chain;
 
          /* Add process to GDB's tables.  */
-         child_inf = add_inferior (child_pid);
+         child_inf = add_inferior (ptid_get_pid (child_ptid));
 
          parent_inf = current_inferior ();
          child_inf->attach_flag = parent_inf->attach_flag;
@@ -483,7 +475,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          old_chain = save_inferior_ptid ();
          save_current_program_space ();
 
-         inferior_ptid = ptid_build (child_pid, child_pid, 0);
+         inferior_ptid = child_ptid;
          add_thread (inferior_ptid);
          child_inf->symfile_flags = SYMFILE_NO_READ;
 
@@ -549,17 +541,16 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
        {
          target_terminal_ours_for_output ();
          fprintf_filtered (gdb_stdlog,
-                           _("Attaching after process %d "
-                             "%s to child process %d.\n"),
-                           parent_pid,
+                           _("Attaching after %s %s to child %s.\n"),
+                           target_pid_to_str (parent_ptid),
                            has_vforked ? "vfork" : "fork",
-                           child_pid);
+                           target_pid_to_str (child_ptid));
        }
 
       /* Add the new inferior first, so that the target_detach below
         doesn't unpush the target.  */
 
-      child_inf = add_inferior (child_pid);
+      child_inf = add_inferior (ptid_get_pid (child_ptid));
 
       parent_inf = current_inferior ();
       child_inf->attach_flag = parent_inf->attach_flag;
@@ -596,8 +587,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
              target_terminal_ours_for_output ();
              fprintf_filtered (gdb_stdlog,
                                _("Detaching after fork from "
-                                 "child process %d.\n"),
-                               child_pid);
+                                 "child %s.\n"),
+                               target_pid_to_str (child_ptid));
            }
 
          target_detach (NULL, 0);
@@ -609,7 +600,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
         this new thread, before cloning the program space, and
         informing the solib layer about this new process.  */
 
-      inferior_ptid = ptid_build (child_pid, child_pid, 0);
+      inferior_ptid = child_ptid;
       add_thread (inferior_ptid);
 
       /* If this is a vfork child, then the address-space is shared
@@ -868,7 +859,7 @@ proceed_after_vfork_done (struct thread_info *thread,
 
       switch_to_thread (thread->ptid);
       clear_proceed_status (0);
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
 
   return 0;
@@ -1060,10 +1051,11 @@ show_follow_exec_mode_string (struct ui_file *file, int from_tty,
 /* EXECD_PATHNAME is assumed to be non-NULL.  */
 
 static void
-follow_exec (ptid_t pid, char *execd_pathname)
+follow_exec (ptid_t ptid, char *execd_pathname)
 {
-  struct thread_info *th = inferior_thread ();
+  struct thread_info *th, *tmp;
   struct inferior *inf = current_inferior ();
+  int pid = ptid_get_pid (ptid);
 
   /* 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
@@ -1088,24 +1080,47 @@ follow_exec (ptid_t pid, char *execd_pathname)
 
   mark_breakpoints_out ();
 
-  update_breakpoints_after_exec ();
-
-  /* If there was one, it's gone now.  We cannot truly step-to-next
-     statement through an exec().  */
+  /* 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
+     stopped or already gone.  We may still have non-leader threads of
+     the process on our list.  E.g., on targets that don't have thread
+     exit events (like remote); or on native Linux in non-stop mode if
+     there were only two threads in the inferior and the non-leader
+     one is the one that execs (and nothing forces an update of the
+     thread list up to here).  When debugging remotely, it's best to
+     avoid extra traffic, when possible, so avoid syncing the thread
+     list with the target, and instead go ahead and delete all threads
+     of the process but one that reported the event.  Note this must
+     be done before calling update_breakpoints_after_exec, as
+     otherwise clearing the threads' resources would reference stale
+     thread breakpoints -- it may have been one of these threads that
+     stepped across the exec.  We could just clear their stepping
+     states, but as long as we're iterating, might as well delete
+     them.  Deleting them now rather than at the next user-visible
+     stop provides a nicer sequence of events for user and MI
+     notifications.  */
+  ALL_THREADS_SAFE (th, tmp)
+    if (ptid_get_pid (th->ptid) == pid && !ptid_equal (th->ptid, ptid))
+      delete_thread (th->ptid);
+
+  /* We also need to clear any left over stale state for the
+     leader/event thread.  E.g., if there was any step-resume
+     breakpoint or similar, it's gone now.  We cannot truly
+     step-to-next statement through an exec().  */
+  th = inferior_thread ();
   th->control.step_resume_breakpoint = NULL;
   th->control.exception_resume_breakpoint = NULL;
   th->control.single_step_breakpoints = NULL;
   th->control.step_range_start = 0;
   th->control.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.  */
+  /* The user may have had the main thread held stopped in the
+     previous image (e.g., schedlock on, or non-stop).  Release
+     it now.  */
   th->stop_requested = 0;
 
+  update_breakpoints_after_exec ();
+
   /* What is this a.out's name?  */
   printf_unfiltered (_("%s is executing new program: %s\n"),
                     target_pid_to_str (inferior_ptid),
@@ -1450,6 +1465,20 @@ get_displaced_stepping_state (int pid)
   return NULL;
 }
 
+/* Return true if process PID has a thread doing a displaced step.  */
+
+static int
+displaced_step_in_progress (int pid)
+{
+  struct displaced_step_inferior_state *displaced;
+
+  displaced = get_displaced_stepping_state (pid);
+  if (displaced != NULL && !ptid_equal (displaced->step_ptid, null_ptid))
+    return 1;
+
+  return 0;
+}
+
 /* Add a new displaced stepping state for process PID to the displaced
    stepping state list, or return a pointer to an already existing
    entry, if it already exists.  Never returns NULL.  */
@@ -1781,8 +1810,16 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 
   displaced_step_restore (displaced, displaced->step_ptid);
 
+  /* Fixup may need to read memory/registers.  Switch to the thread
+     that we're fixing up.  Also, target_stopped_by_watchpoint checks
+     the current thread.  */
+  switch_to_thread (event_ptid);
+
   /* Did the instruction complete successfully?  */
-  if (signal == GDB_SIGNAL_TRAP)
+  if (signal == GDB_SIGNAL_TRAP
+      && !(target_stopped_by_watchpoint ()
+          && (gdbarch_have_nonsteppable_watchpoint (displaced->step_gdbarch)
+              || target_have_steppable_watchpoint)))
     {
       /* Fix up the resulting state.  */
       gdbarch_displaced_step_fixup (displaced->step_gdbarch,
@@ -1828,6 +1865,7 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
       regcache = get_thread_regcache (ptid);
       actual_pc = regcache_read_pc (regcache);
       aspace = get_regcache_aspace (regcache);
+      gdbarch = get_regcache_arch (regcache);
 
       if (breakpoint_here_p (aspace, actual_pc))
        {
@@ -1838,8 +1876,6 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 
          displaced_step_prepare (ptid);
 
-         gdbarch = get_regcache_arch (regcache);
-
          if (debug_displaced)
            {
              CORE_ADDR actual_pc = regcache_read_pc (regcache);
@@ -1872,6 +1908,9 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
          /* Go back to what we were trying to do.  */
          step = currently_stepping (tp);
 
+         if (step)
+           step = maybe_software_singlestep (gdbarch, actual_pc);
+
          if (debug_displaced)
            fprintf_unfiltered (gdb_stdlog,
                                "displaced: breakpoint is gone: %s, step(%d)\n",
@@ -1978,19 +2017,13 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
   return hw_step;
 }
 
+/* See infrun.h.  */
+
 ptid_t
 user_visible_resume_ptid (int step)
 {
-  /* By default, resume all threads of all processes.  */
-  ptid_t resume_ptid = RESUME_ALL;
-
-  /* Maybe resume only all threads of the current process.  */
-  if (!sched_multi && target_supports_multi_process ())
-    {
-      resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
-    }
+  ptid_t resume_ptid;
 
-  /* Maybe resume a single thread after all.  */
   if (non_stop)
     {
       /* With non-stop mode on, threads are always handled
@@ -2000,29 +2033,77 @@ user_visible_resume_ptid (int step)
   else if ((scheduler_mode == schedlock_on)
           || (scheduler_mode == schedlock_step && step))
     {
-      /* User-settable 'scheduler' mode requires solo thread resume.  */
+      /* User-settable 'scheduler' mode requires solo thread
+        resume.  */
       resume_ptid = inferior_ptid;
     }
+  else if (!sched_multi && target_supports_multi_process ())
+    {
+      /* Resume all threads of the current process (and none of other
+        processes).  */
+      resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
+    }
+  else
+    {
+      /* Resume all threads of all processes.  */
+      resume_ptid = RESUME_ALL;
+    }
 
-  /* We may actually resume fewer threads at first, e.g., if a thread
-     is stopped at a breakpoint that needs stepping-off, but that
-     should not be visible to the user/frontend, and neither should
-     the frontend/user be allowed to proceed any of the threads that
-     happen to be stopped for internal run control handling, if a
-     previous command wanted them resumed.  */
   return resume_ptid;
 }
 
+/* Wrapper for target_resume, that handles infrun-specific
+   bookkeeping.  */
+
+static void
+do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
+{
+  struct thread_info *tp = inferior_thread ();
+
+  /* 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->suspend.stop_signal = GDB_SIGNAL_0;
+
+  /* Advise target which signals may be handled silently.
+
+     If we have removed breakpoints because we are stepping over one
+     in-line (in any thread), we need to receive all signals to avoid
+     accidentally skipping a breakpoint during execution of a signal
+     handler.
+
+     Likewise if we're displaced stepping, otherwise a trap for a
+     breakpoint in a signal handler might be confused with the
+     displaced step finishing.  We don't make the displaced_step_fixup
+     step distinguish the cases instead, because:
+
+     - a backtrace while stopped in the signal handler would show the
+       scratch pad as frame older than the signal handler, instead of
+       the real mainline code.
+
+     - when the thread is later resumed, the signal handler would
+       return to the scratch pad area, which would no longer be
+       valid.  */
+  if (step_over_info_valid_p ()
+      || displaced_step_in_progress (ptid_get_pid (tp->ptid)))
+    target_pass_signals (0, NULL);
+  else
+    target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
+
+  target_resume (resume_ptid, step, sig);
+}
+
 /* Resume the inferior, but allow a QUIT.  This is useful if the user
    wants to interrupt some lengthy single-stepping operation
    (for child processes, the SIGINT goes to the inferior, and so
    we get a SIGINT random_signal, but for remote debugging and perhaps
    other targets, that's not true).
 
-   STEP nonzero if we should step (zero to continue instead).
    SIG is the signal to give the inferior (zero for none).  */
 void
-resume (int step, enum gdb_signal sig)
+resume (enum gdb_signal sig)
 {
   struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
   struct regcache *regcache = get_current_regcache ();
@@ -2031,18 +2112,23 @@ resume (int step, enum gdb_signal sig)
   CORE_ADDR pc = regcache_read_pc (regcache);
   struct address_space *aspace = get_regcache_aspace (regcache);
   ptid_t resume_ptid;
-  /* From here on, this represents the caller's step vs continue
-     request, while STEP represents what we'll actually request the
-     target to do.  STEP can decay from a step to a continue, if e.g.,
-     we need to implement single-stepping with breakpoints (software
-     single-step).  When deciding whether "set scheduler-locking step"
-     applies, it's the callers intention that counts.  */
-  const int entry_step = step;
+  /* This represents the user's step vs continue request.  When
+     deciding whether "set scheduler-locking step" applies, it's the
+     user's intention that counts.  */
+  const int user_step = tp->control.stepping_command;
+  /* This represents what we'll actually request the target to do.
+     This can decay from a step to a continue, if e.g., we need to
+     implement single-stepping with breakpoints (software
+     single-step).  */
+  int step;
 
   tp->stepped_breakpoint = 0;
 
   QUIT;
 
+  /* Depends on stepped_breakpoint.  */
+  step = currently_stepping (tp);
+
   if (current_inferior ()->waiting_for_vfork_done)
     {
       /* Don't try to single-step a vfork parent that is waiting for
@@ -2133,21 +2219,16 @@ resume (int step, enum gdb_signal sig)
                 reported to handle_inferior_event.  Set a breakpoint
                 at the current PC, and run to it.  Don't update
                 prev_pc, because if we end in
-                switch_back_to_stepping, we want the "expected thread
-                advanced also" branch to be taken.  IOW, we don't
-                want this thread to step further from PC
+                switch_back_to_stepped_thread, we want the "expected
+                thread advanced also" branch to be taken.  IOW, we
+                don't want this thread to step further from PC
                 (overstep).  */
+             gdb_assert (!step_over_info_valid_p ());
              insert_single_step_breakpoint (gdbarch, aspace, pc);
              insert_breakpoints ();
 
-             tp->suspend.stop_signal = GDB_SIGNAL_0;
-             /* We're continuing with all breakpoints inserted.  It's
-                safe to let the target bypass signals.  */
-             target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
-             /* ... and safe to let other threads run, according to
-                schedlock.  */
-             resume_ptid = user_visible_resume_ptid (entry_step);
-             target_resume (resume_ptid, 0, GDB_SIGNAL_0);
+             resume_ptid = user_visible_resume_ptid (user_step);
+             do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
              discard_cleanups (old_cleanups);
              return;
            }
@@ -2172,6 +2253,7 @@ resume (int step, enum gdb_signal sig)
      step software breakpoint.  */
   if (use_displaced_stepping (gdbarch)
       && tp->control.trap_expected
+      && !step_over_info_valid_p ()
       && sig == GDB_SIGNAL_0
       && !current_inferior ()->waiting_for_vfork_done)
     {
@@ -2188,7 +2270,7 @@ resume (int step, enum gdb_signal sig)
             Unless we're calling an inferior function, as in that
             case we pretend the inferior doesn't run at all.  */
          if (!tp->control.in_infcall)
-           set_running (user_visible_resume_ptid (entry_step), 1);
+           set_running (user_visible_resume_ptid (user_step), 1);
          discard_cleanups (old_cleanups);
          return;
        }
@@ -2261,7 +2343,7 @@ resume (int step, enum gdb_signal sig)
   /* Decide the set of threads to ask the target to resume.  Start
      by assuming everything will be resumed, than narrow the set
      by applying increasingly restricting conditions.  */
-  resume_ptid = user_visible_resume_ptid (entry_step);
+  resume_ptid = user_visible_resume_ptid (user_step);
 
   /* Even if RESUME_PTID is a wildcard, and we end up resuming less
      (e.g., we might need to step over a breakpoint), from the
@@ -2317,9 +2399,10 @@ resume (int step, enum gdb_signal sig)
 
   if (debug_displaced
       && use_displaced_stepping (gdbarch)
-      && tp->control.trap_expected)
+      && tp->control.trap_expected
+      && !step_over_info_valid_p ())
     {
-      struct regcache *resume_regcache = get_thread_regcache (resume_ptid);
+      struct regcache *resume_regcache = get_thread_regcache (tp->ptid);
       struct gdbarch *resume_gdbarch = get_regcache_arch (resume_regcache);
       CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
       gdb_byte buf[4];
@@ -2340,24 +2423,7 @@ resume (int step, enum gdb_signal sig)
       gdb_assert (pc_in_thread_step_range (pc, tp));
     }
 
-  /* 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->suspend.stop_signal = GDB_SIGNAL_0;
-
-  /* Advise target which signals may be handled silently.  If we have
-     removed breakpoints because we are stepping over one (in any
-     thread), we need to receive all signals to avoid accidentally
-     skipping a breakpoint during execution of a signal handler.  */
-  if (step_over_info_valid_p ())
-    target_pass_signals (0, NULL);
-  else
-    target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
-
-  target_resume (resume_ptid, step, sig);
-
+  do_target_resume (resume_ptid, step, sig);
   discard_cleanups (old_cleanups);
 }
 \f
@@ -2386,6 +2452,7 @@ clear_proceed_status_thread (struct thread_info *tp)
   tp->control.step_frame_id = null_frame_id;
   tp->control.step_stack_frame_id = null_frame_id;
   tp->control.step_over_calls = STEP_OVER_UNDEBUGGABLE;
+  tp->control.step_start_function = NULL;
   tp->stop_requested = 0;
 
   tp->control.stop_step = 0;
@@ -2393,6 +2460,7 @@ clear_proceed_status_thread (struct thread_info *tp)
   tp->control.proceed_to_finish = 0;
 
   tp->control.command_interp = NULL;
+  tp->control.stepping_command = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
   bpstat_clear (&tp->control.stop_bpstat);
@@ -2472,21 +2540,19 @@ thread_still_needs_step_over (struct thread_info *tp)
    we're about to do a step/next-like command to a thread.  */
 
 static int
-schedlock_applies (int step)
+schedlock_applies (struct thread_info *tp)
 {
   return (scheduler_mode == schedlock_on
          || (scheduler_mode == schedlock_step
-             && step));
+             && tp->control.stepping_command));
 }
 
 /* Look a thread other than EXCEPT that has previously reported a
    breakpoint event, and thus needs a step-over in order to make
-   progress.  Returns NULL is none is found.  STEP indicates whether
-   we're about to step the current thread, in order to decide whether
-   "set scheduler-locking step" applies.  */
+   progress.  Returns NULL is none is found.  */
 
 static struct thread_info *
-find_thread_needs_step_over (int step, struct thread_info *except)
+find_thread_needs_step_over (struct thread_info *except)
 {
   struct thread_info *tp, *current;
 
@@ -2497,7 +2563,7 @@ find_thread_needs_step_over (int step, struct thread_info *except)
 
   /* If scheduler locking applies, we can avoid iterating over all
      threads.  */
-  if (schedlock_applies (step))
+  if (schedlock_applies (except))
     {
       if (except != current
          && thread_still_needs_step_over (current))
@@ -2536,7 +2602,7 @@ find_thread_needs_step_over (int step, struct thread_info *except)
    You should call clear_proceed_status before calling proceed.  */
 
 void
-proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
+proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 {
   struct regcache *regcache;
   struct gdbarch *gdbarch;
@@ -2565,11 +2631,6 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
   pc = regcache_read_pc (regcache);
   tp = inferior_thread ();
 
-  if (step > 0)
-    step_start_function = find_pc_function (pc);
-  if (step < 0)
-    stop_after_trap = 1;
-
   /* Fill in with reasonable starting values.  */
   init_thread_stepping_state (tp);
 
@@ -2612,9 +2673,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
-                       "infrun: proceed (addr=%s, signal=%s, step=%d)\n",
+                       "infrun: proceed (addr=%s, signal=%s)\n",
                        paddress (gdbarch, addr),
-                       gdb_signal_to_symbol_string (siggnal), step);
+                       gdb_signal_to_symbol_string (siggnal));
 
   if (non_stop)
     /* In non-stop, each thread is handled individually.  The context
@@ -2634,7 +2695,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
 
         Look for a thread other than the current (TP) that reported a
         breakpoint hit and hasn't been resumed yet since.  */
-      step_over = find_thread_needs_step_over (step, tp);
+      step_over = find_thread_needs_step_over (tp);
       if (step_over != NULL)
        {
          if (debug_infrun)
@@ -2643,7 +2704,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
                                target_pid_to_str (step_over->ptid));
 
          /* Store the prev_pc for the stepping thread too, needed by
-            switch_back_to_stepping thread.  */
+            switch_back_to_stepped_thread.  */
          tp->prev_pc = regcache_read_pc (get_current_regcache ());
          switch_to_thread (step_over->ptid);
          tp = step_over;
@@ -2700,8 +2761,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
   tp->prev_pc = regcache_read_pc (get_current_regcache ());
 
   /* Resume inferior.  */
-  resume (tp->control.trap_expected || step || bpstat_should_step (),
-         tp->suspend.stop_signal);
+  resume (tp->suspend.stop_signal);
 
   /* Wait for it to stop (if not standalone)
      and in any case decode why it stopped, and act accordingly.  */
@@ -3002,14 +3062,19 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
      is set.  */
 
   fprintf_unfiltered (tmp_stream,
-                     "infrun: target_wait (%d", ptid_get_pid (waiton_ptid));
+                     "infrun: target_wait (%d.%ld.%ld",
+                     ptid_get_pid (waiton_ptid),
+                     ptid_get_lwp (waiton_ptid),
+                     ptid_get_tid (waiton_ptid));
   if (ptid_get_pid (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",
+                     "infrun:   %d.%ld.%ld [%s],\n",
                      ptid_get_pid (result_ptid),
+                     ptid_get_lwp (result_ptid),
+                     ptid_get_tid (result_ptid),
                      target_pid_to_str (result_ptid));
   fprintf_unfiltered (tmp_stream,
                      "infrun:   %s\n",
@@ -3113,6 +3178,7 @@ void
 wait_for_inferior (void)
 {
   struct cleanup *old_cleanups;
+  struct cleanup *thread_state_chain;
 
   if (debug_infrun)
     fprintf_unfiltered
@@ -3122,11 +3188,15 @@ wait_for_inferior (void)
     = make_cleanup (delete_just_stopped_threads_infrun_breakpoints_cleanup,
                    NULL);
 
+  /* If an error happens while handling the event, propagate GDB's
+     knowledge of the executing state to the frontend/user running
+     state.  */
+  thread_state_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+
   while (1)
     {
       struct execution_control_state ecss;
       struct execution_control_state *ecs = &ecss;
-      struct cleanup *old_chain;
       ptid_t waiton_ptid = minus_one_ptid;
 
       memset (ecs, 0, sizeof (*ecs));
@@ -3147,21 +3217,16 @@ wait_for_inferior (void)
       if (debug_infrun)
        print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
 
-      /* 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;
     }
 
+  /* No error, don't finish the state yet.  */
+  discard_cleanups (thread_state_chain);
+
   do_cleanups (old_cleanups);
 }
 
@@ -3178,6 +3243,16 @@ wait_for_inferior (void)
 static void
 reinstall_readline_callback_handler_cleanup (void *arg)
 {
+  if (!interpreter_async)
+    {
+      /* We're not going back to the top level event loop yet.  Don't
+        install the readline callback, as it'd prep the terminal,
+        readline-style (raw, noecho) (e.g., --batch).  We'll install
+        it the next time the prompt is displayed, when we're ready
+        for input.  */
+      return;
+    }
+
   if (async_command_editing_p && !sync_execution)
     gdb_rl_callback_handler_reinstall ();
 }
@@ -3262,7 +3337,7 @@ fetch_inferior_event (void *client_data)
 
   if (!ecs->wait_some_more)
     {
-      struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
+      struct inferior *inf = find_inferior_ptid (ecs->ptid);
 
       delete_just_stopped_threads_infrun_breakpoints ();
 
@@ -3435,12 +3510,24 @@ adjust_pc_after_break (struct execution_control_state *ecs)
   if (execution_direction == EXEC_REVERSE)
     return;
 
+  /* If the target can tell whether the thread hit a SW breakpoint,
+     trust it.  Targets that can tell also adjust the PC
+     themselves.  */
+  if (target_supports_stopped_by_sw_breakpoint ())
+    return;
+
+  /* Note that relying on whether a breakpoint is planted in memory to
+     determine this can fail.  E.g,. the breakpoint could have been
+     removed since.  Or the thread could have been told to step an
+     instruction the size of a breakpoint instruction, and only
+     _after_ was a breakpoint inserted at its address.  */
+
   /* 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);
 
-  decr_pc = target_decr_pc_after_break (gdbarch);
+  decr_pc = gdbarch_decr_pc_after_break (gdbarch);
   if (decr_pc == 0)
     return;
 
@@ -3450,6 +3537,11 @@ adjust_pc_after_break (struct execution_control_state *ecs)
      breakpoint would be.  */
   breakpoint_pc = regcache_read_pc (regcache) - decr_pc;
 
+  /* If the target can't tell whether a software breakpoint triggered,
+     fallback to figuring it out based on breakpoints we think were
+     inserted in the target, and on whether the thread was stepped or
+     continued.  */
+
   /* Check whether there actually is a software breakpoint inserted at
      that location.
 
@@ -3457,7 +3549,10 @@ adjust_pc_after_break (struct execution_control_state *ecs)
      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.  */
+     and retire them after a number of stop events are reported.  Note
+     this is an heuristic and can thus get confused.  The real fix is
+     to get the "stopped by SW BP and needs adjustment" info out of
+     the target/kernel (and thus never reach here; see above).  */
   if (software_breakpoint_inserted_here_p (aspace, breakpoint_pc)
       || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
@@ -3473,7 +3568,6 @@ adjust_pc_after_break (struct execution_control_state *ecs)
 
         The SIGTRAP can be due to a completed hardware single-step only if 
          - we didn't insert software single-step breakpoints
-         - the thread to be examined is still the current thread
          - this thread is currently being stepped
 
         If any of these events did not occur, we must have stopped due
@@ -3485,7 +3579,6 @@ adjust_pc_after_break (struct execution_control_state *ecs)
         we also need to back up to the breakpoint address.  */
 
       if (thread_has_single_step_breakpoints_set (ecs->event_thread)
-         || !ptid_equal (ecs->ptid, inferior_ptid)
          || !currently_stepping (ecs->event_thread)
          || (ecs->event_thread->stepped_breakpoint
              && ecs->event_thread->prev_pc == breakpoint_pc))
@@ -3581,7 +3674,7 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 static enum stop_kind
 get_inferior_stop_soon (ptid_t ptid)
 {
-  struct inferior *inf = find_inferior_pid (ptid_get_pid (ptid));
+  struct inferior *inf = find_inferior_ptid (ptid);
 
   gdb_assert (inf != NULL);
   return inf->control.stop_soon;
@@ -3774,7 +3867,7 @@ handle_inferior_event (struct execution_control_state *ecs)
             addresses.  Make sure new breakpoints are inserted.  */
          if (stop_soon == NO_STOP_QUIETLY)
            insert_breakpoints ();
-         resume (0, GDB_SIGNAL_0);
+         resume (GDB_SIGNAL_0);
          prepare_to_wait (ecs);
          return;
        }
@@ -3798,7 +3891,7 @@ handle_inferior_event (struct execution_control_state *ecs)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SPURIOUS\n");
       if (!ptid_equal (ecs->ptid, inferior_ptid))
        context_switch (ecs->ptid);
-      resume (0, GDB_SIGNAL_0);
+      resume (GDB_SIGNAL_0);
       prepare_to_wait (ecs);
       return;
 
@@ -3815,7 +3908,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        }
 
       inferior_ptid = ecs->ptid;
-      set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid)));
+      set_current_inferior (find_inferior_ptid (ecs->ptid));
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
       target_terminal_ours (); /* Must do this before mourn anyway.  */
@@ -3899,7 +3992,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
        if (displaced && ptid_equal (displaced->step_ptid, ecs->ptid))
          {
            struct inferior *parent_inf
-             = find_inferior_pid (ptid_get_pid (ecs->ptid));
+             = find_inferior_ptid (ecs->ptid);
            struct regcache *child_regcache;
            CORE_ADDR parent_pc;
 
@@ -4474,6 +4567,54 @@ handle_signal_stop (struct execution_control_state *ecs)
     = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
                               ecs->event_thread->suspend.stop_signal);
 
+  /* Maybe this was a trap for a software breakpoint that has since
+     been removed.  */
+  if (random_signal && target_stopped_by_sw_breakpoint ())
+    {
+      if (program_breakpoint_here_p (gdbarch, stop_pc))
+       {
+         struct regcache *regcache;
+         int decr_pc;
+
+         /* Re-adjust PC to what the program would see if GDB was not
+            debugging it.  */
+         regcache = get_thread_regcache (ecs->event_thread->ptid);
+         decr_pc = gdbarch_decr_pc_after_break (gdbarch);
+         if (decr_pc != 0)
+           {
+             struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
+
+             if (record_full_is_used ())
+               record_full_gdb_operation_disable_set ();
+
+             regcache_write_pc (regcache, stop_pc + decr_pc);
+
+             do_cleanups (old_cleanups);
+           }
+       }
+      else
+       {
+         /* A delayed software breakpoint event.  Ignore the trap.  */
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: delayed software breakpoint "
+                               "trap, ignoring\n");
+         random_signal = 0;
+       }
+    }
+
+  /* Maybe this was a trap for a hardware breakpoint/watchpoint that
+     has since been removed.  */
+  if (random_signal && target_stopped_by_hw_breakpoint ())
+    {
+      /* A delayed hardware breakpoint event.  Ignore the trap.  */
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: delayed hardware breakpoint/watchpoint "
+                           "trap, ignoring\n");
+      random_signal = 0;
+    }
+
   /* If not, perhaps stepping/nexting can.  */
   if (random_signal)
     random_signal = !(ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
@@ -4495,7 +4636,7 @@ handle_signal_stop (struct execution_control_state *ecs)
   if (random_signal)
     {
       /* Signal not for debugging purposes.  */
-      struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
+      struct inferior *inf = find_inferior_ptid (ecs->ptid);
       enum gdb_signal stop_signal = ecs->event_thread->suspend.stop_signal;
 
       if (debug_infrun)
@@ -4858,7 +4999,8 @@ process_event_stop_test (struct execution_control_state *ecs)
       struct breakpoint *sr_bp
        = ecs->event_thread->control.step_resume_breakpoint;
 
-      if (sr_bp->loc->permanent
+      if (sr_bp != NULL
+         && sr_bp->loc->permanent
          && sr_bp->type == bp_hp_step_resume
          && sr_bp->loc->address == ecs->event_thread->prev_pc)
        {
@@ -5074,7 +5216,8 @@ process_event_stop_test (struct execution_control_state *ecs)
                       ecs->event_thread->control.step_stack_frame_id)
          && (!frame_id_eq (ecs->event_thread->control.step_stack_frame_id,
                            outer_frame_id)
-             || step_start_function != find_pc_function (stop_pc))))
+             || (ecs->event_thread->control.step_start_function
+                 != find_pc_function (stop_pc)))))
     {
       CORE_ADDR real_stop_pc;
 
@@ -5497,7 +5640,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
         current thread is stepping.  If some other thread not the
         event thread is stepping, then it must be that scheduler
         locking is not in effect.  */
-      if (schedlock_applies (0))
+      if (schedlock_applies (ecs->event_thread))
        return 0;
 
       /* Look for the stepping/nexting thread, and check if any other
@@ -5533,7 +5676,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
                 stepping, then scheduler locking can't be in effect,
                 otherwise we wouldn't have resumed the current event
                 thread in the first place.  */
-             gdb_assert (!schedlock_applies (currently_stepping (tp)));
+             gdb_assert (!schedlock_applies (tp));
 
              stepping_thread = tp;
            }
@@ -5637,6 +5780,8 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 
          if (stop_pc != tp->prev_pc)
            {
+             ptid_t resume_ptid;
+
              if (debug_infrun)
                fprintf_unfiltered (gdb_stdlog,
                                    "infrun: expected thread advanced also\n");
@@ -5652,9 +5797,10 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
              insert_single_step_breakpoint (get_frame_arch (frame),
                                             get_frame_address_space (frame),
                                             stop_pc);
-             ecs->event_thread->control.trap_expected = 1;
 
-             resume (0, GDB_SIGNAL_0);
+             resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
+             do_target_resume (resume_ptid,
+                               currently_stepping (tp), GDB_SIGNAL_0);
              prepare_to_wait (ecs);
            }
          else
@@ -5692,13 +5838,13 @@ static void
 handle_step_into_function (struct gdbarch *gdbarch,
                           struct execution_control_state *ecs)
 {
-  struct symtab *s;
+  struct compunit_symtab *cust;
   struct symtab_and_line stop_func_sal, sr_sal;
 
   fill_in_stop_func (gdbarch, ecs);
 
-  s = find_pc_symtab (stop_pc);
-  if (s && s->language != language_asm)
+  cust = find_pc_compunit_symtab (stop_pc);
+  if (cust != NULL && compunit_language (cust) != language_asm)
     ecs->stop_func_start = gdbarch_skip_prologue (gdbarch,
                                                  ecs->stop_func_start);
 
@@ -5771,13 +5917,13 @@ static void
 handle_step_into_function_backward (struct gdbarch *gdbarch,
                                    struct execution_control_state *ecs)
 {
-  struct symtab *s;
+  struct compunit_symtab *cust;
   struct symtab_and_line stop_func_sal;
 
   fill_in_stop_func (gdbarch, ecs);
 
-  s = find_pc_symtab (stop_pc);
-  if (s && s->language != language_asm)
+  cust = find_pc_compunit_symtab (stop_pc);
+  if (cust != NULL && compunit_language (cust) != language_asm)
     ecs->stop_func_start = gdbarch_skip_prologue (gdbarch,
                                                  ecs->stop_func_start);
 
@@ -5931,10 +6077,7 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
                                    struct frame_info *frame,
                                    struct symbol *sym)
 {
-  volatile struct gdb_exception e;
-
-  /* We want to ignore errors here.  */
-  TRY_CATCH (e, RETURN_MASK_ERROR)
+  TRY
     {
       struct symbol *vsym;
       struct value *value;
@@ -5963,6 +6106,11 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
          inferior_thread ()->control.exception_resume_breakpoint = bp;
        }
     }
+  CATCH (e, RETURN_MASK_ERROR)
+    {
+      /* We want to ignore errors here.  */
+    }
+  END_CATCH
 }
 
 /* A helper for check_exception_resume that sets an
@@ -6003,7 +6151,6 @@ static void
 check_exception_resume (struct execution_control_state *ecs,
                        struct frame_info *frame)
 {
-  volatile struct gdb_exception e;
   struct bound_probe probe;
   struct symbol *func;
 
@@ -6022,7 +6169,7 @@ check_exception_resume (struct execution_control_state *ecs,
   if (!func)
     return;
 
-  TRY_CATCH (e, RETURN_MASK_ERROR)
+  TRY
     {
       const struct block *b;
       struct block_iterator iter;
@@ -6059,6 +6206,10 @@ check_exception_resume (struct execution_control_state *ecs,
            }
        }
     }
+  CATCH (e, RETURN_MASK_ERROR)
+    {
+    }
+  END_CATCH
 }
 
 static void
@@ -6096,12 +6247,10 @@ keep_going (struct execution_control_state *ecs)
         are supposed to pass through to the inferior.  Simply
         continue.  */
       discard_cleanups (old_cleanups);
-      resume (currently_stepping (ecs->event_thread),
-             ecs->event_thread->suspend.stop_signal);
+      resume (ecs->event_thread->suspend.stop_signal);
     }
   else
     {
-      volatile struct gdb_exception e;
       struct regcache *regcache = get_current_regcache ();
       int remove_bp;
       int remove_wps;
@@ -6130,7 +6279,12 @@ keep_going (struct execution_control_state *ecs)
       remove_wps = (ecs->event_thread->stepping_over_watchpoint
                    && !target_have_steppable_watchpoint);
 
-      if (remove_bp && !use_displaced_stepping (get_regcache_arch (regcache)))
+      /* We can't use displaced stepping if we need to step past a
+        watchpoint.  The instruction copied to the scratch pad would
+        still trigger the watchpoint.  */
+      if (remove_bp
+         && (remove_wps
+             || !use_displaced_stepping (get_regcache_arch (regcache))))
        {
          set_step_over_info (get_regcache_aspace (regcache),
                              regcache_read_pc (regcache), remove_wps);
@@ -6141,16 +6295,18 @@ keep_going (struct execution_control_state *ecs)
        clear_step_over_info ();
 
       /* Stop stepping if inserting breakpoints fails.  */
-      TRY_CATCH (e, RETURN_MASK_ERROR)
+      TRY
        {
          insert_breakpoints ();
        }
-      if (e.reason < 0)
+      CATCH (e, RETURN_MASK_ERROR)
        {
          exception_print (gdb_stderr, e);
          stop_waiting (ecs);
+         discard_cleanups (old_cleanups);
          return;
        }
+      END_CATCH
 
       ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
 
@@ -6169,8 +6325,7 @@ keep_going (struct execution_control_state *ecs)
        ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
 
       discard_cleanups (old_cleanups);
-      resume (currently_stepping (ecs->event_thread),
-             ecs->event_thread->suspend.stop_signal);
+      resume (ecs->event_thread->suspend.stop_signal);
     }
 
   prepare_to_wait (ecs);
@@ -6342,7 +6497,7 @@ print_stop_event (struct target_waitstatus *ws)
       if (tp->control.stop_step
          && frame_id_eq (tp->control.step_frame_id,
                          get_frame_id (get_current_frame ()))
-         && step_start_function == find_pc_function (stop_pc))
+         && tp->control.step_start_function == find_pc_function (stop_pc))
        {
          /* Finished step, just print source line.  */
          source_flag = SRC_LINE;
@@ -6948,72 +7103,6 @@ handle_completer (struct cmd_list_element *ignore,
   return return_val;
 }
 
-static void
-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 = gdb_buildargv (args);
-  old_chain = make_cleanup_freeargv (argv);
-  if (argv[1] != (char *) NULL)
-    {
-      char *argBuf;
-      int bufLen;
-
-      bufLen = strlen (argv[0]) + 20;
-      argBuf = (char *) xmalloc (bufLen);
-      if (argBuf)
-       {
-         int validFlag = 1;
-         enum gdb_signal oursig;
-
-         oursig = gdb_signal_from_name (argv[0]);
-         memset (argBuf, 0, bufLen);
-         if (strcmp (argv[1], "Q") == 0)
-           sprintf (argBuf, "%s %s", argv[0], "noprint");
-         else
-           {
-             if (strcmp (argv[1], "s") == 0)
-               {
-                 if (!signal_stop[oursig])
-                   sprintf (argBuf, "%s %s", argv[0], "stop");
-                 else
-                   sprintf (argBuf, "%s %s", argv[0], "nostop");
-               }
-             else if (strcmp (argv[1], "i") == 0)
-               {
-                 if (!signal_program[oursig])
-                   sprintf (argBuf, "%s %s", argv[0], "pass");
-                 else
-                   sprintf (argBuf, "%s %s", argv[0], "nopass");
-               }
-             else if (strcmp (argv[1], "r") == 0)
-               {
-                 if (!signal_print[oursig])
-                   sprintf (argBuf, "%s %s", argv[0], "print");
-                 else
-                   sprintf (argBuf, "%s %s", argv[0], "noprint");
-               }
-             else
-               validFlag = 0;
-           }
-         if (validFlag)
-           handle_command (argBuf, from_tty);
-         else
-           printf_filtered (_("Invalid signal handling flag.\n"));
-         if (argBuf)
-           xfree (argBuf);
-       }
-    }
-  do_cleanups (old_chain);
-}
-
 enum gdb_signal
 gdb_signal_from_command (int num)
 {
@@ -7596,29 +7685,6 @@ may be interspersed with actions, with the actions being performed for\n\
 all signals cumulatively specified."));
   set_cmd_completer (c, handle_completer);
 
-  if (xdb_commands)
-    {
-      add_com ("lz", class_info, signals_info, _("\
-What debugger does when program gets various signals.\n\
-Specify a signal as argument to print info on that signal only."));
-      add_com ("z", class_run, xdb_handle_command, _("\
-Specify how to handle a signal.\n\
-Args are signals and actions to apply to those signals.\n\
-Symbolic signals (e.g. SIGSEGV) are recommended but numeric signals\n\
-from 1-15 are allowed for compatibility with old versions of GDB.\n\
-Numeric ranges may be specified with the form LOW-HIGH (e.g. 1-5).\n\
-The special arg \"all\" is recognized to mean all signals except those\n\
-used by the debugger, typically SIGTRAP and SIGINT.\n\
-Recognized actions include \"s\" (toggles between stop and nostop),\n\
-\"r\" (toggles between print and noprint), \"i\" (toggles between pass and \
-nopass), \"Q\" (noprint)\n\
-Stop means reenter debugger if this signal happens (implies print).\n\
-Print means print a message if this signal happens.\n\
-Pass means let program see this signal; otherwise program doesn't know.\n\
-Ignore is a synonym for nopass and noignore is a synonym for pass.\n\
-Pass and Stop may be combined."));
-    }
-
   if (!dbx_commands)
     stop_command = add_cmd ("stop", class_obscure,
                            not_just_help_class_command, _("\
@@ -7775,9 +7841,8 @@ Set mode for locking scheduler during execution."), _("\
 Show mode for locking scheduler during execution."), _("\
 off  == no locking (threads may preempt at any time)\n\
 on   == full locking (no thread except the current thread may run)\n\
-step == scheduler locked during every single-step operation.\n\
-       In this mode, no other thread may run during a step command.\n\
-       Other threads may run while stepping over a function call ('next')."), 
+step == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
+       In this mode, other threads may run during other commands."),
                        set_schedlock_func,     /* traps on target vector */
                        show_scheduler_mode,
                        &setlist, &showlist);
This page took 0.039574 seconds and 4 git commands to generate.