infrun.c:handle_inferior_event: Remove some more dead code.
[deliverable/binutils-gdb.git] / gdb / infrun.c
index bd209f76d258f45505e937789ce91802c7d73fdc..8b1b668a41c2b873a1ebbe14089be44e3502cbaa 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-struct-independent code to start (run) and stop an inferior
    process.
 
-   Copyright (C) 1986-2012 Free Software Foundation, Inc.
+   Copyright (C) 1986-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -49,6 +49,7 @@
 #include "mi/mi-common.h"
 #include "event-top.h"
 #include "record.h"
+#include "record-full.h"
 #include "inline-frame.h"
 #include "jit.h"
 #include "tracepoint.h"
@@ -57,6 +58,8 @@
 #include "skip.h"
 #include "probe.h"
 #include "objfiles.h"
+#include "completer.h"
+#include "target-descriptions.h"
 
 /* Prototypes for local functions */
 
@@ -129,8 +132,12 @@ int sync_execution = 0;
 
 static ptid_t previous_inferior_ptid;
 
-/* Default behavior is to detach newly forked processes (legacy).  */
-int detach_fork = 1;
+/* If set (default for legacy reasons), when following a fork, GDB
+   will detach from one of the fork branches, child or parent.
+   Exactly which branch is detached depends on 'set follow-fork-mode'
+   setting.  */
+
+static int detach_fork = 1;
 
 int debug_displaced = 0;
 static void
@@ -140,7 +147,7 @@ show_debug_displaced (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Displace stepping debugging is %s.\n"), value);
 }
 
-int debug_infrun = 0;
+unsigned int debug_infrun = 0;
 static void
 show_debug_infrun (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c, const char *value)
@@ -178,64 +185,37 @@ set_disable_randomization (char *args, int from_tty,
             "this platform."));
 }
 
+/* User interface for non-stop mode.  */
 
-/* If the program uses ELF-style shared libraries, then calls to
-   functions in shared libraries go through stubs, which live in a
-   table called the PLT (Procedure Linkage Table).  The first time the
-   function is called, the stub sends control to the dynamic linker,
-   which looks up the function's real address, patches the stub so
-   that future calls will go directly to the function, and then passes
-   control to the function.
-
-   If we are stepping at the source level, we don't want to see any of
-   this --- we just want to skip over the stub and the dynamic linker.
-   The simple approach is to single-step until control leaves the
-   dynamic linker.
-
-   However, on some systems (e.g., Red Hat's 5.2 distribution) the
-   dynamic linker calls functions in the shared C library, so you
-   can't tell from the PC alone whether the dynamic linker is still
-   running.  In this case, we use a step-resume breakpoint to get us
-   past the dynamic linker, as if we were using "next" to step over a
-   function call.
-
-   in_solib_dynsym_resolve_code() says whether we're in the dynamic
-   linker code or not.  Normally, this means we single-step.  However,
-   if SKIP_SOLIB_RESOLVER then returns non-zero, then its value is an
-   address where we can place a step-resume breakpoint to get past the
-   linker's symbol resolution function.
-
-   in_solib_dynsym_resolve_code() can generally be implemented in a
-   pretty portable way, by comparing the PC against the address ranges
-   of the dynamic linker's sections.
-
-   SKIP_SOLIB_RESOLVER is generally going to be system-specific, since
-   it depends on internal details of the dynamic linker.  It's usually
-   not too hard to figure out where to put a breakpoint, but it
-   certainly isn't portable.  SKIP_SOLIB_RESOLVER should do plenty of
-   sanity checking.  If it can't figure things out, returning zero and
-   getting the (possibly confusing) stepping behavior is better than
-   signalling an error, which will obscure the change in the
-   inferior's state.  */
-
-/* This function returns TRUE if pc is the address of an instruction
-   that lies within the dynamic linker (such as the event hook, or the
-   dld itself).
-
-   This function must be used only when a dynamic linker event has
-   been caught, and the inferior is being stepped out of the hook, or
-   undefined results are guaranteed.  */
-
-#ifndef SOLIB_IN_DYNAMIC_LINKER
-#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
-#endif
+int non_stop = 0;
+static int non_stop_1 = 0;
+
+static void
+set_non_stop (char *args, int from_tty,
+             struct cmd_list_element *c)
+{
+  if (target_has_execution)
+    {
+      non_stop_1 = non_stop;
+      error (_("Cannot change this setting while the inferior is running."));
+    }
+
+  non_stop = non_stop_1;
+}
+
+static void
+show_non_stop (struct ui_file *file, int from_tty,
+              struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file,
+                   _("Controlling the inferior in non-stop mode is %s.\n"),
+                   value);
+}
 
 /* "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.  */
 
-static int non_stop_1 = 0;
-
 int observer_mode = 0;
 static int observer_mode_1 = 0;
 
@@ -243,8 +223,6 @@ 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;
@@ -316,6 +294,12 @@ static unsigned char *signal_stop;
 static unsigned char *signal_print;
 static unsigned char *signal_program;
 
+/* Table of signals that are registered with "catch signal".  A
+   non-zero entry indicates that the signal is caught by some "catch
+   signal" command.  This has size GDB_SIGNAL_LAST, to accommodate all
+   signals.  */
+static unsigned char *signal_catch;
+
 /* Table of signals that the target may silently handle.
    This is automatically determined from the flags above,
    and simply cached here.  */
@@ -361,6 +345,16 @@ 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;
+
+/* Enable or disable optional shared library event breakpoints
+   as appropriate when the above flag is changed.  */
+
+static void
+set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
+{
+  update_solib_breakpoints ();
+}
+
 static void
 show_stop_on_solib_events (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c, const char *value)
@@ -395,7 +389,7 @@ static void context_switch (ptid_t ptid);
 
 void init_thread_stepping_state (struct thread_info *tss);
 
-void init_infwait_state (void);
+static void init_infwait_state (void);
 
 static const char follow_fork_mode_child[] = "child";
 static const char follow_fork_mode_parent[] = "parent";
@@ -507,7 +501,7 @@ follow_fork (void)
 
        /* Tell the target to do whatever is necessary to follow
           either parent or child.  */
-       if (target_follow_fork (follow_child))
+       if (target_follow_fork (follow_child, detach_fork))
          {
            /* Target refused to follow, or there's some other reason
               we shouldn't resume.  */
@@ -662,7 +656,18 @@ handle_vfork_child_exec_or_exit (int exec)
 
          /* follow-fork child, detach-on-fork on.  */
 
-         old_chain = make_cleanup_restore_current_thread ();
+         inf->vfork_parent->pending_detach = 0;
+
+         if (!exec)
+           {
+             /* If we're handling a child exit, then inferior_ptid
+                points at the inferior's pid, not to a thread.  */
+             old_chain = save_inferior_ptid ();
+             save_current_program_space ();
+             save_current_inferior ();
+           }
+         else
+           old_chain = save_current_space_and_thread ();
 
          /* We're letting loose of the parent.  */
          tp = any_live_thread_of_process (inf->vfork_parent->pid);
@@ -786,7 +791,7 @@ handle_vfork_child_exec_or_exit (int exec)
     }
 }
 
