* breakpoint.c (can_use_hardware_watchpoint): Handle the first
[binutils-gdb.git] / gdb / infrun.c
index 7379107020a3f5e87ac8549a5d7832edbb123d4c..031544633e9e76b81508c2dde6ff9194c0d3f6b7 100644 (file)
@@ -83,6 +83,16 @@ static void xdb_handle_command (char *args, int from_tty);
 
 static int prepare_to_proceed (int);
 
 
 static int prepare_to_proceed (int);
 
+static void print_exited_reason (int exitstatus);
+
+static void print_signal_exited_reason (enum target_signal siggnal);
+
+static void print_no_history_reason (void);
+
+static void print_signal_received_reason (enum target_signal siggnal);
+
+static void print_end_stepping_range_reason (void);
+
 void _initialize_infrun (void);
 
 void nullify_last_target_wait_ptid (void);
 void _initialize_infrun (void);
 
 void nullify_last_target_wait_ptid (void);
@@ -119,7 +129,7 @@ show_debug_displaced (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Displace stepping debugging is %s.\n"), value);
 }
 
   fprintf_filtered (file, _("Displace stepping debugging is %s.\n"), value);
 }
 
-static int debug_infrun = 0;
+int debug_infrun = 0;
 static void
 show_debug_infrun (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c, const char *value)
 static void
 show_debug_infrun (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c, const char *value)
@@ -178,16 +188,85 @@ show_debug_infrun (struct ui_file *file, int from_tty,
 #define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
 #endif
 
 #define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
 #endif
 
+/* "Observer mode" is somewhat like a more extreme version of
+   non-stop, in which all GDB operations that might affect the
+   target's execution have been disabled.  */
 
 
-/* Convert the #defines into values.  This is temporary until wfi control
-   flow is completely sorted out.  */
+static int non_stop_1 = 0;
 
 
-#ifndef CANNOT_STEP_HW_WATCHPOINTS
-#define CANNOT_STEP_HW_WATCHPOINTS 0
-#else
-#undef  CANNOT_STEP_HW_WATCHPOINTS
-#define CANNOT_STEP_HW_WATCHPOINTS 1
-#endif
+int observer_mode = 0;
+static int observer_mode_1 = 0;
+
+static void
+set_observer_mode (char *args, int from_tty,
+                  struct cmd_list_element *c)
+{
+  extern int pagination_enabled;
+
+  if (target_has_execution)
+    {
+      observer_mode_1 = observer_mode;
+      error (_("Cannot change this setting while the inferior is running."));
+    }
+
+  observer_mode = observer_mode_1;
+
+  may_write_registers = !observer_mode;
+  may_write_memory = !observer_mode;
+  may_insert_breakpoints = !observer_mode;
+  may_insert_tracepoints = !observer_mode;
+  /* We can insert fast tracepoints in or out of observer mode,
+     but enable them if we're going into this mode.  */
+  if (observer_mode)
+    may_insert_fast_tracepoints = 1;
+  may_stop = !observer_mode;
+  update_target_permissions ();
+
+  /* Going *into* observer mode we must force non-stop, then
+     going out we leave it that way.  */
+  if (observer_mode)
+    {
+      target_async_permitted = 1;
+      pagination_enabled = 0;
+      non_stop = non_stop_1 = 1;
+    }
+
+  if (from_tty)
+    printf_filtered (_("Observer mode is now %s.\n"),
+                    (observer_mode ? "on" : "off"));
+}
+
+static void
+show_observer_mode (struct ui_file *file, int from_tty,
+                   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Observer mode is %s.\n"), value);
+}
+
+/* This updates the value of observer mode based on changes in
+   permissions.  Note that we are deliberately ignoring the values of
+   may-write-registers and may-write-memory, since the user may have
+   reason to enable these during a session, for instance to turn on a
+   debugging-related global.  */
+
+void
+update_observer_mode (void)
+{
+  int newval;
+
+  newval = (!may_insert_breakpoints
+           && !may_insert_tracepoints
+           && may_insert_fast_tracepoints
+           && !may_stop
+           && non_stop);
+
+  /* Let the user know if things change.  */
+  if (newval != observer_mode)
+    printf_filtered (_("Observer mode is now %s.\n"),
+                    (newval ? "on" : "off"));
+
+  observer_mode = observer_mode_1 = newval;
+}
 
 /* Tables of how to react to signals; the user sets them.  */
 
 
 /* Tables of how to react to signals; the user sets them.  */
 
@@ -225,7 +304,7 @@ 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.  */
 
 /* 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;
+int stop_on_solib_events;
 static void
 show_stop_on_solib_events (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c, const char *value)
 static void
 show_stop_on_solib_events (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c, const char *value)
@@ -660,7 +739,6 @@ show_follow_exec_mode_string (struct ui_file *file, int from_tty,
 static void
 follow_exec (ptid_t pid, char *execd_pathname)
 {
 static void
 follow_exec (ptid_t pid, char *execd_pathname)
 {
-  struct target_ops *tgt;
   struct thread_info *th = inferior_thread ();
   struct inferior *inf = current_inferior ();
 
   struct thread_info *th = inferior_thread ();
   struct inferior *inf = current_inferior ();
 
@@ -720,6 +798,7 @@ follow_exec (ptid_t pid, char *execd_pathname)
       char *name = alloca (strlen (gdb_sysroot)
                            + strlen (execd_pathname)
                            + 1);
       char *name = alloca (strlen (gdb_sysroot)
                            + strlen (execd_pathname)
                            + 1);
+
       strcpy (name, gdb_sysroot);
       strcat (name, execd_pathname);
       execd_pathname = name;
       strcpy (name, gdb_sysroot);
       strcat (name, execd_pathname);
       execd_pathname = name;
@@ -736,7 +815,6 @@ follow_exec (ptid_t pid, char *execd_pathname)
   if (follow_exec_mode_string == follow_exec_mode_new)
     {
       struct program_space *pspace;
   if (follow_exec_mode_string == follow_exec_mode_new)
     {
       struct program_space *pspace;
-      struct inferior *new_inf;
 
       /* The user wants to keep the old inferior and program spaces
         around.  Create a new fresh one, and switch to it.  */
 
       /* The user wants to keep the old inferior and program spaces
         around.  Create a new fresh one, and switch to it.  */
@@ -1222,6 +1300,7 @@ static void
 write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
 {
   struct cleanup *ptid_cleanup = save_inferior_ptid ();
 write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
 {
   struct cleanup *ptid_cleanup = save_inferior_ptid ();
+
   inferior_ptid = ptid;
   write_memory (memaddr, myaddr, len);
   do_cleanups (ptid_cleanup);
   inferior_ptid = ptid;
   write_memory (memaddr, myaddr, len);
   do_cleanups (ptid_cleanup);
@@ -1248,6 +1327,7 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
   /* Restore the contents of the copy area.  */
   {
     ULONGEST len = gdbarch_max_insn_length (displaced->step_gdbarch);
   /* Restore the contents of the copy area.  */
   {
     ULONGEST len = gdbarch_max_insn_length (displaced->step_gdbarch);
+
     write_memory_ptid (displaced->step_ptid, displaced->step_copy,
                       displaced->step_saved_copy, len);
     if (debug_displaced)
     write_memory_ptid (displaced->step_ptid, displaced->step_copy,
                       displaced->step_saved_copy, len);
     if (debug_displaced)
@@ -1272,6 +1352,7 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
          relocate the PC.  */
       struct regcache *regcache = get_thread_regcache (event_ptid);
       CORE_ADDR pc = regcache_read_pc (regcache);
          relocate the PC.  */
       struct regcache *regcache = get_thread_regcache (event_ptid);
       CORE_ADDR pc = regcache_read_pc (regcache);
+
       pc = displaced->step_original + (pc - displaced->step_copy);
       regcache_write_pc (regcache, pc);
     }
       pc = displaced->step_original + (pc - displaced->step_copy);
       regcache_write_pc (regcache, pc);
     }
@@ -1444,7 +1525,8 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   int hw_step = 1;
 
 {
   int hw_step = 1;
 
-  if (gdbarch_software_single_step_p (gdbarch)
+  if (execution_direction == EXEC_FORWARD
+      && gdbarch_software_single_step_p (gdbarch)
       && gdbarch_software_single_step (gdbarch, get_current_frame ()))
     {
       hw_step = 0;
       && gdbarch_software_single_step (gdbarch, get_current_frame ()))
     {
       hw_step = 0;
@@ -1484,18 +1566,6 @@ resume (int step, enum target_signal sig)
                        "trap_expected=%d\n",
                        step, sig, tp->trap_expected);
 
                        "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
-     a hardware watchpoint. The kernel properly notices that it shouldn't
-     stop, because the hardware watchpoint is not triggered, but it forgets
-     the step request and continues the program normally.
-     Work around the problem by removing hardware watchpoints if a step is
-     requested, GDB will check for a hardware watchpoint trigger after the
-     step anyway.  */
-  if (CANNOT_STEP_HW_WATCHPOINTS && step)
-    remove_hw_watchpoints ();
-
-
   /* Normally, by the time we reach `resume', the breakpoints are either
      removed or inserted, as appropriate.  The exception is if we're sitting
      at a permanent breakpoint; we need to step over it, but permanent
   /* Normally, by the time we reach `resume', the breakpoints are either
      removed or inserted, as appropriate.  The exception is if we're sitting
      at a permanent breakpoint; we need to step over it, but permanent
@@ -2014,8 +2084,8 @@ void
 start_remote (int from_tty)
 {
   struct inferior *inferior;
 start_remote (int from_tty)
 {
   struct inferior *inferior;
-  init_wait_for_inferior ();
 
 
+  init_wait_for_inferior ();
   inferior = current_inferior ();
   inferior->stop_soon = STOP_QUIETLY_REMOTE;
 
   inferior = current_inferior ();
   inferior->stop_soon = STOP_QUIETLY_REMOTE;
 
@@ -2079,22 +2149,6 @@ enum infwait_states
   infwait_nonstep_watch_state
 };
 
   infwait_nonstep_watch_state
 };
 
-/* Why did the inferior stop? Used to print the appropriate messages
-   to the interface from within handle_inferior_event(). */
-enum inferior_stop_reason
-{
-  /* Step, next, nexti, stepi finished. */
-  END_STEPPING_RANGE,
-  /* Inferior terminated by signal. */
-  SIGNAL_EXITED,
-  /* Inferior exited. */
-  EXITED,
-  /* Inferior received signal, and user asked to be notified. */
-  SIGNAL_RECEIVED,
-  /* Reverse execution -- target ran out of history info.  */
-  NO_HISTORY
-};
-
 /* The PTID we'll do a target_wait on.*/
 ptid_t waiton_ptid;
 
 /* The PTID we'll do a target_wait on.*/
 ptid_t waiton_ptid;
 
@@ -2135,8 +2189,6 @@ static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
 static void stop_stepping (struct execution_control_state *ecs);
 static void prepare_to_wait (struct execution_control_state *ecs);
 static void keep_going (struct execution_control_state *ecs);
 static void stop_stepping (struct execution_control_state *ecs);
 static void prepare_to_wait (struct execution_control_state *ecs);
 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
 
 /* Callback for iterate over threads.  If the thread is stopped, but
    the user/frontend doesn't know about that yet, go through
@@ -2276,6 +2328,7 @@ delete_step_thread_step_resume_breakpoint (void)
         longjmp-resume breakpoint of the thread that just stopped
         stepping.  */
       struct thread_info *tp = inferior_thread ();
         longjmp-resume breakpoint of the thread that just stopped
         stepping.  */
       struct thread_info *tp = inferior_thread ();
+
       delete_step_resume_breakpoint (tp);
     }
   else
       delete_step_resume_breakpoint (tp);
     }
   else
@@ -2331,6 +2384,92 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
   ui_file_delete (tmp_stream);
 }
 
   ui_file_delete (tmp_stream);
 }
 
+/* Prepare and stabilize the inferior for detaching it.  E.g.,
+   detaching while a thread is displaced stepping is a recipe for
+   crashing it, as nothing would readjust the PC out of the scratch
+   pad.  */
+
+void
+prepare_for_detach (void)
+{
+  struct inferior *inf = current_inferior ();
+  ptid_t pid_ptid = pid_to_ptid (inf->pid);
+  struct cleanup *old_chain_1;
+  struct displaced_step_inferior_state *displaced;
+
+  displaced = get_displaced_stepping_state (inf->pid);
+
+  /* Is any thread of this process displaced stepping?  If not,
+     there's nothing else to do.  */
+  if (displaced == NULL || ptid_equal (displaced->step_ptid, null_ptid))
+    return;
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+                       "displaced-stepping in-process while detaching");
+
+  old_chain_1 = make_cleanup_restore_integer (&inf->detaching);
+  inf->detaching = 1;
+
+  while (!ptid_equal (displaced->step_ptid, null_ptid))
+    {
+      struct cleanup *old_chain_2;
+      struct execution_control_state ecss;
+      struct execution_control_state *ecs;
+
+      ecs = &ecss;
+      memset (ecs, 0, sizeof (*ecs));
+
+      overlay_cache_invalid = 1;
+
+      /* 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 targets that provide critical registers
+        as part of their normal status mechanism. */
+
+      registers_changed ();
+
+      if (deprecated_target_wait_hook)
+       ecs->ptid = deprecated_target_wait_hook (pid_ptid, &ecs->ws, 0);
+      else
+       ecs->ptid = target_wait (pid_ptid, &ecs->ws, 0);
+
+      if (debug_infrun)
+       print_target_wait_results (pid_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_2 = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+
+      /* In non-stop mode, each thread is handled individually.
+        Switch early, so the global state is set correctly for this
+        thread.  */
+      if (non_stop
+         && ecs->ws.kind != TARGET_WAITKIND_EXITED
+         && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED)
+       context_switch (ecs->ptid);
+
+      /* Now figure out what to do with the result of the result.  */
+      handle_inferior_event (ecs);
+
+      /* No error, don't finish the state yet.  */
+      discard_cleanups (old_chain_2);
+
+      /* Breakpoints and watchpoints are not installed on the target
+        at this point, and signals are passed directly to the
+        inferior, so this must mean the process is gone.  */
+      if (!ecs->wait_some_more)
+       {
+         discard_cleanups (old_chain_1);
+         error (_("Program exited while detaching"));
+       }
+    }
+
+  discard_cleanups (old_chain_1);
+}
+
 /* Wait for control to return from inferior to debugger.
 
    If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals
 /* Wait for control to return from inferior to debugger.
 
    If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals
@@ -2662,6 +2801,7 @@ adjust_pc_after_break (struct execution_control_state *ecs)
       || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
       struct cleanup *old_cleanups = NULL;
       || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
       struct cleanup *old_cleanups = NULL;
+
       if (RECORD_IS_USED)
        old_cleanups = record_gdb_operation_disable_set ();
 
       if (RECORD_IS_USED)
        old_cleanups = record_gdb_operation_disable_set ();
 
@@ -2815,6 +2955,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED)
     {
       struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
       && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED)
     {
       struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
+
       gdb_assert (inf);
       stop_soon = inf->stop_soon;
     }
       gdb_assert (inf);
       stop_soon = inf->stop_soon;
     }
@@ -2826,7 +2967,7 @@ handle_inferior_event (struct execution_control_state *ecs)
   target_last_waitstatus = ecs->ws;
 
   /* Always clear state belonging to the previous time we stopped.  */
   target_last_waitstatus = ecs->ws;
 
   /* Always clear state belonging to the previous time we stopped.  */
-  stop_stack_dummy = 0;
+  stop_stack_dummy = STOP_NONE;
 
   /* If it's a new process, add it to the thread database */
 
 
   /* If it's a new process, add it to the thread database */
 
@@ -3008,7 +3149,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
       target_terminal_ours (); /* Must do this before mourn anyway */
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
       target_terminal_ours (); /* Must do this before mourn anyway */
-      print_stop_reason (EXITED, ecs->ws.value.integer);
+      print_exited_reason (ecs->ws.value.integer);
 
       /* Record the exit code in the convenience variable $_exitcode, so
          that the user can inspect this again later.  */
 
       /* Record the exit code in the convenience variable $_exitcode, so
          that the user can inspect this again later.  */
@@ -3017,6 +3158,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
       singlestep_breakpoints_inserted_p = 0;
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
       singlestep_breakpoints_inserted_p = 0;
+      cancel_single_step_breakpoints ();
       stop_print_frame = 0;
       stop_stepping (ecs);
       return;
       stop_print_frame = 0;
       stop_stepping (ecs);
       return;
@@ -3038,8 +3180,9 @@ handle_inferior_event (struct execution_control_state *ecs)
          may be needed. */
       target_mourn_inferior ();
 
          may be needed. */
       target_mourn_inferior ();
 
-      print_stop_reason (SIGNAL_EXITED, ecs->ws.value.sig);
+      print_signal_exited_reason (ecs->ws.value.sig);
       singlestep_breakpoints_inserted_p = 0;
       singlestep_breakpoints_inserted_p = 0;
+      cancel_single_step_breakpoints ();
       stop_stepping (ecs);
       return;
 
       stop_stepping (ecs);
       return;
 
@@ -3077,6 +3220,13 @@ handle_inferior_event (struct execution_control_state *ecs)
          detach_breakpoints (child_pid);
        }
 
          detach_breakpoints (child_pid);
        }
 