-/* Enum strings for "set|show displaced-stepping".  */
+/* Enum strings for "set|show follow-exec-mode".  */
 
 static const char follow_exec_mode_new[] = "new";
 static const char follow_exec_mode_same[] = "same";
@@ -901,6 +906,16 @@ follow_exec (ptid_t pid, char *execd_pathname)
       set_current_inferior (inf);
       set_current_program_space (pspace);
     }
+  else
+    {
+      /* The old description may no longer be fit for the new image.
+        E.g, a 64-bit process exec'ed a 32-bit process.  Clear the
+        old description; we'll read a new one below.  No need to do
+        this on "follow-exec-mode new", as the old inferior stays
+        around (its description is later cleared/refetched on
+        restart).  */
+      target_clear_description ();
+    }
 
   gdb_assert (current_program_space == inf->pspace);
 
@@ -920,11 +935,15 @@ follow_exec (ptid_t pid, char *execd_pathname)
   if ((inf->symfile_flags & SYMFILE_NO_READ) == 0)
     set_initial_language ();
 
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
-  SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
-#else
+  /* If the target can specify a description, read it.  Must do this
+     after flipping to the new executable (because the target supplied
+     description must be compatible with the executable's
+     architecture, and the old executable may e.g., be 32-bit, while
+     the new one 64-bit), and before anything involving memory or
+     registers.  */
+  target_find_description ();
+
   solib_create_inferior_hook (0);
-#endif
 
   jit_inferior_created_hook ();
 
@@ -1277,6 +1296,7 @@ static int
 displaced_step_prepare (ptid_t ptid)
 {
   struct cleanup *old_cleanups, *ignore_cleanups;
+  struct thread_info *tp = find_thread_ptid (ptid);
   struct regcache *regcache = get_thread_regcache (ptid);
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   CORE_ADDR original, copy;
@@ -1289,6 +1309,12 @@ displaced_step_prepare (ptid_t ptid)
      support displaced stepping.  */
   gdb_assert (gdbarch_displaced_step_copy_insn_p (gdbarch));
 
+  /* Disable range stepping while executing in the scratch pad.  We
+     want a single-step even if executing the displaced instruction in
+     the scratch buffer lands within the stepping range (e.g., a
+     jump/branch).  */
+  tp->control.may_range_step = 0;
+
   /* We have to displaced step one thread at a time, as we only have
      access to a single scratch space per inferior.  */
 
@@ -1723,9 +1749,10 @@ resume (int step, enum gdb_signal sig)
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
-                        "infrun: resume (step=%d, signal=%d), "
+                       "infrun: resume (step=%d, signal=%s), "
                        "trap_expected=%d, current thread [%s] at %s\n",
-                       step, sig, tp->control.trap_expected,
+                       step, gdb_signal_to_symbol_string (sig),
+                       tp->control.trap_expected,
                        target_pid_to_str (inferior_ptid),
                        paddress (gdbarch, pc));
 
@@ -1744,6 +1771,11 @@ how to step past a permanent breakpoint on this architecture.  Try using\n\
 a command like `return' or `jump' to continue execution."));
     }
 
+  /* If we have a breakpoint to step over, make sure to do a single
+     step only.  Same if we have software watchpoints.  */
+  if (tp->control.trap_expected || bpstat_should_step ())
+    tp->control.may_range_step = 0;
+
   /* If enabled, step over breakpoints by executing a copy of the
      instruction at a different address.
 
@@ -1905,6 +1937,16 @@ a command like `return' or `jump' to continue execution."));
           displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
         }
 
+      if (tp->control.may_range_step)
+       {
+         /* If we're resuming a thread with the PC out of the step
+            range, then we're doing some nested/finer run control
+            operation, like stepping the thread out of the dynamic
+            linker or the displaced stepping scratch pad.  We
+            shouldn't have allowed a range step then.  */
+         gdb_assert (pc_in_thread_step_range (pc, tp));
+       }
+
       /* Install inferior's terminal modes.  */
       target_terminal_inferior ();
 
@@ -1946,6 +1988,7 @@ clear_proceed_status_thread (struct thread_info *tp)
   tp->control.trap_expected = 0;
   tp->control.step_range_start = 0;
   tp->control.step_range_end = 0;
+  tp->control.may_range_step = 0;
   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;
@@ -2102,7 +2145,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
   struct thread_info *tp;
   CORE_ADDR pc;
   struct address_space *aspace;
-  int oneproc = 0;
+  /* GDB may force the inferior to step due to various reasons.  */
+  int force_step = 0;
 
   /* If we're stopped at a fork/vfork, follow the branch set by the
      "set follow-fork-mode" command; otherwise, we'll just proceed
@@ -2142,13 +2186,13 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
           actually be executing the breakpoint insn anyway.
           We'll be (un-)executing the previous instruction.  */
 
-       oneproc = 1;
+       force_step = 1;
       else if (gdbarch_single_step_through_delay_p (gdbarch)
               && gdbarch_single_step_through_delay (gdbarch,
                                                     get_current_frame ()))
        /* We stepped onto an instruction that needs to be stepped
           again before re-inserting the breakpoint, do so.  */
-       oneproc = 1;
+       force_step = 1;
     }
   else
     {
@@ -2157,8 +2201,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
-                       "infrun: proceed (addr=%s, signal=%d, step=%d)\n",
-                       paddress (gdbarch, addr), siggnal, step);
+                       "infrun: proceed (addr=%s, signal=%s, step=%d)\n",
+                       paddress (gdbarch, addr),
+                       gdb_signal_to_symbol_string (siggnal), step);
 
   if (non_stop)
     /* In non-stop, each thread is handled individually.  The context
@@ -2179,13 +2224,13 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
         is required it returns TRUE and sets the current thread to
         the old thread.  */
       if (prepare_to_proceed (step))
-       oneproc = 1;
+       force_step = 1;
     }
 
   /* prepare_to_proceed may change the current thread.  */
   tp = inferior_thread ();
 