+      if (singlestep_breakpoints_inserted_p)
+       {
+         /* Pull the single step breakpoints out of the target. */
+         remove_single_step_breakpoints ();
+         singlestep_breakpoints_inserted_p = 0;
+       }
+
       /* 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.  */
       /* 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.  */
@@ -3166,6 +3316,9 @@ handle_inferior_event (struct execution_control_state *ecs)
          reinit_frame_cache ();
        }
 
          reinit_frame_cache ();
        }
 
+      singlestep_breakpoints_inserted_p = 0;
+      cancel_single_step_breakpoints ();
+
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
       /* Do whatever is necessary to the parent branch of the vfork.  */
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
       /* Do whatever is necessary to the parent branch of the vfork.  */
@@ -3227,7 +3380,7 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_NO_HISTORY:
       /* Reverse execution: target ran out of history info.  */
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
     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);
+      print_no_history_reason ();
       stop_stepping (ecs);
       return;
     }
       stop_stepping (ecs);
       return;
     }
@@ -3286,6 +3439,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
       if (target_stopped_by_watchpoint ())
        {
           CORE_ADDR addr;
       if (target_stopped_by_watchpoint ())
        {
           CORE_ADDR addr;
+
          fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
 
           if (target_stopped_data_address (&current_target, &addr))
          fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
 
           if (target_stopped_data_address (&current_target, &addr))
@@ -3624,6 +3778,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
         the instruction and once for the delay slot.  */
       int step_through_delay
        = gdbarch_single_step_through_delay (gdbarch, frame);
         the instruction and once for the delay slot.  */
       int step_through_delay
        = gdbarch_single_step_through_delay (gdbarch, frame);
+
       if (debug_infrun && step_through_delay)
        fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
       if (ecs->event_thread->step_range_end == 0 && step_through_delay)
       if (debug_infrun && step_through_delay)
        fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
       if (ecs->event_thread->step_range_end == 0 && step_through_delay)
@@ -3787,6 +3942,7 @@ process_event_stop_test:
     {
       /* Signal not for debugging purposes.  */
       int printed = 0;
     {
       /* Signal not for debugging purposes.  */
       int printed = 0;
+      struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
 
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n",
 
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n",
@@ -3798,14 +3954,15 @@ process_event_stop_test:
        {
          printed = 1;
          target_terminal_ours_for_output ();
        {
          printed = 1;
          target_terminal_ours_for_output ();
-         print_stop_reason (SIGNAL_RECEIVED, ecs->event_thread->stop_signal);
+         print_signal_received_reason (ecs->event_thread->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
        }
       /* 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))
+         || (!inf->detaching
+             && signal_stop_state (ecs->event_thread->stop_signal)))
        {
          stop_stepping (ecs);
          return;
        {
          stop_stepping (ecs);
          return;
@@ -3890,9 +4047,15 @@ process_event_stop_test:
 
     if (what.call_dummy)
       {
 
     if (what.call_dummy)
       {
-       stop_stack_dummy = 1;
+       stop_stack_dummy = what.call_dummy;
       }
 
       }
 
+    /* If we hit an internal event that triggers symbol changes, the
+       current frame will be invalidated within bpstat_what (e.g., if
+       we hit an internal solib event).  Re-fetch it.  */
+    frame = get_current_frame ();
+    gdbarch = get_frame_arch (frame);
+
     switch (what.main_action)
       {
       case BPSTAT_WHAT_SET_LONGJMP_RESUME:
     switch (what.main_action)
       {
       case BPSTAT_WHAT_SET_LONGJMP_RESUME:
@@ -3935,7 +4098,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
        delete_step_resume_breakpoint (ecs->event_thread);
 
        ecs->event_thread->stop_step = 1;
        delete_step_resume_breakpoint (ecs->event_thread);
 
        ecs->event_thread->stop_step = 1;
-       print_stop_reason (END_STEPPING_RANGE, 0);
+       print_end_stepping_range_reason ();
        stop_stepping (ecs);
        return;
 
        stop_stepping (ecs);
        return;
 
@@ -3997,66 +4160,6 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          }
        break;
 
          }
        break;
 
-      case BPSTAT_WHAT_CHECK_SHLIBS:
-       {
-          if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_SHLIBS\n");
-
-         /* Check for any newly added shared libraries if we're
-            supposed to be adding them automatically.  Switch
-            terminal for any messages produced by
-            breakpoint_re_set.  */
-         target_terminal_ours_for_output ();
-         /* NOTE: cagney/2003-11-25: Make certain that the target
-            stack's section table is kept up-to-date.  Architectures,
-            (e.g., PPC64), use the section table to perform
-            operations such as address => section name and hence
-            require the table to contain all sections (including
-            those found in shared libraries).  */
-#ifdef SOLIB_ADD
-         SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
-#else
-         solib_add (NULL, 0, &current_target, auto_solib_add);
-#endif
-         target_terminal_inferior ();
-
-         /* If requested, stop when the dynamic linker notifies
-            gdb of events.  This allows the user to get control
-            and place breakpoints in initializer routines for
-            dynamically loaded objects (among other things).  */
-         if (stop_on_solib_events || stop_stack_dummy)
-           {
-             stop_stepping (ecs);
-             return;
-           }
-         else
-           {
-             /* We want to step over this breakpoint, then keep going.  */
-             ecs->event_thread->stepping_over_breakpoint = 1;
-             break;
-           }
-       }
-       break;
-
-      case BPSTAT_WHAT_CHECK_JIT:
-        if (debug_infrun)
-          fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_JIT\n");
-
-        /* Switch terminal for any messages produced by breakpoint_re_set.  */
-        target_terminal_ours_for_output ();
-
-        jit_event_handler (gdbarch);
-
-        target_terminal_inferior ();
-
-        /* We want to step over this breakpoint, then keep going.  */
-        ecs->event_thread->stepping_over_breakpoint = 1;
-
-        break;
-
-      case BPSTAT_WHAT_LAST:
-       /* Not a real code, but listed here to shut up gcc -Wall.  */
-
       case BPSTAT_WHAT_KEEP_CHECKING:
        break;
       }
       case BPSTAT_WHAT_KEEP_CHECKING:
        break;
       }
@@ -4073,6 +4176,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
   if (!non_stop)
     {
       struct thread_info *tp;
   if (!non_stop)
     {
       struct thread_info *tp;
+
       tp = iterate_over_threads (currently_stepping_or_nexting_callback,
                                 ecs->event_thread);
       if (tp)
       tp = iterate_over_threads (currently_stepping_or_nexting_callback,
                                 ecs->event_thread);
       if (tp)
@@ -4192,6 +4296,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
      the frame cache to be re-initialized, making our FRAME variable
      a dangling pointer.  */
   frame = get_current_frame ();
      the frame cache to be re-initialized, making our FRAME variable
      a dangling pointer.  */
   frame = get_current_frame ();
+  gdbarch = get_frame_arch (frame);
 
   /* If stepping through a line, keep going if still within it.
 
 
   /* If stepping through a line, keep going if still within it.
 
@@ -4223,7 +4328,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
          && execution_direction == EXEC_REVERSE)
        {
          ecs->event_thread->stop_step = 1;
          && execution_direction == EXEC_REVERSE)
        {
          ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
        }
       else
          stop_stepping (ecs);
        }
       else
@@ -4261,6 +4366,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
          /* Set up a step-resume breakpoint at the address
             indicated by SKIP_SOLIB_RESOLVER.  */
          struct symtab_and_line sr_sal;
          /* Set up a step-resume breakpoint at the address
             indicated by SKIP_SOLIB_RESOLVER.  */
          struct symtab_and_line sr_sal;
+
          init_sal (&sr_sal);
          sr_sal.pc = pc_after_resolver;
          sr_sal.pspace = get_frame_program_space (frame);
          init_sal (&sr_sal);
          sr_sal.pc = pc_after_resolver;
          sr_sal.pspace = get_frame_program_space (frame);
@@ -4332,7 +4438,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
             well.  FENN */
          /* And this works the same backward as frontward.  MVS */
          ecs->event_thread->stop_step = 1;
             well.  FENN */
          /* And this works the same backward as frontward.  MVS */
          ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
          return;
        }
          stop_stepping (ecs);
          return;
        }
@@ -4399,6 +4505,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
       if (real_stop_pc != 0 && in_solib_dynsym_resolve_code (real_stop_pc))
        {
          struct symtab_and_line sr_sal;
       if (real_stop_pc != 0 && in_solib_dynsym_resolve_code (real_stop_pc))
        {
          struct symtab_and_line sr_sal;
+
          init_sal (&sr_sal);
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
          init_sal (&sr_sal);
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
@@ -4437,7 +4544,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
          && step_stop_if_no_debug)
        {
          ecs->event_thread->stop_step = 1;
          && step_stop_if_no_debug)
        {
          ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
          return;
        }
          stop_stepping (ecs);
          return;
        }
@@ -4447,6 +4554,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
          /* 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;
          /* 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;
          sr_sal.pspace = get_frame_program_space (frame);
          init_sal (&sr_sal);
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
@@ -4485,6 +4593,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
             Set a breakpoint at its start and continue, then
             one more step will take us out.  */
          struct symtab_and_line sr_sal;
             Set a breakpoint at its start and continue, then
             one more step will take us out.  */
          struct symtab_and_line sr_sal;
+
          init_sal (&sr_sal);
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
          init_sal (&sr_sal);
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
@@ -4502,6 +4611,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
     {
       /* Determine where this trampoline returns.  */
       CORE_ADDR real_stop_pc;
     {
       /* Determine where this trampoline returns.  */
       CORE_ADDR real_stop_pc;
+
       real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
 
       if (debug_infrun)
       real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
 
       if (debug_infrun)
@@ -4558,7 +4668,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
             is set, we stop the step so that the user has a chance to
             switch in assembly mode.  */
          ecs->event_thread->stop_step = 1;
             is set, we stop the step so that the user has a chance to
             switch in assembly mode.  */
          ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
          return;
        }
          stop_stepping (ecs);
          return;
        }
@@ -4579,7 +4689,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepi/nexti\n");
       ecs->event_thread->stop_step = 1;
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepi/nexti\n");
       ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
       return;
     }
       stop_stepping (ecs);
       return;
     }
@@ -4593,7 +4703,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
       ecs->event_thread->stop_step = 1;
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
       ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
       return;
     }
       stop_stepping (ecs);
       return;
     }
@@ -4626,7 +4736,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
            step_into_inline_frame (ecs->ptid);
 
          ecs->event_thread->stop_step = 1;
            step_into_inline_frame (ecs->ptid);
 
          ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
          return;
        }
          stop_stepping (ecs);
          return;
        }
@@ -4641,7 +4751,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
          else
            {
              ecs->event_thread->stop_step = 1;
          else
            {
              ecs->event_thread->stop_step = 1;
-             print_stop_reason (END_STEPPING_RANGE, 0);
+             print_end_stepping_range_reason ();
              stop_stepping (ecs);
            }
          return;
              stop_stepping (ecs);
            }
          return;
@@ -4668,7 +4778,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
       else
        {
          ecs->event_thread->stop_step = 1;
       else
        {
          ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
        }
       return;
          stop_stepping (ecs);
        }
       return;
@@ -4685,7 +4795,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different line\n");
       ecs->event_thread->stop_step = 1;
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different line\n");
       ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
       return;
     }
       stop_stepping (ecs);
       return;
     }
@@ -4786,7 +4896,7 @@ handle_step_into_function (struct gdbarch *gdbarch,
     {
       /* We are already there: stop now.  */
       ecs->event_thread->stop_step = 1;
     {
       /* We are already there: stop now.  */
       ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
       return;
     }
       stop_stepping (ecs);
       return;
     }
@@ -4818,7 +4928,7 @@ handle_step_into_function_backward (struct gdbarch *gdbarch,
                                    struct execution_control_state *ecs)
 {
   struct symtab *s;
                                    struct execution_control_state *ecs)
 {
   struct symtab *s;
-  struct symtab_and_line stop_func_sal, sr_sal;
+  struct symtab_and_line stop_func_sal;
 
   s = find_pc_symtab (stop_pc);
   if (s && s->language != language_asm)
 
   s = find_pc_symtab (stop_pc);
   if (s && s->language != language_asm)
@@ -4832,7 +4942,7 @@ handle_step_into_function_backward (struct gdbarch *gdbarch,
     {
       /* We're there already.  Just stop stepping now.  */
       ecs->event_thread->stop_step = 1;
     {
       /* We're there already.  Just stop stepping now.  */
       ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
     }
   else
       stop_stepping (ecs);
     }
   else
@@ -5010,6 +5120,7 @@ keep_going (struct execution_control_state *ecs)
       if (ecs->event_thread->stepping_over_breakpoint)
        {
          struct regcache *thread_regcache = get_thread_regcache (ecs->ptid);
       if (ecs->event_thread->stepping_over_breakpoint)
        {
          struct regcache *thread_regcache = get_thread_regcache (ecs->ptid);
+
          if (!use_displaced_stepping (get_regcache_arch (thread_regcache)))
            /* Since we can't do a displaced step, we have to remove
               the breakpoint while we step it.  To keep things
          if (!use_displaced_stepping (get_regcache_arch (thread_regcache)))
            /* Since we can't do a displaced step, we have to remove
               the breakpoint while we step it.  To keep things
@@ -5019,6 +5130,7 @@ keep_going (struct execution_control_state *ecs)
       else
        {
          struct gdb_exception e;
       else
        {
          struct gdb_exception e;
+
          /* Stop stepping when inserting breakpoints
             has failed.  */
          TRY_CATCH (e, RETURN_MASK_ERROR)
          /* Stop stepping when inserting breakpoints
             has failed.  */
          TRY_CATCH (e, RETURN_MASK_ERROR)
@@ -5075,116 +5187,121 @@ prepare_to_wait (struct execution_control_state *ecs)
   ecs->wait_some_more = 1;
 }
 
   ecs->wait_some_more = 1;
 }
 
-/* Print why the inferior has stopped. We always print something when
-   the inferior exits, or receives a signal. The rest of the cases are
-   dealt with later on in normal_stop() and print_it_typical().  Ideally
-   there should be a call to this function from handle_inferior_event()
-   each time stop_stepping() is called.*/
+/* Several print_*_reason functions to print why the inferior has stopped.
+   We always print something when the inferior exits, or receives a signal.
+   The rest of the cases are dealt with later on in normal_stop and
+   print_it_typical.  Ideally there should be a call to one of these
+   print_*_reason functions functions from handle_inferior_event each time
+   stop_stepping is called.  */
+
+/* Print why the inferior has stopped.  
+   We are done with a step/next/si/ni command, print why the inferior has
+   stopped.  For now print nothing.  Print a message only if not in the middle
+   of doing a "step n" operation for n > 1.  */
+
+static void
+print_end_stepping_range_reason (void)
+{
+  if ((!inferior_thread ()->step_multi || !inferior_thread ()->stop_step)
+      && ui_out_is_mi_like_p (uiout))
+    ui_out_field_string (uiout, "reason",
+                         async_reason_lookup (EXEC_ASYNC_END_STEPPING_RANGE));
+}
+
+/* The inferior was terminated by a signal, print why it stopped.  */
+
+static void
+print_signal_exited_reason (enum target_signal siggnal)
+{
+  annotate_signalled ();
+  if (ui_out_is_mi_like_p (uiout))
+    ui_out_field_string
+      (uiout, "reason", async_reason_lookup (EXEC_ASYNC_EXITED_SIGNALLED));
+  ui_out_text (uiout, "\nProgram terminated with signal ");
+  annotate_signal_name ();
+  ui_out_field_string (uiout, "signal-name",
+                      target_signal_to_name (siggnal));
+  annotate_signal_name_end ();
+  ui_out_text (uiout, ", ");
+  annotate_signal_string ();
+  ui_out_field_string (uiout, "signal-meaning",
+                      target_signal_to_string (siggnal));
+  annotate_signal_string_end ();
+  ui_out_text (uiout, ".\n");
+  ui_out_text (uiout, "The program no longer exists.\n");
+}
+
+/* The inferior program is finished, print why it stopped.  */
+
 static void
 static void
-print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
+print_exited_reason (int exitstatus)
 {
 {
-  switch (stop_reason)
+  annotate_exited (exitstatus);
+  if (exitstatus)
+    {
+      if (ui_out_is_mi_like_p (uiout))
+       ui_out_field_string (uiout, "reason", 
+                            async_reason_lookup (EXEC_ASYNC_EXITED));
+      ui_out_text (uiout, "\nProgram exited with code ");
+      ui_out_field_fmt (uiout, "exit-code", "0%o", (unsigned int) exitstatus);
+      ui_out_text (uiout, ".\n");
+    }
+  else
     {
     {
-    case END_STEPPING_RANGE:
-      /* We are done with a step/next/si/ni command. */
-      /* For now print nothing. */
-      /* Print a message only if not in the middle of doing a "step n"
-         operation for n > 1 */
-      if (!inferior_thread ()->step_multi
-         || !inferior_thread ()->stop_step)
-       if (ui_out_is_mi_like_p (uiout))
-         ui_out_field_string
-           (uiout, "reason",
-            async_reason_lookup (EXEC_ASYNC_END_STEPPING_RANGE));
-      break;
-    case SIGNAL_EXITED:
-      /* The inferior was terminated by a signal. */
-      annotate_signalled ();
       if (ui_out_is_mi_like_p (uiout))
        ui_out_field_string
       if (ui_out_is_mi_like_p (uiout))
        ui_out_field_string
-         (uiout, "reason",
-          async_reason_lookup (EXEC_ASYNC_EXITED_SIGNALLED));
-      ui_out_text (uiout, "\nProgram terminated with signal ");
+         (uiout, "reason", async_reason_lookup (EXEC_ASYNC_EXITED_NORMALLY));
+      ui_out_text (uiout, "\nProgram exited normally.\n");
+    }
+  /* Support the --return-child-result option.  */
+  return_child_result_value = exitstatus;
+}
+
+/* Signal received, print why the inferior has stopped.  The signal table
+   tells us to print about it. */
+
+static void
+print_signal_received_reason (enum target_signal siggnal)
+{
+  annotate_signal ();
+
+  if (siggnal == 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 ();
       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",
       ui_out_field_string (uiout, "signal-name",
-                          target_signal_to_name (stop_info));
+                          target_signal_to_name (siggnal));
       annotate_signal_name_end ();
       ui_out_text (uiout, ", ");
       annotate_signal_string ();
       ui_out_field_string (uiout, "signal-meaning",
       annotate_signal_name_end ();
       ui_out_text (uiout, ", ");
       annotate_signal_string ();
       ui_out_field_string (uiout, "signal-meaning",
-                          target_signal_to_string (stop_info));
+                          target_signal_to_string (siggnal));
       annotate_signal_string_end ();
       annotate_signal_string_end ();
-      ui_out_text (uiout, ".\n");
-      ui_out_text (uiout, "The program no longer exists.\n");
-      break;
-    case EXITED:
-      /* The inferior program is finished. */
-      annotate_exited (stop_info);
-      if (stop_info)
-       {
-         if (ui_out_is_mi_like_p (uiout))
-           ui_out_field_string (uiout, "reason", 
-                                async_reason_lookup (EXEC_ASYNC_EXITED));
-         ui_out_text (uiout, "\nProgram exited with code ");
-         ui_out_field_fmt (uiout, "exit-code", "0%o",
-                           (unsigned int) stop_info);
-         ui_out_text (uiout, ".\n");
-       }
-      else
-       {
-         if (ui_out_is_mi_like_p (uiout))
-           ui_out_field_string
-             (uiout, "reason",
-              async_reason_lookup (EXEC_ASYNC_EXITED_NORMALLY));
-         ui_out_text (uiout, "\nProgram exited normally.\n");
-       }
-      /* Support the --return-child-result option.  */
-      return_child_result_value = stop_info;
-      break;
-    case SIGNAL_RECEIVED:
-      /* Signal received.  The signal table tells us to print about
-        it. */
-      annotate_signal ();
+    }
+  ui_out_text (uiout, ".\n");
+}
 
 
-      if (stop_info == TARGET_SIGNAL_0 && !ui_out_is_mi_like_p (uiout))
-       {
-         struct thread_info *t = inferior_thread ();
+/* Reverse execution: target ran out of history info, print why the inferior
+   has stopped.  */
 
 
-         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"));
-      break;
-    }
+static void
+print_no_history_reason (void)
+{
+  ui_out_text (uiout, "\nNo more reverse-execution history.\n");
 }
 }
-\f
 
 /* Here to return control to GDB when the inferior stops for real.
    Print appropriate messages, remove breakpoints, give terminal our modes.
 
 /* Here to return control to GDB when the inferior stops for real.
    Print appropriate messages, remove breakpoints, give terminal our modes.
@@ -5380,12 +5497,13 @@ Further execution is probably impossible.\n"));
       stop_registers = regcache_dup (get_current_regcache ());
     }
 
       stop_registers = regcache_dup (get_current_regcache ());
     }
 
-  if (stop_stack_dummy)
+  if (stop_stack_dummy == STOP_STACK_DUMMY)
     {
       /* 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 ();
     {
       /* 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
       gdb_assert (get_frame_type (frame) == DUMMY_FRAME);
       frame_pop (frame);
       /* frame_pop() calls reinit_frame_cache as the last thing it does
@@ -5473,6 +5591,7 @@ int
 signal_stop_update (int signo, int state)
 {
   int ret = signal_stop[signo];
 signal_stop_update (int signo, int state)
 {
   int ret = signal_stop[signo];
+
   signal_stop[signo] = state;
   return ret;
 }
   signal_stop[signo] = state;
   return ret;
 }
@@ -5481,6 +5600,7 @@ int
 signal_print_update (int signo, int state)
 {
   int ret = signal_print[signo];
 signal_print_update (int signo, int state)
 {
   int ret = signal_print[signo];
+
   signal_print[signo] = state;
   return ret;
 }
   signal_print[signo] = state;
   return ret;
 }
@@ -5489,6 +5609,7 @@ int
 signal_pass_update (int signo, int state)
 {
   int ret = signal_program[signo];
 signal_pass_update (int signo, int state)
 {
   int ret = signal_program[signo];
+
   signal_program[signo] = state;
   return ret;
 }
   signal_program[signo] = state;
   return ret;
 }
@@ -5772,6 +5893,7 @@ static void
 signals_info (char *signum_exp, int from_tty)
 {
   enum target_signal oursig;
 signals_info (char *signum_exp, int from_tty)
 {
   enum target_signal oursig;
+
   sig_print_header ();
 
   if (signum_exp)
   sig_print_header ();
 
   if (signum_exp)
@@ -5870,6 +5992,7 @@ siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var)
       && gdbarch_get_siginfo_type_p (gdbarch))
     {
       struct type *type = gdbarch_get_siginfo_type (gdbarch);
       && gdbarch_get_siginfo_type_p (gdbarch))
     {
       struct type *type = gdbarch_get_siginfo_type (gdbarch);
+
       return allocate_computed_value (type, &siginfo_value_funcs, NULL);
     }
 
       return allocate_computed_value (type, &siginfo_value_funcs, NULL);
     }
 
@@ -5958,7 +6081,7 @@ struct inferior_status
 {
   bpstat stop_bpstat;
   int stop_step;
 {
   bpstat stop_bpstat;
   int stop_step;
-  int stop_stack_dummy;
+  enum stop_stack_kind stop_stack_dummy;
   int stopped_by_random_signal;
   int stepping_over_breakpoint;
   CORE_ADDR step_range_start;
   int stopped_by_random_signal;
   int stepping_over_breakpoint;
   CORE_ADDR step_range_start;
@@ -6245,8 +6368,7 @@ ptid_match (ptid_t ptid, ptid_t filter)
   /* Since both parameters have the same type, prevent easy mistakes
      from happening.  */
   gdb_assert (!ptid_equal (ptid, minus_one_ptid)
   /* Since both parameters have the same type, prevent easy mistakes
      from happening.  */
   gdb_assert (!ptid_equal (ptid, minus_one_ptid)
-             && !ptid_equal (ptid, null_ptid)
-             && !ptid_is_pid (ptid));
+             && !ptid_equal (ptid, null_ptid));
 
   if (ptid_equal (filter, minus_one_ptid))
     return 1;
 
   if (ptid_equal (filter, minus_one_ptid))
     return 1;
@@ -6267,6 +6389,7 @@ static void
 restore_inferior_ptid (void *arg)
 {
   ptid_t *saved_ptid_ptr = arg;
 restore_inferior_ptid (void *arg)
 {
   ptid_t *saved_ptid_ptr = arg;
+
   inferior_ptid = *saved_ptid_ptr;
   xfree (arg);
 }
   inferior_ptid = *saved_ptid_ptr;
   xfree (arg);
 }
@@ -6311,6 +6434,11 @@ set_exec_direction_func (char *args, int from_tty,
       else if (!strcmp (exec_direction, exec_reverse))
        execution_direction = EXEC_REVERSE;
     }
       else if (!strcmp (exec_direction, exec_reverse))
        execution_direction = EXEC_REVERSE;
     }
+  else
+    {
+      exec_direction = exec_forward;
+      error (_("Target does not support this operation."));
+    }
 }
 
 static void
 }
 
 static void