-  if (oneproc)
+  if (force_step)
     {
       tp->control.trap_expected = 1;
       /* If displaced stepping is enabled, we can step over the
@@ -2273,7 +2318,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
   init_infwait_state ();
 
   /* Resume inferior.  */
-  resume (oneproc || step || bpstat_should_step (), tp->suspend.stop_signal);
+  resume (force_step || step || bpstat_should_step (),
+         tp->suspend.stop_signal);
 
   /* Wait for it to stop (if not standalone)
      and in any case decode why it stopped, and act accordingly.  */
@@ -2361,7 +2407,7 @@ enum infwait_states
 ptid_t waiton_ptid;
 
 /* Current inferior wait state.  */
-enum infwait_states infwait_state;
+static enum infwait_states infwait_state;
 
 /* Data to be passed around while handling an event.  This data is
    discarded between events.  */
@@ -2563,14 +2609,15 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
      is set.  */
 
   fprintf_unfiltered (tmp_stream,
-                     "infrun: target_wait (%d", PIDGET (waiton_ptid));
-  if (PIDGET (waiton_ptid) != -1)
+                     "infrun: target_wait (%d", ptid_get_pid (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",
-                     PIDGET (result_ptid), target_pid_to_str (result_ptid));
+                     ptid_get_pid (result_ptid),
+                     target_pid_to_str (result_ptid));
   fprintf_unfiltered (tmp_stream,
                      "infrun:   %s\n",
                      status_string);
@@ -2968,10 +3015,10 @@ adjust_pc_after_break (struct execution_control_state *ecs)
   if (software_breakpoint_inserted_here_p (aspace, breakpoint_pc)
       || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
-      struct cleanup *old_cleanups = NULL;
+      struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
 
       if (RECORD_IS_USED)
-       old_cleanups = record_gdb_operation_disable_set ();
+       record_full_gdb_operation_disable_set ();
 
       /* When using hardware single-step, a SIGTRAP is reported for both
         a completed single-step and a software breakpoint.  Need to
@@ -2997,32 +3044,17 @@ adjust_pc_after_break (struct execution_control_state *ecs)
          || ecs->event_thread->prev_pc == breakpoint_pc)
        regcache_write_pc (regcache, breakpoint_pc);
 
-      if (RECORD_IS_USED)
-       do_cleanups (old_cleanups);
+      do_cleanups (old_cleanups);
     }
 }
 
-void
+static void
 init_infwait_state (void)
 {
   waiton_ptid = pid_to_ptid (-1);
   infwait_state = infwait_normal_state;
 }
 
-void
-error_is_running (void)
-{
-  error (_("Cannot execute this command while "
-          "the selected thread is running."));
-}
-
-void
-ensure_not_running (void)
-{
-  if (is_running (inferior_ptid))
-    error_is_running ();
-}
-
 static int
 stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id)
 {
@@ -3048,20 +3080,20 @@ static int
 handle_syscall_event (struct execution_control_state *ecs)
 {
   struct regcache *regcache;
-  struct gdbarch *gdbarch;
   int syscall_number;
 
   if (!ptid_equal (ecs->ptid, inferior_ptid))
     context_switch (ecs->ptid);
 
   regcache = get_thread_regcache (ecs->ptid);
-  gdbarch = get_regcache_arch (regcache);
   syscall_number = ecs->ws.value.syscall_number;
   stop_pc = regcache_read_pc (regcache);
 
   if (catch_syscall_enabled () > 0
       && catching_syscall_number (syscall_number) > 0)
     {
+      enum bpstat_signal_value sval;
+
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: syscall number = '%d'\n",
                             syscall_number);
@@ -3069,8 +3101,10 @@ handle_syscall_event (struct execution_control_state *ecs)
       ecs->event_thread->control.stop_bpstat
        = bpstat_stop_status (get_regcache_aspace (regcache),
                              stop_pc, ecs->ptid, &ecs->ws);
-      ecs->random_signal
-       = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+
+      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                    GDB_SIGNAL_TRAP);
+      ecs->random_signal = sval == BPSTAT_SIGNAL_NO;
 
       if (!ecs->random_signal)
        {
@@ -3086,17 +3120,6 @@ handle_syscall_event (struct execution_control_state *ecs)
   return 1;
 }
 
-/* Clear the supplied execution_control_state's stop_func_* fields.  */
-
-static void
-clear_stop_func (struct execution_control_state *ecs)
-{
-  ecs->stop_func_filled_in = 0;
-  ecs->stop_func_start = 0;
-  ecs->stop_func_end = 0;
-  ecs->stop_func_name = NULL;
-}
-
 /* Lazily fill in the execution_control_state's stop_func_* fields.  */
 
 static void
@@ -3194,13 +3217,16 @@ handle_inferior_event (struct execution_control_state *ecs)
     }
 
   if (ecs->ws.kind != TARGET_WAITKIND_EXITED
-      && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
-      && !ptid_equal (ecs->ptid, minus_one_ptid))
+      && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED)
     {
       ecs->event_thread = find_thread_ptid (ecs->ptid);
       /* If it's a new thread, add it to the thread database.  */
       if (ecs->event_thread == NULL)
        ecs->event_thread = add_thread (ecs->ptid);
+
+      /* Disable range stepping.  If the next step request could use a
+        range, this will be end up re-enabled then.  */
+      ecs->event_thread->control.may_range_step = 0;
     }
 
   /* Dependent on valid ECS->EVENT_THREAD.  */
@@ -3303,6 +3329,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       if (stop_soon == NO_STOP_QUIETLY)
        {
          struct regcache *regcache;
+         enum bpstat_signal_value sval;
 
          if (!ptid_equal (ecs->ptid, inferior_ptid))
            context_switch (ecs->ptid);
@@ -3313,8 +3340,11 @@ handle_inferior_event (struct execution_control_state *ecs)
          ecs->event_thread->control.stop_bpstat
            = bpstat_stop_status (get_regcache_aspace (regcache),
                                  stop_pc, ecs->ptid, &ecs->ws);
-         ecs->random_signal
-           = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+
+         sval
+           = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                     GDB_SIGNAL_TRAP);
+         ecs->random_signal = sval == BPSTAT_SIGNAL_NO;
 
          if (!ecs->random_signal)
            {
@@ -3363,60 +3393,81 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_SPURIOUS:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SPURIOUS\n");
-      if (!ptid_equal (ecs->ptid, inferior_ptid)
-         && !ptid_equal (ecs->ptid, minus_one_ptid))
+      if (!ptid_equal (ecs->ptid, inferior_ptid))
        context_switch (ecs->ptid);
       resume (0, GDB_SIGNAL_0);
       prepare_to_wait (ecs);
       return;
 
     case TARGET_WAITKIND_EXITED:
+    case TARGET_WAITKIND_SIGNALLED:
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\n");
+       {
+         if (ecs->ws.kind == TARGET_WAITKIND_EXITED)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: TARGET_WAITKIND_EXITED\n");
+         else
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: TARGET_WAITKIND_SIGNALLED\n");
+       }
+
       inferior_ptid = ecs->ptid;
       set_current_inferior (find_inferior_pid (ptid_get_pid (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.  */
-      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.  */
-      set_internalvar_integer (lookup_internalvar ("_exitcode"),
-                              (LONGEST) ecs->ws.value.integer);
+      /* Clearing any previous state of convenience variables.  */
+      clear_exit_convenience_vars ();
 
-      /* Also record this in the inferior itself.  */
-      current_inferior ()->has_exit_code = 1;
-      current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer;
+      if (ecs->ws.kind == TARGET_WAITKIND_EXITED)
+       {
+         /* Record the exit code in the convenience variable $_exitcode, so
+            that the user can inspect this again later.  */
+         set_internalvar_integer (lookup_internalvar ("_exitcode"),
+                                  (LONGEST) ecs->ws.value.integer);
 
-      gdb_flush (gdb_stdout);
-      target_mourn_inferior ();
-      singlestep_breakpoints_inserted_p = 0;
-      cancel_single_step_breakpoints ();
-      stop_print_frame = 0;
-      stop_stepping (ecs);
-      return;
+         /* Also record this in the inferior itself.  */
+         current_inferior ()->has_exit_code = 1;
+         current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer;
 
-    case TARGET_WAITKIND_SIGNALLED:
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n");
-      inferior_ptid = ecs->ptid;
-      set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid)));
-      set_current_program_space (current_inferior ()->pspace);
-      handle_vfork_child_exec_or_exit (0);
-      stop_print_frame = 0;
-      target_terminal_ours (); /* Must do this before mourn anyway.  */
+         print_exited_reason (ecs->ws.value.integer);
+       }
+      else
+       {
+         struct regcache *regcache = get_thread_regcache (ecs->ptid);
+         struct gdbarch *gdbarch = get_regcache_arch (regcache);
 
-      /* Note: By definition of TARGET_WAITKIND_SIGNALLED, we shouldn't
-         reach here unless the inferior is dead.  However, for years
-         target_kill() was called here, which hints that fatal signals aren't
-         really fatal on some systems.  If that's true, then some changes
-         may be needed.  */
-      target_mourn_inferior ();
+         if (gdbarch_gdb_signal_to_target_p (gdbarch))
+           {
+             /* Set the value of the internal variable $_exitsignal,
+                which holds the signal uncaught by the inferior.  */
+             set_internalvar_integer (lookup_internalvar ("_exitsignal"),
+                                      gdbarch_gdb_signal_to_target (gdbarch,
+                                                         ecs->ws.value.sig));
+           }
+         else
+           {
+             /* We don't have access to the target's method used for
+                converting between signal numbers (GDB's internal
+                representation <-> target's representation).
+                Therefore, we cannot do a good job at displaying this
+                information to the user.  It's better to just warn
+                her about it (if infrun debugging is enabled), and
+                give up.  */
+             if (debug_infrun)
+               fprintf_filtered (gdb_stdlog, _("\
+Cannot fill $_exitsignal with the correct signal number.\n"));
+           }
 
-      print_signal_exited_reason (ecs->ws.value.sig);
+         print_signal_exited_reason (ecs->ws.value.sig);
+       }
+
+      gdb_flush (gdb_stdout);
+      target_mourn_inferior ();
       singlestep_breakpoints_inserted_p = 0;
       cancel_single_step_breakpoints ();
+      stop_print_frame = 0;
       stop_stepping (ecs);
       return;
 
@@ -3425,7 +3476,12 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_FORKED:
     case TARGET_WAITKIND_VFORKED:
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
+       {
+         if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
+           fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
+         else
+           fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_VFORKED\n");
+       }
 
       /* Check whether the inferior is displaced stepping.  */
       {
@@ -3498,11 +3554,9 @@ handle_inferior_event (struct execution_control_state *ecs)
         vfork follow are detached.  */
       if (ecs->ws.kind != TARGET_WAITKIND_VFORKED)
        {
-         int child_pid = ptid_get_pid (ecs->ws.value.related_pid);
-
          /* This won't actually modify the breakpoint list, but will
             physically remove the breakpoints from the child.  */
-         detach_breakpoints (child_pid);
+         detach_breakpoints (ecs->ws.value.related_pid);
        }
 
       if (singlestep_breakpoints_inserted_p)
@@ -3618,7 +3672,9 @@ handle_inferior_event (struct execution_control_state *ecs)
        = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
                              stop_pc, ecs->ptid, &ecs->ws);
       ecs->random_signal
-       = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+       = (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                  GDB_SIGNAL_TRAP)
+          == BPSTAT_SIGNAL_NO);
 
       /* Note that this may be referenced from inside
         bpstat_stop_status above, through inferior_has_execd.  */
@@ -3669,6 +3725,15 @@ handle_inferior_event (struct execution_control_state *ecs)
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_NO_HISTORY\n");
       /* Reverse execution: target ran out of history info.  */
+
+      /* Pull the single step breakpoints out of the target.  */
+      if (singlestep_breakpoints_inserted_p)
+       {
+         if (!ptid_equal (ecs->ptid, inferior_ptid))
+           context_switch (ecs->ptid);
+         remove_single_step_breakpoints ();
+         singlestep_breakpoints_inserted_p = 0;
+       }
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
       print_no_history_reason ();
       stop_stepping (ecs);
@@ -3745,12 +3810,11 @@ handle_inferior_event (struct execution_control_state *ecs)
          remove_single_step_breakpoints ();
          singlestep_breakpoints_inserted_p = 0;
 
-         ecs->random_signal = 0;
          ecs->event_thread->control.trap_expected = 0;
 
          context_switch (saved_singlestep_ptid);
          if (deprecated_context_hook)
-           deprecated_context_hook (pid_to_thread_id (ecs->ptid));
+           deprecated_context_hook (pid_to_thread_id (saved_singlestep_ptid));
 
          resume (1, GDB_SIGNAL_0);
          prepare_to_wait (ecs);
@@ -3810,7 +3874,6 @@ handle_inferior_event (struct execution_control_state *ecs)
          not see this breakpoint hit when stepping onto breakpoints.  */
       if (regular_breakpoint_inserted_here_p (aspace, stop_pc))
        {
-         ecs->random_signal = 0;
          if (!breakpoint_thread_match (aspace, stop_pc, ecs->ptid))
            thread_hop_needed = 1;
        }
@@ -3824,7 +3887,6 @@ handle_inferior_event (struct execution_control_state *ecs)
                                "trap for %s\n",
                                target_pid_to_str (ecs->ptid));
 