@@ -6336,7 +6464,6 @@ show_exec_direction_func (struct ui_file *out, int from_tty,
 /* User interface for non-stop mode.  */
 
 int non_stop = 0;
 /* User interface for non-stop mode.  */
 
 int non_stop = 0;
-static int non_stop_1 = 0;
 
 static void
 set_non_stop (char *args, int from_tty,
 
 static void
 set_non_stop (char *args, int from_tty,
@@ -6373,7 +6500,6 @@ _initialize_infrun (void)
 {
   int i;
   int numsigs;
 {
   int i;
   int numsigs;
-  struct cmd_list_element *c;
 
   add_info ("signals", signals_info, _("\
 What debugger does when program gets various signals.\n\
 
   add_info ("signals", signals_info, _("\
 What debugger does when program gets various signals.\n\
@@ -6408,7 +6534,7 @@ 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\
 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\
+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\
 \"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\
@@ -6542,7 +6668,7 @@ An exec call replaces the program image of a process.\n\
 \n\
 follow-exec-mode can be:\n\
 \n\
 \n\
 follow-exec-mode can be:\n\
 \n\
-  new - the debugger creates a new inferior and rebinds the process \n\
+  new - the debugger creates a new inferior and rebinds the process\n\
 to this new inferior.  The program the process was running before\n\
 the exec call can be restarted afterwards by restarting the original\n\
 inferior.\n\
 to this new inferior.  The program the process was running before\n\
 the exec call can be restarted afterwards by restarting the original\n\
 inferior.\n\
@@ -6639,4 +6765,17 @@ Tells gdb whether to detach the child of a fork."),
      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);
      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);
+
+  add_setshow_boolean_cmd ("observer", no_class,
+                          &observer_mode_1, _("\
+Set whether gdb controls the inferior in observer mode."), _("\
+Show whether gdb controls the inferior in observer mode."), _("\
+In observer mode, GDB can get data from the inferior, but not\n\
+affect its execution.  Registers and memory may not be changed,\n\
+breakpoints may not be set, and the program cannot be interrupted\n\
+or signalled."),
+                          set_observer_mode,
+                          show_observer_mode,
+                          &setlist,
+                          &showlist);
 }
 }