-         ecs->random_signal = 0;
          /* The call to in_thread_list is necessary because PTIDs sometimes
             change when we go from single-threaded to multi-threaded.  If
             the singlestep_ptid is still in the list, assume that it is
@@ -3938,13 +4000,7 @@ handle_inferior_event (struct execution_control_state *ecs)
              return;
            }
        }
-      else if (singlestep_breakpoints_inserted_p)
-       {
-         ecs->random_signal = 0;
-       }
     }
-  else
-    ecs->random_signal = 1;
 
   /* See if something interesting happened to the non-current thread.  If
      so, then switch to that thread.  */
@@ -4022,12 +4078,10 @@ handle_inferior_event (struct execution_control_state *ecs)
       return;
     }
 
-  clear_stop_func (ecs);
   ecs->event_thread->stepping_over_breakpoint = 0;
   bpstat_clear (&ecs->event_thread->control.stop_bpstat);
   ecs->event_thread->control.stop_step = 0;
   stop_print_frame = 1;
-  ecs->random_signal = 0;
   stopped_by_random_signal = 0;
 
   /* Hide inlined functions starting here, unless we just performed stepi or
@@ -4114,128 +4168,124 @@ handle_inferior_event (struct execution_control_state *ecs)
      will be made according to the signal handling tables.  */
 
   if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-      || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
-      || stop_soon == STOP_QUIETLY_REMOTE)
+      && stop_after_trap)
     {
-      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-         && stop_after_trap)
-       {
-          if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
-         stop_print_frame = 0;
-         stop_stepping (ecs);
-         return;
-       }
-
-      /* This is originated from start_remote(), start_inferior() and
-         shared libraries hook functions.  */
-      if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
-       {
-          if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
-         stop_stepping (ecs);
-         return;
-       }
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
+      stop_print_frame = 0;
+      stop_stepping (ecs);
+      return;
+    }
 
-      /* This originates from attach_command().  We need to overwrite
-        the stop_signal here, because some kernels don't ignore a
-        SIGSTOP in a subsequent ptrace(PTRACE_CONT,SIGSTOP) call.
-        See more comments in inferior.h.  On the other hand, if we
-        get a non-SIGSTOP, report it to the user - assume the backend
-        will handle the SIGSTOP if it should show up later.
-
-        Also consider that the attach is complete when we see a
-        SIGTRAP.  Some systems (e.g. Windows), and stubs supporting
-        target extended-remote report it instead of a SIGSTOP
-        (e.g. gdbserver).  We already rely on SIGTRAP being our
-        signal, so this is no exception.
-
-        Also consider that the attach is complete when we see a
-        GDB_SIGNAL_0.  In non-stop mode, GDB will explicitly tell
-        the target to stop all threads of the inferior, in case the
-        low level attach operation doesn't stop them implicitly.  If
-        they weren't stopped implicitly, then the stub will report a
-        GDB_SIGNAL_0, meaning: stopped for no particular reason
-        other than GDB's request.  */
-      if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
-         && (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_STOP
-             || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-             || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_0))
-       {
-         stop_stepping (ecs);
-         ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
-         return;
-       }
+  /* This is originated from start_remote(), start_inferior() and
+     shared libraries hook functions.  */
+  if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
+      stop_stepping (ecs);
+      return;
+    }
 
-      /* See if there is a breakpoint/watchpoint/catchpoint/etc. that
-        handles this event.  */
-      ecs->event_thread->control.stop_bpstat
-       = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
-                             stop_pc, ecs->ptid, &ecs->ws);
+  /* This originates from attach_command().  We need to overwrite
+     the stop_signal here, because some kernels don't ignore a
+     SIGSTOP in a subsequent ptrace(PTRACE_CONT,SIGSTOP) call.
+     See more comments in inferior.h.  On the other hand, if we
+     get a non-SIGSTOP, report it to the user - assume the backend
+     will handle the SIGSTOP if it should show up later.
+
+     Also consider that the attach is complete when we see a
+     SIGTRAP.  Some systems (e.g. Windows), and stubs supporting
+     target extended-remote report it instead of a SIGSTOP
+     (e.g. gdbserver).  We already rely on SIGTRAP being our
+     signal, so this is no exception.
+
+     Also consider that the attach is complete when we see a
+     GDB_SIGNAL_0.  In non-stop mode, GDB will explicitly tell
+     the target to stop all threads of the inferior, in case the
+     low level attach operation doesn't stop them implicitly.  If
+     they weren't stopped implicitly, then the stub will report a
+     GDB_SIGNAL_0, meaning: stopped for no particular reason
+     other than GDB's request.  */
+  if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
+      && (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_STOP
+         || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
+         || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_0))
+    {
+      stop_stepping (ecs);
+      ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+      return;
+    }
 
-      /* Following in case break condition called a
-        function.  */
-      stop_print_frame = 1;
-
-      /* This is where we handle "moribund" watchpoints.  Unlike
-        software breakpoints traps, hardware watchpoint traps are
-        always distinguishable from random traps.  If no high-level
-        watchpoint is associated with the reported stop data address
-        anymore, then the bpstat does not explain the signal ---
-        simply make sure to ignore it if `stopped_by_watchpoint' is
-        set.  */
-
-      if (debug_infrun
-         && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-         && !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
-         && stopped_by_watchpoint)
-       fprintf_unfiltered (gdb_stdlog,
-                           "infrun: no user watchpoint explains "
-                           "watchpoint SIGTRAP, ignoring\n");
+  /* See if there is a breakpoint/watchpoint/catchpoint/etc. that
+     handles this event.  */
+  ecs->event_thread->control.stop_bpstat
+    = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
+                         stop_pc, ecs->ptid, &ecs->ws);
 
-      /* NOTE: cagney/2003-03-29: These two checks for a random signal
-         at one stage in the past included checks for an inferior
-         function call's call dummy's return breakpoint.  The original
-         comment, that went with the test, read:
+  /* Following in case break condition called a
+     function.  */
+  stop_print_frame = 1;
 
-         ``End of a stack dummy.  Some systems (e.g. Sony news) give
-         another signal besides SIGTRAP, so check here as well as
-         above.''
+  /* This is where we handle "moribund" watchpoints.  Unlike
+     software breakpoints traps, hardware watchpoint traps are
+     always distinguishable from random traps.  If no high-level
+     watchpoint is associated with the reported stop data address
+     anymore, then the bpstat does not explain the signal ---
+     simply make sure to ignore it if `stopped_by_watchpoint' is
+     set.  */
+
+  if (debug_infrun
+      && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
+      && (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                 GDB_SIGNAL_TRAP)
+         == BPSTAT_SIGNAL_NO)
+      && stopped_by_watchpoint)
+    fprintf_unfiltered (gdb_stdlog,
+                       "infrun: no user watchpoint explains "
+                       "watchpoint SIGTRAP, ignoring\n");
 
-         If someone ever tries to get call dummys on a
-         non-executable stack to work (where the target would stop
-         with something like a SIGSEGV), then those tests might need
-         to be re-instated.  Given, however, that the tests were only
-         enabled when momentary breakpoints were not being used, I
-         suspect that it won't be the case.
+  /* NOTE: cagney/2003-03-29: These two checks for a random signal
+     at one stage in the past included checks for an inferior
+     function call's call dummy's return breakpoint.  The original
+     comment, that went with the test, read:
 
-         NOTE: kettenis/2004-02-05: Indeed such checks don't seem to
-         be necessary for call dummies on a non-executable stack on
-         SPARC.  */
+     ``End of a stack dummy.  Some systems (e.g. Sony news) give
+     another signal besides SIGTRAP, so check here as well as
+     above.''
 
-      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
-       ecs->random_signal
-         = !(bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
-             || stopped_by_watchpoint
-             || ecs->event_thread->control.trap_expected
-             || (ecs->event_thread->control.step_range_end
-                 && (ecs->event_thread->control.step_resume_breakpoint
-                     == NULL)));
-      else
-       {
-         ecs->random_signal = !bpstat_explains_signal
-                                    (ecs->event_thread->control.stop_bpstat);
-         if (!ecs->random_signal)
-           ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
-       }
-    }
+     If someone ever tries to get call dummys on a
+     non-executable stack to work (where the target would stop
+     with something like a SIGSEGV), then those tests might need
+     to be re-instated.  Given, however, that the tests were only
+     enabled when momentary breakpoints were not being used, I
+     suspect that it won't be the case.
 
-  /* When we reach this point, we've pretty much decided
-     that the reason for stopping must've been a random
-     (unexpected) signal.  */
+     NOTE: kettenis/2004-02-05: Indeed such checks don't seem to
+     be necessary for call dummies on a non-executable stack on
+     SPARC.  */
 
+  if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
+    ecs->random_signal
+      = !((bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                  GDB_SIGNAL_TRAP)
+          != BPSTAT_SIGNAL_NO)
+         || stopped_by_watchpoint
+         || ecs->event_thread->control.trap_expected
+         || (ecs->event_thread->control.step_range_end
+             && (ecs->event_thread->control.step_resume_breakpoint
+                 == NULL)));
   else
-    ecs->random_signal = 1;
+    {
+      enum bpstat_signal_value sval;
+
+      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                    ecs->event_thread->suspend.stop_signal);
+      ecs->random_signal = (sval == BPSTAT_SIGNAL_NO);
+
+      if (sval == BPSTAT_SIGNAL_HIDE)
+       ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
+    }
 
 process_event_stop_test:
 
@@ -4252,10 +4302,11 @@ process_event_stop_test:
       /* Signal not for debugging purposes.  */
       int printed = 0;
       struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
+      enum gdb_signal stop_signal = ecs->event_thread->suspend.stop_signal;
 
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n",
-                            ecs->event_thread->suspend.stop_signal);
+        fprintf_unfiltered (gdb_stdlog, "infrun: random signal (%s)\n",
+                            gdb_signal_to_symbol_string (stop_signal));
 
       stopped_by_random_signal = 1;
 
@@ -4315,8 +4366,7 @@ process_event_stop_test:
 
       if (ecs->event_thread->control.step_range_end != 0
          && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0
-         && (ecs->event_thread->control.step_range_start <= stop_pc
-             && stop_pc < ecs->event_thread->control.step_range_end)
+         && pc_in_thread_step_range (stop_pc, ecs->event_thread)
          && frame_id_eq (get_stack_frame_id (frame),
                          ecs->event_thread->control.step_stack_frame_id)
          && ecs->event_thread->control.step_resume_breakpoint == NULL)
@@ -4646,6 +4696,17 @@ process_event_stop_test:
        }
     }
 
+  if (ecs->random_signal)
+    {
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog,
+                            "infrun: random signal, keep going\n");
+
+      /* Signal not stepping related.  */
+      keep_going (ecs);
+      return;
+    }
+
   if (ecs->event_thread->control.step_resume_breakpoint)
     {
       if (debug_infrun)
@@ -4685,8 +4746,7 @@ process_event_stop_test:
      through a function epilogue and therefore must detect when
      the current-frame changes in the middle of a line.  */
 
-  if (stop_pc >= ecs->event_thread->control.step_range_start
-      && stop_pc < ecs->event_thread->control.step_range_end
+  if (pc_in_thread_step_range (stop_pc, ecs->event_thread)
       && (execution_direction != EXEC_REVERSE
          || frame_id_eq (get_frame_id (frame),
                          ecs->event_thread->control.step_frame_id)))
@@ -4697,6 +4757,11 @@ process_event_stop_test:
           paddress (gdbarch, ecs->event_thread->control.step_range_start),
           paddress (gdbarch, ecs->event_thread->control.step_range_end));
 
+      /* Tentatively re-enable range stepping; `resume' disables it if
+        necessary (e.g., if we're stepping over a breakpoint or we
+        have software watchpoints).  */
+      ecs->event_thread->control.may_range_step = 1;
+
       /* When stepping backward, stop at beginning of line range
         (unless it's the function entry point, in which case
         keep going back to the call point).  */
@@ -4896,14 +4961,22 @@ process_event_stop_test:
 
          if (execution_direction == EXEC_REVERSE)
            {
-             struct symtab_and_line sr_sal;
-
-             /* Normal function call return (static or dynamic).  */
-             init_sal (&sr_sal);
-             sr_sal.pc = ecs->stop_func_start;
-             sr_sal.pspace = get_frame_program_space (frame);
-             insert_step_resume_breakpoint_at_sal (gdbarch,
-                                                   sr_sal, null_frame_id);
+             /* If we're already at the start of the function, we've either
+                just stepped backward into a single instruction function,
+                or stepped back out of a signal handler to the first instruction
+                of the function.  Just keep going, which will single-step back
+                to the caller.  */
+             if (ecs->stop_func_start != stop_pc && ecs->stop_func_start != 0)
+               {
+                 struct symtab_and_line sr_sal;
+
+                 /* Normal function call return (static or dynamic).  */
+                 init_sal (&sr_sal);
+                 sr_sal.pc = ecs->stop_func_start;
+                 sr_sal.pspace = get_frame_program_space (frame);
+                 insert_step_resume_breakpoint_at_sal (gdbarch,
+                                                       sr_sal, null_frame_id);
+               }
            }
          else
            insert_step_resume_breakpoint_at_caller (frame);
@@ -4949,7 +5022,8 @@ process_event_stop_test:
 
        tmp_sal = find_pc_line (ecs->stop_func_start, 0);
        if (tmp_sal.line != 0
-           && !function_pc_is_marked_for_skip (ecs->stop_func_start))
+           && !function_name_is_marked_for_skip (ecs->stop_func_name,
+                                                 &tmp_sal))
          {
            if (execution_direction == EXEC_REVERSE)
              handle_step_into_function_backward (gdbarch, ecs);
@@ -4973,15 +5047,23 @@ process_event_stop_test:
 
       if (execution_direction == EXEC_REVERSE)
        {
-         /* Set a breakpoint at callee's start address.
-            From there we can step once and be back in the caller.  */
-         struct symtab_and_line sr_sal;
+         /* If we're already at the start of the function, we've either just
+            stepped backward into a single instruction function without line
+            number info, or stepped back out of a signal handler to the first
+            instruction of the function without line number info.  Just keep
+            going, which will single-step back to the caller.  */
+         if (ecs->stop_func_start != stop_pc)
+           {
+             /* 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);
-         insert_step_resume_breakpoint_at_sal (gdbarch,
-                                               sr_sal, null_frame_id);
+             init_sal (&sr_sal);
+             sr_sal.pc = ecs->stop_func_start;
+             sr_sal.pspace = get_frame_program_space (frame);
+             insert_step_resume_breakpoint_at_sal (gdbarch,
+                                                   sr_sal, null_frame_id);
+           }
        }
       else
        /* Set a breakpoint at callee's return address (the address
@@ -5196,6 +5278,7 @@ process_event_stop_test:
 
   ecs->event_thread->control.step_range_start = stop_pc_sal.pc;
   ecs->event_thread->control.step_range_end = stop_pc_sal.end;
+  ecs->event_thread->control.may_range_step = 1;
   set_step_info (frame, stop_pc_sal);
 
   if (debug_infrun)
@@ -5618,9 +5701,9 @@ stop_stepping (struct execution_control_state *ecs)
   ecs->wait_some_more = 0;
 }
 
-/* This function handles various cases where we need to continue
-   waiting for the inferior.  */
-/* (Used to be the keep_going: label in the old wait_for_inferior).  */
+/* Called when we should continue running the inferior, because the
+   current event doesn't cause a user visible stop.  This does the
+   resuming part; waiting for the next event is done elsewhere.  */
 
 static void
 keep_going (struct execution_control_state *ecs)
@@ -5633,16 +5716,13 @@ keep_going (struct execution_control_state *ecs)
   ecs->event_thread->prev_pc
     = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
-  /* If we did not do break;, it means we should keep running the
-     inferior and not return to debugger.  */
-
   if (ecs->event_thread->control.trap_expected
       && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_TRAP)
     {
-      /* We took a signal (which we are supposed to pass through to
-        the inferior, else we'd not get here) and we haven't yet
-        gotten our trap.  Simply continue.  */
-
+      /* We haven't yet gotten our trap, and either: intercepted a
+        non-signal event (e.g., a fork); or took a signal which we
+        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);
@@ -5650,34 +5730,35 @@ keep_going (struct execution_control_state *ecs)
   else
     {
       /* Either the trap was not expected, but we are continuing
-         anyway (the user asked that this signal be passed to the
-         child)
-         -- or --
-         The signal was SIGTRAP, e.g. it was our signal, but we
-         decided we should resume from it.
+        anyway (if we got a signal, the user asked it be passed to
+        the child)
+        -- or --
+        We got our expected trap, but decided we should resume from
+        it.
 
-         We're going to run this baby now!  
+        We're going to run this baby now!
 
         Note that insert_breakpoints won't try to re-insert
         already inserted breakpoints.  Therefore, we don't
         care if breakpoints were already inserted, or not.  */
-      
+
       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
-              simple, we remove them all.  */
-           remove_breakpoints ();
+           {
+             /* Since we can't do a displaced step, we have to remove
+                the breakpoint while we step it.  To keep things
+                simple, we remove them all.  */
+             remove_breakpoints ();
+           }
        }
       else
        {
          volatile struct gdb_exception e;
 
-         /* Stop stepping when inserting breakpoints
-            has failed.  */
+         /* Stop stepping if inserting breakpoints fails.  */
          TRY_CATCH (e, RETURN_MASK_ERROR)
            {
              insert_breakpoints ();
@@ -5693,18 +5774,16 @@ keep_going (struct execution_control_state *ecs)
       ecs->event_thread->control.trap_expected
        = ecs->event_thread->stepping_over_breakpoint;
 
-      /* Do not deliver SIGNAL_TRAP (except when the user explicitly
-         specifies that such a signal should be delivered to the
-         target program).
-
-         Typically, this would occure when a user is debugging a
-         target monitor on a simulator: the target monitor sets a
-         breakpoint; the simulator encounters this break-point and
-         halts the simulation handing control to GDB; GDB, noteing
-         that the break-point isn't valid, returns control back to the
-         simulator; the simulator then delivers the hardware
-         equivalent of a SIGNAL_TRAP to the program being debugged.  */
-
+      /* Do not deliver GDB_SIGNAL_TRAP (except when the user
+        explicitly specifies that such a signal should be delivered
+        to the target program).  Typically, that would occur when a
+        user is debugging a target monitor on a simulator: the target
+        monitor sets a breakpoint; the simulator encounters this
+        breakpoint and halts the simulation handing control to GDB;
+        GDB, noting that the stop address doesn't map to any known
+        breakpoint, returns control back to the simulator; the
+        simulator then delivers the hardware equivalent of a
+        GDB_SIGNAL_TRAP to the program being debugged.  */
       if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
          && !signal_program[ecs->event_thread->suspend.stop_signal])
        ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
@@ -6042,7 +6121,7 @@ normal_stop (void)
             LOCATION: Print only location
             SRC_AND_LOC: Print location and source line.  */
          if (do_frame_printing)
-           print_stack_frame (get_selected_frame (NULL), 0, source_flag);
+           print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
 
          /* Display the auto-display expressions.  */
          do_displays ();
@@ -6169,7 +6248,8 @@ signal_cache_update (int signo)
 
   signal_pass[signo] = (signal_stop[signo] == 0
                        && signal_print[signo] == 0
-                       && signal_program[signo] == 1);
+                       && signal_program[signo] == 1
+                       && signal_catch[signo] == 0);
 }
 
 int
@@ -6202,6 +6282,20 @@ signal_pass_update (int signo, int state)
   return ret;
 }
 
+/* Update the global 'signal_catch' from INFO and notify the
+   target.  */
+
+void
+signal_catch_update (const unsigned int *info)
+{
+  int i;
+
+  for (i = 0; i < GDB_SIGNAL_LAST; ++i)
+    signal_catch[i] = info[i] > 0;
+  signal_cache_update (-1);
+  target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
+}
+
 static void
 sig_print_header (void)
 {
@@ -6409,6 +6503,36 @@ Are you sure you want to change it? "),
   do_cleanups (old_chain);
 }
 
+/* Complete the "handle" command.  */
+
+static VEC (char_ptr) *
+handle_completer (struct cmd_list_element *ignore,
+                 const char *text, const char *word)
+{
+  VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
+  static const char * const keywords[] =
+    {
+      "all",
+      "stop",
+      "ignore",
+      "print",
+      "pass",
+      "nostop",
+      "noignore",
+      "noprint",
+      "nopass",
+      NULL,
+    };
+
+  vec_signals = signal_completer (ignore, text, word);
+  vec_keywords = complete_on_enum (keywords, word, word);
+
+  return_val = VEC_merge (char_ptr, vec_signals, vec_keywords);
+  VEC_free (char_ptr, vec_signals);
+  VEC_free (char_ptr, vec_keywords);
+  return return_val;
+}
+
 static void
 xdb_handle_command (char *args, int from_tty)
 {
@@ -6656,7 +6780,9 @@ save_infcall_suspend_state (void)
 {
   struct infcall_suspend_state *inf_state;
   struct thread_info *tp = inferior_thread ();
+#if 0
   struct inferior *inf = current_inferior ();
+#endif
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   gdb_byte *siginfo_data = NULL;
@@ -6711,7 +6837,9 @@ void
 restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
   struct thread_info *tp = inferior_thread ();
+#if 0
   struct inferior *inf = current_inferior ();
+#endif
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
 
@@ -6725,11 +6853,10 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
   if (inf_state->siginfo_gdbarch == gdbarch)
     {
       struct type *type = gdbarch_get_siginfo_type (gdbarch);
-      size_t len = TYPE_LENGTH (type);
 
       /* Errors ignored.  */
       target_write (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
-                   inf_state->siginfo_data, 0, len);
+                   inf_state->siginfo_data, 0, TYPE_LENGTH (type));
     }
 
   /* The inferior can be gone if the user types "print exit(0)"
@@ -6952,6 +7079,15 @@ save_inferior_ptid (void)
   *saved_ptid_ptr = inferior_ptid;
   return make_cleanup (restore_inferior_ptid, saved_ptid_ptr);
 }
+
+/* See inferior.h.  */
+
+void
+clear_exit_convenience_vars (void)
+{
+  clear_internalvar (lookup_internalvar ("_exitsignal"));
+  clear_internalvar (lookup_internalvar ("_exitcode"));
+}
 \f
 
 /* User interface for reverse debugging:
@@ -7004,32 +7140,6 @@ show_exec_direction_func (struct ui_file *out, int from_tty,
   }
 }
 
-/* User interface for non-stop mode.  */
-
-int non_stop = 0;
-
-static void
-set_non_stop (char *args, int from_tty,
-             struct cmd_list_element *c)
-{
-  if (target_has_execution)
-    {
-      non_stop_1 = non_stop;
-      error (_("Cannot change this setting while the inferior is running."));
-    }
-
-  non_stop = non_stop_1;
-}
-
-static void
-show_non_stop (struct ui_file *file, int from_tty,
-              struct cmd_list_element *c, const char *value)
-{
-  fprintf_filtered (file,
-                   _("Controlling the inferior in non-stop mode is %s.\n"),
-                   value);
-}
-
 static void
 show_schedule_multiple (struct ui_file *file, int from_tty,
                        struct cmd_list_element *c, const char *value)
@@ -7052,27 +7162,39 @@ _initialize_infrun (void)
 {
   int i;
   int numsigs;
+  struct cmd_list_element *c;
 
   add_info ("signals", signals_info, _("\
 What debugger does when program gets various signals.\n\
 Specify a signal as argument to print info on that signal only."));
   add_info_alias ("handle", "signals", 0);
 
-  add_com ("handle", class_run, handle_command, _("\
-Specify how to handle a signal.\n\
+  c = add_com ("handle", class_run, handle_command, _("\
+Specify how to handle signals.\n\
+Usage: handle SIGNAL [ACTIONS]\n\
 Args are signals and actions to apply to those signals.\n\
+If no actions are specified, the current settings for the specified signals\n\
+will be displayed instead.\n\
+\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\
+\n\
 Recognized actions include \"stop\", \"nostop\", \"print\", \"noprint\",\n\
 \"pass\", \"nopass\", \"ignore\", or \"noignore\".\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."));
+Pass and Stop may be combined.\n\
+\n\
+Multiple signals may be specified.  Signal numbers and signal names\n\
+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, _("\
@@ -7103,13 +7225,13 @@ There is no `stop' command, but you can set a hook on `stop'.\n\
 This allows you to set a list of commands to be run each time execution\n\
 of the program stops."), &cmdlist);
 
-  add_setshow_zinteger_cmd ("infrun", class_maintenance, &debug_infrun, _("\
+  add_setshow_zuinteger_cmd ("infrun", class_maintenance, &debug_infrun, _("\
 Set inferior debugging."), _("\
 Show inferior debugging."), _("\
 When non-zero, inferior specific debugging is enabled."),
-                           NULL,
-                           show_debug_infrun,
-                           &setdebuglist, &showdebuglist);
+                            NULL,
+                            show_debug_infrun,
+                            &setdebuglist, &showdebuglist);
 
   add_setshow_boolean_cmd ("displaced", class_maintenance,
                           &debug_displaced, _("\
@@ -7146,6 +7268,8 @@ leave it stopped or free to run as needed."),
     xmalloc (sizeof (signal_print[0]) * numsigs);
   signal_program = (unsigned char *)
     xmalloc (sizeof (signal_program[0]) * numsigs);
+  signal_catch = (unsigned char *)
+    xmalloc (sizeof (signal_catch[0]) * numsigs);
   signal_pass = (unsigned char *)
     xmalloc (sizeof (signal_program[0]) * numsigs);
   for (i = 0; i < numsigs; i++)
@@ -7153,6 +7277,7 @@ leave it stopped or free to run as needed."),
       signal_stop[i] = 1;
       signal_print[i] = 1;
       signal_program[i] = 1;
+      signal_catch[i] = 0;
     }
 
   /* Signals caused by debugger's own actions
@@ -7201,7 +7326,7 @@ Show stopping for shared library events."), _("\
 If nonzero, gdb will give control to the user when the dynamic linker\n\
 notifies gdb of shared library events.  The most common event of interest\n\
 to the user would be loading/unloading of a new library."),
-                           NULL,
+                           set_stop_on_solib_events,
                            show_stop_on_solib_events,
                            &setlist, &showlist);
 
This page took 0.045402 seconds and 4 git commands to generate.