2011-05-20 Pedro Alves <pedro@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 8b1f82a7f84f9d549a45dfe3a6fd6995145dce28..8d6910df4a04fd134d4ba857730f73b5eabde380 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
    1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008, 2009, 2010 Free Software Foundation, Inc.
+   2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -45,6 +45,8 @@
 #include "language.h"
 #include "solib.h"
 #include "main.h"
+#include "dictionary.h"
+#include "block.h"
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
 #include "event-top.h"
@@ -83,10 +85,30 @@ static void xdb_handle_command (char *args, int from_tty);
 
 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);
 
+static void insert_step_resume_breakpoint_at_frame (struct frame_info *);
+
+static void insert_step_resume_breakpoint_at_caller (struct frame_info *);
+
+static void insert_step_resume_breakpoint_at_sal (struct gdbarch *,
+                                                 struct symtab_and_line ,
+                                                 struct frame_id);
+
+static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
+
 /* When set, stop the 'step' command if we enter a function which has
    no line number information.  The normal behavior is that we step
    over such function.  */
@@ -98,7 +120,7 @@ show_step_stop_if_no_debug (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Mode of the step operation is %s.\n"), value);
 }
 
-/* In asynchronous mode, but simulating synchronous execution. */
+/* In asynchronous mode, but simulating synchronous execution.  */
 
 int sync_execution = 0;
 
@@ -264,6 +286,11 @@ static unsigned char *signal_stop;
 static unsigned char *signal_print;
 static unsigned char *signal_program;
 
+/* Table of signals that the target may silently handle.
+   This is automatically determined from the flags above,
+   and simply cached here.  */
+static unsigned char *signal_pass;
+
 #define SET_SIGS(nsigs,sigs,flags) \
   do { \
     int signum = (nsigs); \
@@ -280,7 +307,7 @@ static unsigned char *signal_program;
        (flags)[signum] = 0; \
   } while (0)
 
-/* Value to pass to target_resume() to cause all threads to resume */
+/* Value to pass to target_resume() to cause all threads to resume */
 
 #define RESUME_ALL minus_one_ptid
 
@@ -345,8 +372,9 @@ static void
 show_follow_fork_mode_string (struct ui_file *file, int from_tty,
                              struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Debugger response to a program call of fork or vfork is \"%s\".\n"),
+  fprintf_filtered (file,
+                   _("Debugger response to a program "
+                     "call of fork or vfork is \"%s\".\n"),
                    value);
 }
 \f
@@ -367,6 +395,7 @@ follow_fork (void)
      parent thread structure's run control related fields, not just these.
      Initialized to avoid "may be used uninitialized" warnings from gcc.  */
   struct breakpoint *step_resume_breakpoint = NULL;
+  struct breakpoint *exception_resume_breakpoint = NULL;
   CORE_ADDR step_range_start = 0;
   CORE_ADDR step_range_end = 0;
   struct frame_id step_frame_id = { 0 };
@@ -414,11 +443,13 @@ follow_fork (void)
           preserve the stepping state in the fork child.  */
        if (follow_child && should_resume)
          {
-           step_resume_breakpoint
-             = clone_momentary_breakpoint (tp->step_resume_breakpoint);
-           step_range_start = tp->step_range_start;
-           step_range_end = tp->step_range_end;
-           step_frame_id = tp->step_frame_id;
+           step_resume_breakpoint = clone_momentary_breakpoint
+                                        (tp->control.step_resume_breakpoint);
+           step_range_start = tp->control.step_range_start;
+           step_range_end = tp->control.step_range_end;
+           step_frame_id = tp->control.step_frame_id;
+           exception_resume_breakpoint
+             = clone_momentary_breakpoint (tp->control.exception_resume_breakpoint);
 
            /* For now, delete the parent's sr breakpoint, otherwise,
               parent/child sr breakpoints are considered duplicates,
@@ -426,9 +457,10 @@ follow_fork (void)
               this when the breakpoints module becomes aware of
               inferiors and address spaces.  */
            delete_step_resume_breakpoint (tp);
-           tp->step_range_start = 0;
-           tp->step_range_end = 0;
-           tp->step_frame_id = null_frame_id;
+           tp->control.step_range_start = 0;
+           tp->control.step_range_end = 0;
+           tp->control.step_frame_id = null_frame_id;
+           delete_exception_resume_breakpoint (tp);
          }
 
        parent = inferior_ptid;
@@ -456,7 +488,7 @@ follow_fork (void)
               over from WAIT_PID" logic above.  */
            nullify_last_target_wait_ptid ();
 
-           /* If we followed the child, switch to it... */
+           /* If we followed the child, switch to it...  */
            if (follow_child)
              {
                switch_to_thread (child);
@@ -466,10 +498,13 @@ follow_fork (void)
                if (should_resume)
                  {
                    tp = inferior_thread ();
-                   tp->step_resume_breakpoint = step_resume_breakpoint;
-                   tp->step_range_start = step_range_start;
-                   tp->step_range_end = step_range_end;
-                   tp->step_frame_id = step_frame_id;
+                   tp->control.step_resume_breakpoint
+                     = step_resume_breakpoint;
+                   tp->control.step_range_start = step_range_start;
+                   tp->control.step_range_end = step_range_end;
+                   tp->control.step_frame_id = step_frame_id;
+                   tp->control.exception_resume_breakpoint
+                     = exception_resume_breakpoint;
                  }
                else
                  {
@@ -479,8 +514,8 @@ follow_fork (void)
                       forked.  In that case, the resume command
                       issued is most likely not applicable to the
                       child, so just warn, and refuse to resume.  */
-                   warning (_("\
-Not resuming: switched threads before following fork child.\n"));
+                   warning (_("Not resuming: switched threads "
+                              "before following fork child.\n"));
                  }
 
                /* Reset breakpoints in the child as appropriate.  */
@@ -520,8 +555,11 @@ follow_inferior_reset_breakpoints (void)
      "threads".  We must update the bp's notion of which thread
      it is for, or it'll be ignored when it triggers.  */
 
-  if (tp->step_resume_breakpoint)
-    breakpoint_re_set_thread (tp->step_resume_breakpoint);
+  if (tp->control.step_resume_breakpoint)
+    breakpoint_re_set_thread (tp->control.step_resume_breakpoint);
+
+  if (tp->control.exception_resume_breakpoint)
+    breakpoint_re_set_thread (tp->control.exception_resume_breakpoint);
 
   /* Reinsert all breakpoints in the child.  The user may have set
      breakpoints after catching the fork, in which case those
@@ -545,7 +583,7 @@ proceed_after_vfork_done (struct thread_info *thread,
       && is_running (thread->ptid)
       && !is_executing (thread->ptid)
       && !thread->stop_requested
-      && thread->stop_signal == TARGET_SIGNAL_0)
+      && thread->suspend.stop_signal == TARGET_SIGNAL_0)
     {
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog,
@@ -583,7 +621,7 @@ handle_vfork_child_exec_or_exit (int exec)
          struct program_space *pspace;
          struct address_space *aspace;
 
-         /* follow-fork child, detach-on-fork on */
+         /* follow-fork child, detach-on-fork on */
 
          old_chain = make_cleanup_restore_current_thread ();
 
@@ -614,11 +652,13 @@ handle_vfork_child_exec_or_exit (int exec)
 
              if (exec)
                fprintf_filtered (gdb_stdlog,
-                                 "Detaching vfork parent process %d after child exec.\n",
+                                 "Detaching vfork parent process "
+                                 "%d after child exec.\n",
                                  inf->vfork_parent->pid);
              else
                fprintf_filtered (gdb_stdlog,
-                                 "Detaching vfork parent process %d after child exit.\n",
+                                 "Detaching vfork parent process "
+                                 "%d after child exit.\n",
                                  inf->vfork_parent->pid);
            }
 
@@ -676,7 +716,7 @@ handle_vfork_child_exec_or_exit (int exec)
          inf->aspace = pspace->aspace;
 
          /* Put back inferior_ptid.  We'll continue mourning this
-            inferior. */
+            inferior.  */
          do_cleanups (old_chain);
 
          resume_parent = inf->vfork_parent->pid;
@@ -695,7 +735,8 @@ handle_vfork_child_exec_or_exit (int exec)
          struct cleanup *old_chain = make_cleanup_restore_current_thread ();
 
          if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog, "infrun: resuming vfork parent process %d\n",
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: resuming vfork parent process %d\n",
                                resume_parent);
 
          iterate_over_threads (proceed_after_vfork_done, &resume_parent);
@@ -724,7 +765,7 @@ show_follow_exec_mode_string (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Follow exec mode is \"%s\".\n"),  value);
 }
 
-/* EXECD_PATHNAME is assumed to be non-NULL. */
+/* EXECD_PATHNAME is assumed to be non-NULL.  */
 
 static void
 follow_exec (ptid_t pid, char *execd_pathname)
@@ -751,17 +792,18 @@ follow_exec (ptid_t pid, char *execd_pathname)
      And, we DON'T want to call delete_breakpoints() here, since
      that may write the bp's "shadow contents" (the instruction
      value that was overwritten witha TRAP instruction).  Since
-     we now have a new a.out, those shadow contents aren't valid. */
+     we now have a new a.out, those shadow contents aren't valid.  */
 
   mark_breakpoints_out ();
 
   update_breakpoints_after_exec ();
 
   /* If there was one, it's gone now.  We cannot truly step-to-next
-     statement through an exec(). */
-  th->step_resume_breakpoint = NULL;
-  th->step_range_start = 0;
-  th->step_range_end = 0;
+     statement through an exec().  */
+  th->control.step_resume_breakpoint = NULL;
+  th->control.exception_resume_breakpoint = NULL;
+  th->control.step_range_start = 0;
+  th->control.step_range_end = 0;
 
   /* The target reports the exec event to the main thread, even if
      some other thread does the exec, and even if the main thread was
@@ -771,13 +813,13 @@ follow_exec (ptid_t pid, char *execd_pathname)
      with scheduler-locking on in all-stop mode.  */
   th->stop_requested = 0;
 
-  /* What is this a.out's name? */
+  /* What is this a.out's name?  */
   printf_unfiltered (_("%s is executing new program: %s\n"),
                     target_pid_to_str (inferior_ptid),
                     execd_pathname);
 
   /* We've followed the inferior through an exec.  Therefore, the
-     inferior has essentially been killed & reborn. */
+     inferior has essentially been killed & reborn.  */
 
   gdb_flush (gdb_stdout);
 
@@ -822,11 +864,18 @@ follow_exec (ptid_t pid, char *execd_pathname)
 
   gdb_assert (current_program_space == inf->pspace);
 
-  /* That a.out is now the one to use. */
+  /* That a.out is now the one to use.  */
   exec_file_attach (execd_pathname, 0);
 
-  /* Load the main file's symbols.  */
-  symbol_file_add_main (execd_pathname, 0);
+  /* SYMFILE_DEFER_BP_RESET is used as the proper displacement for PIE
+     (Position Independent Executable) main symbol file will get applied by
+     solib_create_inferior_hook below.  breakpoint_re_set would fail to insert
+     the breakpoints with the zero displacement.  */
+
+  symbol_file_add (execd_pathname, SYMFILE_MAINLINE | SYMFILE_DEFER_BP_RESET,
+                  NULL, 0);
+
+  set_initial_language ();
 
 #ifdef SOLIB_CREATE_INFERIOR_HOOK
   SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
@@ -836,15 +885,17 @@ follow_exec (ptid_t pid, char *execd_pathname)
 
   jit_inferior_created_hook ();
 
+  breakpoint_re_set ();
+
   /* Reinsert all breakpoints.  (Those which were symbolic have
      been reset to the proper address in the new a.out, thanks
-     to symbol_file_command...) */
+     to symbol_file_command...) */
   insert_breakpoints ();
 
   /* The next resume of this inferior should bring it to the shlib
      startup breakpoints.  (If the user had also set bp's on
      "main" from the old (parent) process, then they'll auto-
-     matically get reset there in the new process.) */
+     matically get reset there in the new process.) */
 }
 
 /* Non-zero if we just simulating a single-step.  This is needed
@@ -867,7 +918,7 @@ static int stepping_past_singlestep_breakpoint;
    is finished, we need to switch to deferred_step_ptid, and step it.
 
    The use case is when one thread has hit a breakpoint, and then the user 
-   has switched to another thread and issued 'step'. We need to step over
+   has switched to another thread and issued 'step'.  We need to step over
    breakpoint in the thread which hit the breakpoint, but then continue
    stepping the thread user has selected.  */
 static ptid_t deferred_step_ptid;
@@ -1042,6 +1093,24 @@ add_displaced_stepping_state (int pid)
   return state;
 }
 
+/* If inferior is in displaced stepping, and ADDR equals to starting address
+   of copy area, return corresponding displaced_step_closure.  Otherwise,
+   return NULL.  */
+
+struct displaced_step_closure*
+get_displaced_step_closure_by_addr (CORE_ADDR addr)
+{
+  struct displaced_step_inferior_state *displaced
+    = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
+
+  /* If checking the mode of displaced instruction in copy area.  */
+  if (displaced && !ptid_equal (displaced->step_ptid, null_ptid)
+     && (displaced->step_copy == addr))
+    return displaced->step_closure;
+
+  return NULL;
+}
+
 /* Remove the displaced stepping state of process PID.  */
 
 static void
@@ -1103,14 +1172,14 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
                                 const char *value)
 {
   if (can_use_displaced_stepping == can_use_displaced_stepping_auto)
-    fprintf_filtered (file, _("\
-Debugger's willingness to use displaced stepping to step over \
-breakpoints is %s (currently %s).\n"),
+    fprintf_filtered (file,
+                     _("Debugger's willingness to use displaced stepping "
+                       "to step over breakpoints is %s (currently %s).\n"),
                      value, non_stop ? "on" : "off");
   else
-    fprintf_filtered (file, _("\
-Debugger's willingness to use displaced stepping to step over \
-breakpoints is %s.\n"), value);
+    fprintf_filtered (file,
+                     _("Debugger's willingness to use displaced stepping "
+                       "to step over breakpoints is %s.\n"), value);
 }
 
 /* Return non-zero if displaced stepping can/should be used to step
@@ -1287,7 +1356,8 @@ displaced_step_prepare (ptid_t ptid)
 }
 
 static void
-write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
+write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr,
+                  const gdb_byte *myaddr, int len)
 {
   struct cleanup *ptid_cleanup = save_inferior_ptid ();
 
@@ -1412,17 +1482,18 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
 
          /* The breakpoint we were sitting under has since been
             removed.  */
-         tp->trap_expected = 0;
+         tp->control.trap_expected = 0;
 
          /* Go back to what we were trying to do.  */
          step = currently_stepping (tp);
 
          if (debug_displaced)
-           fprintf_unfiltered (gdb_stdlog, "breakpoint is gone %s: step(%d)\n",
+           fprintf_unfiltered (gdb_stdlog,
+                               "breakpoint is gone %s: step(%d)\n",
                                target_pid_to_str (tp->ptid), step);
 
          target_resume (ptid, step, TARGET_SIGNAL_0);
-         tp->stop_signal = TARGET_SIGNAL_0;
+         tp->suspend.stop_signal = TARGET_SIGNAL_0;
 
          /* This request was discarded.  See if there's any other
             thread waiting for its turn.  */
@@ -1484,8 +1555,9 @@ static void
 show_scheduler_mode (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Mode for locking scheduler during execution is \"%s\".\n"),
+  fprintf_filtered (file,
+                   _("Mode for locking scheduler "
+                     "during execution is \"%s\".\n"),
                    value);
 }
 
@@ -1521,7 +1593,7 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       hw_step = 0;
       /* Do not pull these breakpoints until after a `wait' in
-        `wait_for_inferior' */
+        `wait_for_inferior' */
       singlestep_breakpoints_inserted_p = 1;
       singlestep_ptid = inferior_ptid;
       singlestep_pc = pc;
@@ -1550,11 +1622,32 @@ resume (int step, enum target_signal sig)
 
   QUIT;
 
+  if (current_inferior ()->waiting_for_vfork_done)
+    {
+      /* Don't try to single-step a vfork parent that is waiting for
+        the child to get out of the shared memory region (by exec'ing
+        or exiting).  This is particularly important on software
+        single-step archs, as the child process would trip on the
+        software single step breakpoint inserted for the parent
+        process.  Since the parent will not actually execute any
+        instruction until the child is out of the shared region (such
+        are vfork's semantics), it is safe to simply continue it.
+        Eventually, we'll see a TARGET_WAITKIND_VFORK_DONE event for
+        the parent, and tell it to `keep_going', which automatically
+        re-sets it stepping.  */
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: resume : clear step\n");
+      step = 0;
+    }
+
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
                         "infrun: resume (step=%d, signal=%d), "
-                       "trap_expected=%d\n",
-                       step, sig, tp->trap_expected);
+                       "trap_expected=%d, current thread [%s] at %s\n",
+                       step, sig, tp->control.trap_expected,
+                       target_pid_to_str (inferior_ptid),
+                       paddress (gdbarch, pc));
 
   /* Normally, by the time we reach `resume', the breakpoints are either
      removed or inserted, as appropriate.  The exception is if we're sitting
@@ -1577,11 +1670,16 @@ a command like `return' or `jump' to continue execution."));
      We can't use displaced stepping when we have a signal to deliver;
      the comments for displaced_step_prepare explain why.  The
      comments in the handle_inferior event for dealing with 'random
-     signals' explain what we do instead.  */
+     signals' explain what we do instead.
+
+     We can't use displaced stepping when we are waiting for vfork_done
+     event, displaced stepping breaks the vfork child similarly as single
+     step software breakpoint.  */
   if (use_displaced_stepping (gdbarch)
-      && (tp->trap_expected
+      && (tp->control.trap_expected
          || (step && gdbarch_software_single_step_p (gdbarch)))
-      && sig == TARGET_SIGNAL_0)
+      && sig == TARGET_SIGNAL_0
+      && !current_inferior ()->waiting_for_vfork_done)
     {
       struct displaced_step_inferior_state *displaced;
 
@@ -1607,6 +1705,51 @@ a command like `return' or `jump' to continue execution."));
   else if (step)
     step = maybe_software_singlestep (gdbarch, pc);
 
+  /* Currently, our software single-step implementation leads to different
+     results than hardware single-stepping in one situation: when stepping
+     into delivering a signal which has an associated signal handler,
+     hardware single-step will stop at the first instruction of the handler,
+     while software single-step will simply skip execution of the handler.
+
+     For now, this difference in behavior is accepted since there is no
+     easy way to actually implement single-stepping into a signal handler
+     without kernel support.
+
+     However, there is one scenario where this difference leads to follow-on
+     problems: if we're stepping off a breakpoint by removing all breakpoints
+     and then single-stepping.  In this case, the software single-step
+     behavior means that even if there is a *breakpoint* in the signal
+     handler, GDB still would not stop.
+
+     Fortunately, we can at least fix this particular issue.  We detect
+     here the case where we are about to deliver a signal while software
+     single-stepping with breakpoints removed.  In this situation, we
+     revert the decisions to remove all breakpoints and insert single-
+     step breakpoints, and instead we install a step-resume breakpoint
+     at the current address, deliver the signal without stepping, and
+     once we arrive back at the step-resume breakpoint, actually step
+     over the breakpoint we originally wanted to step over.  */
+  if (singlestep_breakpoints_inserted_p
+      && tp->control.trap_expected && sig != TARGET_SIGNAL_0)
+    {
+      /* If we have nested signals or a pending signal is delivered
+        immediately after a handler returns, might might already have
+        a step-resume breakpoint set on the earlier handler.  We cannot
+        set another step-resume breakpoint; just continue on until the
+        original breakpoint is hit.  */
+      if (tp->control.step_resume_breakpoint == NULL)
+       {
+         insert_step_resume_breakpoint_at_frame (get_current_frame ());
+         tp->step_after_step_resume_breakpoint = 1;
+       }
+
+      remove_single_step_breakpoints ();
+      singlestep_breakpoints_inserted_p = 0;
+
+      insert_breakpoints ();
+      tp->control.trap_expected = 0;
+    }
+
   if (should_resume)
     {
       ptid_t resume_ptid;
@@ -1647,7 +1790,7 @@ a command like `return' or `jump' to continue execution."));
          resume_ptid = inferior_ptid;
        }
       else if ((step || singlestep_breakpoints_inserted_p)
-              && tp->trap_expected)
+              && tp->control.trap_expected)
        {
          /* We're allowing a thread to run past a breakpoint it has
             hit, by single-stepping the thread with the breakpoint
@@ -1671,7 +1814,7 @@ a command like `return' or `jump' to continue execution."));
               || (scheduler_mode == schedlock_step
                   && (step || singlestep_breakpoints_inserted_p)))
        {
-         /* User-settable 'scheduler' mode requires solo thread resume. */
+         /* User-settable 'scheduler' mode requires solo thread resume.  */
          resume_ptid = inferior_ptid;
        }
 
@@ -1686,7 +1829,7 @@ a command like `return' or `jump' to continue execution."));
 
       if (debug_displaced
           && use_displaced_stepping (gdbarch)
-          && tp->trap_expected)
+          && tp->control.trap_expected)
         {
          struct regcache *resume_regcache = get_thread_regcache (resume_ptid);
          struct gdbarch *resume_gdbarch = get_regcache_arch (resume_regcache);
@@ -1704,7 +1847,19 @@ a command like `return' or `jump' to continue execution."));
 
       /* Avoid confusing the next resume, if the next stop/resume
         happens to apply to another thread.  */
-      tp->stop_signal = TARGET_SIGNAL_0;
+      tp->suspend.stop_signal = TARGET_SIGNAL_0;
+
+      /* Advise target which signals may be handled silently.  If we have
+        removed breakpoints because we are stepping over one (which can
+        happen only if we are not using displaced stepping), we need to
+        receive all signals to avoid accidentally skipping a breakpoint
+        during execution of a signal handler.  */
+      if ((step || singlestep_breakpoints_inserted_p)
+         && tp->control.trap_expected
+         && !use_displaced_stepping (gdbarch))
+       target_pass_signals (0, NULL);
+      else
+       target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass);
 
       target_resume (resume_ptid, step, sig);
     }
@@ -1725,20 +1880,20 @@ clear_proceed_status_thread (struct thread_info *tp)
                        "infrun: clear_proceed_status_thread (%s)\n",
                        target_pid_to_str (tp->ptid));
 
-  tp->trap_expected = 0;
-  tp->step_range_start = 0;
-  tp->step_range_end = 0;
-  tp->step_frame_id = null_frame_id;
-  tp->step_stack_frame_id = null_frame_id;
-  tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
+  tp->control.trap_expected = 0;
+  tp->control.step_range_start = 0;
+  tp->control.step_range_end = 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;
   tp->stop_requested = 0;
 
-  tp->stop_step = 0;
+  tp->control.stop_step = 0;
 
-  tp->proceed_to_finish = 0;
+  tp->control.proceed_to_finish = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
-  bpstat_clear (&tp->stop_bpstat);
+  bpstat_clear (&tp->control.stop_bpstat);
 }
 
 static int
@@ -1775,7 +1930,7 @@ clear_proceed_status (void)
        }
 
       inferior = current_inferior ();
-      inferior->stop_soon = NO_STOP_QUIETLY;
+      inferior->control.stop_soon = NO_STOP_QUIETLY;
     }
 
   stop_after_trap = 0;
@@ -1793,7 +1948,7 @@ clear_proceed_status (void)
    event.  If a step-over is required return TRUE and set the current thread
    to the old thread.  Otherwise return FALSE.
 
-   This should be suitable for any targets that support threads. */
+   This should be suitable for any targets that support threads.  */
 
 static int
 prepare_to_proceed (int step)
@@ -1848,9 +2003,15 @@ prepare_to_proceed (int step)
          /* Switch back to WAIT_PID thread.  */
          switch_to_thread (wait_ptid);
 
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: prepare_to_proceed (step=%d), "
+                               "switched to [%s]\n",
+                               step, target_pid_to_str (inferior_ptid));
+
          /* We return 1 to indicate that there is a breakpoint here,
             so we need to step over it before continuing to avoid
-            hitting it straight away. */
+            hitting it straight away.  */
          return 1;
        }
     }
@@ -1931,16 +2092,6 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
                        "infrun: proceed (addr=%s, signal=%d, step=%d)\n",
                        paddress (gdbarch, addr), siggnal, step);
 
-  /* We're handling a live event, so make sure we're doing live
-     debugging.  If we're looking at traceframes while the target is
-     running, we're going to need to get back to that mode after
-     handling the event.  */
-  if (non_stop)
-    {
-      make_cleanup_restore_current_traceframe ();
-      set_traceframe_number (-1);
-    }
-
   if (non_stop)
     /* In non-stop, each thread is handled individually.  The context
        must already be set to the right thread here.  */
@@ -1958,7 +2109,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
         prepare_to_proceed checks the current thread against the
         thread that reported the most recent event.  If a step-over
         is required it returns TRUE and sets the current thread to
-        the old thread. */
+        the old thread.  */
       if (prepare_to_proceed (step))
        oneproc = 1;
     }
@@ -1968,7 +2119,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
 
   if (oneproc)
     {
-      tp->trap_expected = 1;
+      tp->control.trap_expected = 1;
       /* If displaced stepping is enabled, we can step over the
         breakpoint without hitting it, so leave all breakpoints
         inserted.  Otherwise we need to disable all breakpoints, step
@@ -1981,7 +2132,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   /* We can insert breakpoints if we're not trying to step over one,
      or if we are stepping over one but we're using displaced stepping
      to do so.  */
-  if (! tp->trap_expected || use_displaced_stepping (gdbarch))
+  if (! tp->control.trap_expected || use_displaced_stepping (gdbarch))
     insert_breakpoints ();
 
   if (!non_stop)
@@ -2003,18 +2154,18 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
          last_thread = find_thread_ptid (last_ptid);
          if (last_thread)
            {
-             tp->stop_signal = last_thread->stop_signal;
-             last_thread->stop_signal = TARGET_SIGNAL_0;
+             tp->suspend.stop_signal = last_thread->suspend.stop_signal;
+             last_thread->suspend.stop_signal = TARGET_SIGNAL_0;
            }
        }
     }
 
   if (siggnal != TARGET_SIGNAL_DEFAULT)
-    tp->stop_signal = siggnal;
+    tp->suspend.stop_signal = siggnal;
   /* If this signal should not be seen by program,
      give it zero.  Used for debugging signals.  */
-  else if (!signal_program[tp->stop_signal])
-    tp->stop_signal = TARGET_SIGNAL_0;
+  else if (!signal_program[tp->suspend.stop_signal])
+    tp->suspend.stop_signal = TARGET_SIGNAL_0;
 
   annotate_starting ();
 
@@ -2054,15 +2205,15 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   init_infwait_state ();
 
   /* Resume inferior.  */
-  resume (oneproc || step || bpstat_should_step (), tp->stop_signal);
+  resume (oneproc || 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.  */
   /* Do this only if we are not using the event loop, or if the target
-     does not support asynchronous execution. */
+     does not support asynchronous execution.  */
   if (!target_can_async_p ())
     {
-      wait_for_inferior (0);
+      wait_for_inferior ();
       normal_stop ();
     }
 }
@@ -2077,23 +2228,23 @@ start_remote (int from_tty)
 
   init_wait_for_inferior ();
   inferior = current_inferior ();
-  inferior->stop_soon = STOP_QUIETLY_REMOTE;
+  inferior->control.stop_soon = STOP_QUIETLY_REMOTE;
 
-  /* Always go on waiting for the target, regardless of the mode. */
+  /* Always go on waiting for the target, regardless of the mode.  */
   /* FIXME: cagney/1999-09-23: At present it isn't possible to
      indicate to wait_for_inferior that a target should timeout if
      nothing is returned (instead of just blocking).  Because of this,
      targets expecting an immediate response need to, internally, set
      things up so that the target_wait() is forced to eventually
-     timeout. */
+     timeout.  */
   /* FIXME: cagney/1999-09-24: It isn't possible for target_open() to
      differentiate to its caller what the state of the target is after
      the initial open has been performed.  Here we're assuming that
      the target has stopped.  It should be possible to eventually have
      target_open() return to the caller an indication that the target
      is currently running and GDB state should be set to the same as
-     for an async run. */
-  wait_for_inferior (0);
+     for an async run.  */
+  wait_for_inferior ();
 
   /* Now that the inferior has stopped, do any bookkeeping like
      loading shared libraries.  We want to do this before normal_stop,
@@ -2139,22 +2290,6 @@ enum infwait_states
   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;
 
@@ -2185,18 +2320,12 @@ static void handle_step_into_function (struct gdbarch *gdbarch,
                                       struct execution_control_state *ecs);
 static void handle_step_into_function_backward (struct gdbarch *gdbarch,
                                                struct execution_control_state *ecs);
-static void insert_step_resume_breakpoint_at_frame (struct frame_info *step_frame);
-static void insert_step_resume_breakpoint_at_caller (struct frame_info *);
-static void insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch,
-                                                 struct symtab_and_line sr_sal,
-                                                 struct frame_id sr_id);
-static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
+static void check_exception_resume (struct execution_control_state *,
+                                   struct frame_info *, struct symbol *);
 
 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
@@ -2314,6 +2443,7 @@ delete_step_resume_breakpoint_callback (struct thread_info *info, void *data)
     return 0;
 
   delete_step_resume_breakpoint (info);
+  delete_exception_resume_breakpoint (info);
   return 0;
 }
 
@@ -2338,6 +2468,7 @@ delete_step_thread_step_resume_breakpoint (void)
       struct thread_info *tp = inferior_thread ();
 
       delete_step_resume_breakpoint (tp);
+      delete_exception_resume_breakpoint (tp);
     }
   else
     /* In all-stop mode, delete all step-resume and longjmp-resume
@@ -2345,7 +2476,7 @@ delete_step_thread_step_resume_breakpoint (void)
     iterate_over_threads (delete_step_resume_breakpoint_callback, NULL);
 }
 
-/* A cleanup wrapper. */
+/* A cleanup wrapper.  */
 
 static void
 delete_step_thread_step_resume_breakpoint_cleanup (void *arg)
@@ -2434,7 +2565,7 @@ prepare_for_detach (void)
         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. */
+        as part of their normal status mechanism.  */
 
       registers_changed ();
 
@@ -2449,7 +2580,8 @@ prepare_for_detach (void)
       /* 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);
+      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
@@ -2480,18 +2612,13 @@ prepare_for_detach (void)
 
 /* Wait for control to return from inferior to debugger.
 
-   If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals
-   as if they were SIGTRAP signals.  This can be useful during
-   the startup sequence on some targets such as HP/UX, where
-   we receive an EXEC event instead of the expected SIGTRAP.
-
    If inferior gets a signal, we may decide to start it up again
    instead of returning.  That is why there is a loop in this function.
    When this function actually returns it means the inferior
    should be left stopped and GDB should read more commands.  */
 
 void
-wait_for_inferior (int treat_exec_as_sigtrap)
+wait_for_inferior (void)
 {
   struct cleanup *old_cleanups;
   struct execution_control_state ecss;
@@ -2499,8 +2626,7 @@ wait_for_inferior (int treat_exec_as_sigtrap)
 
   if (debug_infrun)
     fprintf_unfiltered
-      (gdb_stdlog, "infrun: wait_for_inferior (treat_exec_as_sigtrap=%d)\n",
-       treat_exec_as_sigtrap);
+      (gdb_stdlog, "infrun: wait_for_inferior ()\n");
 
   old_cleanups =
     make_cleanup (delete_step_thread_step_resume_breakpoint_cleanup, NULL);
@@ -2519,7 +2645,7 @@ wait_for_inferior (int treat_exec_as_sigtrap)
         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. */
+        status mechanism.  */
 
       overlay_cache_invalid = 1;
       registers_changed ();
@@ -2532,13 +2658,6 @@ wait_for_inferior (int treat_exec_as_sigtrap)
       if (debug_infrun)
        print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
 
-      if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD)
-        {
-          xfree (ecs->ws.value.execd_pathname);
-          ecs->ws.kind = TARGET_WAITKIND_STOPPED;
-          ecs->ws.value.sig = TARGET_SIGNAL_TRAP;
-        }
-
       /* If an error happens while handling the event, propagate GDB's
         knowledge of the executing state to the frontend/user running
         state.  */
@@ -2561,14 +2680,14 @@ wait_for_inferior (int treat_exec_as_sigtrap)
   do_cleanups (old_cleanups);
 }
 
-/* Asynchronous version of wait_for_inferior. It is called by the
+/* Asynchronous version of wait_for_inferior.  It is called by the
    event loop whenever a change of state is detected on the file
-   descriptor corresponding to the target. It can be called more than
-   once to complete a single execution command. In such cases we need
-   to keep the state in a global variable ECSS. If it is the last time
+   descriptor corresponding to the target.  It can be called more than
+   once to complete a single execution command.  In such cases we need
+   to keep the state in a global variable ECSS.  If it is the last time
    that this function is called for a single execution command, then
    report to the user that the inferior has stopped, and do the
-   necessary cleanups. */
+   necessary cleanups.  */
 
 void
 fetch_inferior_event (void *client_data)
@@ -2584,6 +2703,16 @@ fetch_inferior_event (void *client_data)
   /* We'll update this if & when we switch to a new thread.  */
   previous_inferior_ptid = inferior_ptid;
 
+  /* We're handling a live event, so make sure we're doing live
+     debugging.  If we're looking at traceframes while the target is
+     running, we're going to need to get back to that mode after
+     handling the event.  */
+  if (non_stop)
+    {
+      make_cleanup_restore_current_traceframe ();
+      set_current_traceframe (-1);
+    }
+
   if (non_stop)
     /* In non-stop mode, the user/frontend should not notice a thread
        switch due to internal events.  Make sure we reverse to the
@@ -2595,7 +2724,7 @@ fetch_inferior_event (void *client_data)
      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. */
+     status mechanism.  */
 
   overlay_cache_invalid = 1;
   registers_changed ();
@@ -2636,14 +2765,14 @@ fetch_inferior_event (void *client_data)
       delete_step_thread_step_resume_breakpoint ();
 
       /* We may not find an inferior if this was a process exit.  */
-      if (inf == NULL || inf->stop_soon == NO_STOP_QUIETLY)
+      if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
        normal_stop ();
 
       if (target_has_execution
          && ecs->ws.kind != TARGET_WAITKIND_EXITED
          && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
          && ecs->event_thread->step_multi
-         && ecs->event_thread->stop_step)
+         && ecs->event_thread->control.stop_step)
        inferior_event_handler (INF_EXEC_CONTINUE, NULL);
       else
        inferior_event_handler (INF_EXEC_COMPLETE, NULL);
@@ -2667,8 +2796,8 @@ set_step_info (struct frame_info *frame, struct symtab_and_line sal)
 {
   struct thread_info *tp = inferior_thread ();
 
-  tp->step_frame_id = get_frame_id (frame);
-  tp->step_stack_frame_id = get_stack_frame_id (frame);
+  tp->control.step_frame_id = get_frame_id (frame);
+  tp->control.step_stack_frame_id = get_stack_frame_id (frame);
 
   tp->current_symtab = sal.symtab;
   tp->current_line = sal.line;
@@ -2852,8 +2981,8 @@ init_infwait_state (void)
 void
 error_is_running (void)
 {
-  error (_("\
-Cannot execute this command while the selected thread is running."));
+  error (_("Cannot execute this command while "
+          "the selected thread is running."));
 }
 
 void
@@ -2908,21 +3037,22 @@ handle_syscall_event (struct execution_control_state *ecs)
         fprintf_unfiltered (gdb_stdlog, "infrun: syscall number = '%d'\n",
                             syscall_number);
 
-      ecs->event_thread->stop_bpstat
+      ecs->event_thread->control.stop_bpstat
        = bpstat_stop_status (get_regcache_aspace (regcache),
                              stop_pc, ecs->ptid);
-      ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
+      ecs->random_signal
+       = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
 
       if (!ecs->random_signal)
        {
          /* Catchpoint hit.  */
-         ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
+         ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_TRAP;
          return 0;
        }
     }
 
   /* If no catchpoint triggered for this, then keep going.  */
-  ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+  ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
   keep_going (ecs);
   return 1;
 }
@@ -2965,19 +3095,19 @@ handle_inferior_event (struct execution_control_state *ecs)
       struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
 
       gdb_assert (inf);
-      stop_soon = inf->stop_soon;
+      stop_soon = inf->control.stop_soon;
     }
   else
     stop_soon = NO_STOP_QUIETLY;
 
-  /* Cache the last pid/waitstatus. */
+  /* Cache the last pid/waitstatus.  */
   target_last_wait_ptid = ecs->ptid;
   target_last_waitstatus = ecs->ws;
 
   /* Always clear state belonging to the previous time we stopped.  */
   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 */
 
   ecs->new_thread_event = (!ptid_equal (ecs->ptid, inferior_ptid)
                           && !ptid_equal (ecs->ptid, minus_one_ptid)
@@ -3156,8 +3286,8 @@ handle_inferior_event (struct execution_control_state *ecs)
       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_stop_reason (EXITED, ecs->ws.value.integer);
+      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.  */
@@ -3179,23 +3309,23 @@ handle_inferior_event (struct execution_control_state *ecs)
       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 */
+      target_terminal_ours (); /* Must do this before mourn anyway */
 
       /* 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. */
+         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;
       cancel_single_step_breakpoints ();
       stop_stepping (ecs);
       return;
 
       /* The following are the only cases in which we keep going;
-         the above cases end in a continue or goto. */
+         the above cases end in a continue or goto.  */
     case TARGET_WAITKIND_FORKED:
     case TARGET_WAITKIND_VFORKED:
       if (debug_infrun)
@@ -3230,7 +3360,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       if (singlestep_breakpoints_inserted_p)
        {
-         /* Pull the single step breakpoints out of the target. */
+         /* Pull the single step breakpoints out of the target.  */
          remove_single_step_breakpoints ();
          singlestep_breakpoints_inserted_p = 0;
        }
@@ -3242,7 +3372,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
-      ecs->event_thread->stop_bpstat
+      ecs->event_thread->control.stop_bpstat
        = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
                              stop_pc, ecs->ptid);
 
@@ -3250,7 +3380,8 @@ handle_inferior_event (struct execution_control_state *ecs)
         causes a stop, not just if it may explain the signal.
         Software watchpoints, for example, always appear in the
         bpstat.  */
-      ecs->random_signal = !bpstat_causes_stop (ecs->event_thread->stop_bpstat);
+      ecs->random_signal
+       = !bpstat_causes_stop (ecs->event_thread->control.stop_bpstat);
 
       /* If no catchpoint triggered for this, then keep going.  */
       if (ecs->random_signal)
@@ -3258,9 +3389,10 @@ handle_inferior_event (struct execution_control_state *ecs)
          ptid_t parent;
          ptid_t child;
          int should_resume;
-         int follow_child = (follow_fork_mode_string == follow_fork_mode_child);
+         int follow_child
+           = (follow_fork_mode_string == follow_fork_mode_child);
 
-         ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+         ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
 
          should_resume = follow_fork ();
 
@@ -3294,7 +3426,7 @@ handle_inferior_event (struct execution_control_state *ecs)
            stop_stepping (ecs);
          return;
        }
-      ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
+      ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_TRAP;
       goto process_event_stop_test;
 
     case TARGET_WAITKIND_VFORK_DONE:
@@ -3302,7 +3434,8 @@ handle_inferior_event (struct execution_control_state *ecs)
         the parent, and keep going.  */
 
       if (debug_infrun)
-       fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_VFORK_DONE\n");
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: TARGET_WAITKIND_VFORK_DONE\n");
 
       if (!ptid_equal (ecs->ptid, inferior_ptid))
        context_switch (ecs->ptid);
@@ -3337,10 +3470,11 @@ handle_inferior_event (struct execution_control_state *ecs)
          stop.  */
       follow_exec (inferior_ptid, ecs->ws.value.execd_pathname);
 
-      ecs->event_thread->stop_bpstat
+      ecs->event_thread->control.stop_bpstat
        = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
                              stop_pc, ecs->ptid);
-      ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
+      ecs->random_signal
+       = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
 
       /* Note that this may be referenced from inside
         bpstat_stop_status above, through inferior_has_execd.  */
@@ -3350,19 +3484,20 @@ handle_inferior_event (struct execution_control_state *ecs)
       /* If no catchpoint triggered for this, then keep going.  */
       if (ecs->random_signal)
        {
-         ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+         ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
          keep_going (ecs);
          return;
        }
-      ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
+      ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_TRAP;
       goto process_event_stop_test;
 
       /* Be careful not to try to gather much state about a thread
          that's in a syscall.  It's frequently a losing proposition.  */
     case TARGET_WAITKIND_SYSCALL_ENTRY:
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n");
-      /* Getting the current syscall number */
+        fprintf_unfiltered (gdb_stdlog,
+                           "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n");
+      /* Getting the current syscall number.  */
       if (handle_syscall_event (ecs) != 0)
         return;
       goto process_event_stop_test;
@@ -3374,7 +3509,8 @@ handle_inferior_event (struct execution_control_state *ecs)
          into user code.)  */
     case TARGET_WAITKIND_SYSCALL_RETURN:
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_RETURN\n");
+        fprintf_unfiltered (gdb_stdlog,
+                           "infrun: TARGET_WAITKIND_SYSCALL_RETURN\n");
       if (handle_syscall_event (ecs) != 0)
         return;
       goto process_event_stop_test;
@@ -3382,13 +3518,13 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_STOPPED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n");
-      ecs->event_thread->stop_signal = ecs->ws.value.sig;
+      ecs->event_thread->suspend.stop_signal = ecs->ws.value.sig;
       break;
 
     case TARGET_WAITKIND_NO_HISTORY:
       /* Reverse execution: target ran out of history info.  */
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
-      print_stop_reason (NO_HISTORY, 0);
+      print_no_history_reason ();
       stop_stepping (ecs);
       return;
     }
@@ -3398,8 +3534,9 @@ handle_inferior_event (struct execution_control_state *ecs)
       if (non_stop)
        /* Non-stop assumes that the target handles adding new threads
           to the thread list.  */
-       internal_error (__FILE__, __LINE__, "\
-targets should add new threads to the thread list themselves in non-stop mode.");
+       internal_error (__FILE__, __LINE__,
+                       "targets should add new threads to the thread "
+                       "list themselves in non-stop mode.");
 
       /* We may want to consider not doing a resume here in order to
         give the user a chance to play with the new thread.  It might
@@ -3421,15 +3558,16 @@ targets should add new threads to the thread list themselves in non-stop mode.")
       /* Do we need to clean up the state of a thread that has
         completed a displaced single-step?  (Doing so usually affects
         the PC, so do it here, before we set stop_pc.)  */
-      displaced_step_fixup (ecs->ptid, ecs->event_thread->stop_signal);
+      displaced_step_fixup (ecs->ptid,
+                           ecs->event_thread->suspend.stop_signal);
 
       /* If we either finished a single-step or hit a breakpoint, but
         the user wanted this thread to be stopped, pretend we got a
         SIG0 (generic unsignaled stop).  */
 
       if (ecs->event_thread->stop_requested
-         && ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
-       ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+         && ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP)
+       ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
     }
 
   stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
@@ -3473,16 +3611,18 @@ targets should add new threads to the thread list themselves in non-stop mode.")
       /* We've either finished single-stepping past the single-step
          breakpoint, or stopped for some other reason.  It would be nice if
          we could tell, but we can't reliably.  */
-      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
+      if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP)
        {
          if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n");
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: stepping_past_"
+                               "singlestep_breakpoint\n");
          /* Pull the single step breakpoints out of the target.  */
          remove_single_step_breakpoints ();
          singlestep_breakpoints_inserted_p = 0;
 
          ecs->random_signal = 0;
-         ecs->event_thread->trap_expected = 0;
+         ecs->event_thread->control.trap_expected = 0;
 
          context_switch (saved_singlestep_ptid);
          if (deprecated_context_hook)
@@ -3501,7 +3641,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
 
       /* If we stopped for some other reason than single-stepping, ignore
         the fact that we were supposed to switch back.  */
-      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
+      if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP)
        {
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog,
@@ -3514,6 +3654,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
              singlestep_breakpoints_inserted_p = 0;
            }
 
+         ecs->event_thread->control.trap_expected = 0;
+
          /* Note: We do not call context_switch at this point, as the
             context is already set up for stepping the original thread.  */
          switch_to_thread (deferred_step_ptid);
@@ -3533,14 +3675,14 @@ targets should add new threads to the thread list themselves in non-stop mode.")
      another thread.  If so, then step that thread past the breakpoint,
      and continue it.  */
 
-  if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
+  if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP)
     {
       int thread_hop_needed = 0;
       struct address_space *aspace = 
        get_regcache_aspace (get_thread_regcache (ecs->ptid));
 
       /* Check if a regular breakpoint has been hit before checking
-         for a potential single step breakpoint. Otherwise, GDB will
+         for a potential single step breakpoint.  Otherwise, GDB will
          not see this breakpoint hit when stepping onto breakpoints.  */
       if (regular_breakpoint_inserted_here_p (aspace, stop_pc))
        {
@@ -3599,11 +3741,11 @@ targets should add new threads to the thread list themselves in non-stop mode.")
                    singlestep_ptid.  Don't swap here, since that's
                    the context we want to use.  Just fudge our
                    state and continue.  */
-                 stop_signal = ecs->event_thread->stop_signal;
-                 ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+                 stop_signal = ecs->event_thread->suspend.stop_signal;
+                 ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
                  ecs->ptid = singlestep_ptid;
                  ecs->event_thread = find_thread_ptid (ecs->ptid);
-                 ecs->event_thread->stop_signal = stop_signal;
+                 ecs->event_thread->suspend.stop_signal = stop_signal;
                  stop_pc = new_singlestep_pc;
                }
              else
@@ -3633,11 +3775,11 @@ targets should add new threads to the thread list themselves in non-stop mode.")
            context_switch (ecs->ptid);
 
          /* Saw a breakpoint, but it was hit by the wrong thread.
-            Just continue. */
+            Just continue.  */
 
          if (singlestep_breakpoints_inserted_p)
            {
-             /* Pull the single step breakpoints out of the target. */
+             /* Pull the single step breakpoints out of the target.  */
              remove_single_step_breakpoints ();
              singlestep_breakpoints_inserted_p = 0;
            }
@@ -3654,7 +3796,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
             the bp's: On HP-UX's that use ttrace, we can't
             change the address space of a vforking child
             process until the child exits (well, okay, not
-            then either :-) or execs. */
+            then either :-) or execs.  */
          if (remove_status != 0)
            error (_("Cannot step over breakpoint hit in wrong thread"));
          else
@@ -3700,7 +3842,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
 
   if (singlestep_breakpoints_inserted_p)
     {
-      /* Pull the single step breakpoints out of the target. */
+      /* Pull the single step breakpoints out of the target.  */
       remove_single_step_breakpoints ();
       singlestep_breakpoints_inserted_p = 0;
     }
@@ -3739,7 +3881,12 @@ targets should add new threads to the thread list themselves in non-stop mode.")
       int hw_step = 1;
 
       if (!target_have_steppable_watchpoint)
-       remove_breakpoints ();
+       {
+         remove_breakpoints ();
+         /* See comment in resume why we need to stop bypassing signals
+            while breakpoints have been removed.  */
+         target_pass_signals (0, NULL);
+       }
        /* Single step */
       hw_step = maybe_software_singlestep (gdbarch, stop_pc);
       target_resume (ecs->ptid, hw_step, TARGET_SIGNAL_0);
@@ -3762,8 +3909,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
   ecs->stop_func_start
     += gdbarch_deprecated_function_start_offset (gdbarch);
   ecs->event_thread->stepping_over_breakpoint = 0;
-  bpstat_clear (&ecs->event_thread->stop_bpstat);
-  ecs->event_thread->stop_step = 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;
@@ -3771,17 +3918,17 @@ targets should add new threads to the thread list themselves in non-stop mode.")
   /* Hide inlined functions starting here, unless we just performed stepi or
      nexti.  After stepi and nexti, always show the innermost frame (not any
      inline function call sites).  */
-  if (ecs->event_thread->step_range_end != 1)
+  if (ecs->event_thread->control.step_range_end != 1)
     skip_inline_frames (ecs->ptid);
 
-  if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
-      && ecs->event_thread->trap_expected
+  if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
+      && ecs->event_thread->control.trap_expected
       && gdbarch_single_step_through_delay_p (gdbarch)
       && currently_stepping (ecs->event_thread))
     {
       /* We're trying to step off a breakpoint.  Turns out that we're
         also on an instruction that needs to be stepped multiple
-        times before it's been fully executing. E.g., architectures
+        times before it's been fully executing.  E.g., architectures
         with a delay slot.  It needs to be stepped twice, once for
         the instruction and once for the delay slot.  */
       int step_through_delay
@@ -3789,7 +3936,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
 
       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 (ecs->event_thread->control.step_range_end == 0
+         && step_through_delay)
        {
          /* The user issued a continue when stopped at a breakpoint.
             Set up for another trap and get out of here.  */
@@ -3817,11 +3965,12 @@ targets should add new threads to the thread list themselves in non-stop mode.")
      3) set ecs->random_signal to 1, and the decision between 1 and 2
      will be made according to the signal handling tables.  */
 
-  if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
+  if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
       || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
       || stop_soon == STOP_QUIETLY_REMOTE)
     {
-      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
+      if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
+         && stop_after_trap)
        {
           if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
@@ -3861,17 +4010,17 @@ targets should add new threads to the thread list themselves in non-stop mode.")
         TARGET_SIGNAL_0, meaning: stopped for no particular reason
         other than GDB's request.  */
       if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
-         && (ecs->event_thread->stop_signal == TARGET_SIGNAL_STOP
-             || ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
-             || ecs->event_thread->stop_signal == TARGET_SIGNAL_0))
+         && (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_STOP
+             || ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
+             || ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_0))
        {
          stop_stepping (ecs);
-         ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+         ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
          return;
        }
 
       /* See if there is a breakpoint at the current PC.  */
-      ecs->event_thread->stop_bpstat
+      ecs->event_thread->control.stop_bpstat
        = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
                              stop_pc, ecs->ptid);
 
@@ -3888,11 +4037,12 @@ targets should add new threads to the thread list themselves in non-stop mode.")
         set.  */
 
       if (debug_infrun
-         && ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
-         && !bpstat_explains_signal (ecs->event_thread->stop_bpstat)
+         && ecs->event_thread->suspend.stop_signal == TARGET_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");
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: no user watchpoint explains "
+                           "watchpoint SIGTRAP, ignoring\n");
 
       /* NOTE: cagney/2003-03-29: These two checks for a random signal
          at one stage in the past included checks for an inferior
@@ -3914,24 +4064,26 @@ infrun: no user watchpoint explains watchpoint SIGTRAP, ignoring\n");
          be necessary for call dummies on a non-executable stack on
          SPARC.  */
 
-      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
+      if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP)
        ecs->random_signal
-         = !(bpstat_explains_signal (ecs->event_thread->stop_bpstat)
+         = !(bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
              || stopped_by_watchpoint
-             || ecs->event_thread->trap_expected
-             || (ecs->event_thread->step_range_end
-                 && ecs->event_thread->step_resume_breakpoint == NULL));
+             || 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->stop_bpstat);
+         ecs->random_signal = !bpstat_explains_signal
+                                    (ecs->event_thread->control.stop_bpstat);
          if (!ecs->random_signal)
-           ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP;
+           ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_TRAP;
        }
     }
 
   /* When we reach this point, we've pretty much decided
      that the reason for stopping must've been a random
-     (unexpected) signal. */
+     (unexpected) signal.  */
 
   else
     ecs->random_signal = 1;
@@ -3954,15 +4106,16 @@ process_event_stop_test:
 
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n",
-                            ecs->event_thread->stop_signal);
+                            ecs->event_thread->suspend.stop_signal);
 
       stopped_by_random_signal = 1;
 
-      if (signal_print[ecs->event_thread->stop_signal])
+      if (signal_print[ecs->event_thread->suspend.stop_signal])
        {
          printed = 1;
          target_terminal_ours_for_output ();
-         print_stop_reason (SIGNAL_RECEIVED, ecs->event_thread->stop_signal);
+         print_signal_received_reason
+                                    (ecs->event_thread->suspend.stop_signal);
        }
       /* Always stop on signals if we're either just gaining control
         of the program, or the user explicitly requested this thread
@@ -3970,7 +4123,7 @@ process_event_stop_test:
       if (stop_soon != NO_STOP_QUIETLY
          || ecs->event_thread->stop_requested
          || (!inf->detaching
-             && signal_stop_state (ecs->event_thread->stop_signal)))
+             && signal_stop_state (ecs->event_thread->suspend.stop_signal)))
        {
          stop_stepping (ecs);
          return;
@@ -3981,12 +4134,12 @@ process_event_stop_test:
        target_terminal_inferior ();
 
       /* Clear the signal if it should not be passed.  */
-      if (signal_program[ecs->event_thread->stop_signal] == 0)
-       ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+      if (signal_program[ecs->event_thread->suspend.stop_signal] == 0)
+       ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
 
       if (ecs->event_thread->prev_pc == stop_pc
-         && ecs->event_thread->trap_expected
-         && ecs->event_thread->step_resume_breakpoint == NULL)
+         && ecs->event_thread->control.trap_expected
+         && ecs->event_thread->control.step_resume_breakpoint == NULL)
        {
          /* We were just starting a new sequence, attempting to
             single-step off of a breakpoint and expecting a SIGTRAP.
@@ -4005,17 +4158,19 @@ process_event_stop_test:
 
          insert_step_resume_breakpoint_at_frame (frame);
          ecs->event_thread->step_after_step_resume_breakpoint = 1;
+         /* Reset trap_expected to ensure breakpoints are re-inserted.  */
+         ecs->event_thread->control.trap_expected = 0;
          keep_going (ecs);
          return;
        }
 
-      if (ecs->event_thread->step_range_end != 0
-         && ecs->event_thread->stop_signal != TARGET_SIGNAL_0
-         && (ecs->event_thread->step_range_start <= stop_pc
-             && stop_pc < ecs->event_thread->step_range_end)
+      if (ecs->event_thread->control.step_range_end != 0
+         && ecs->event_thread->suspend.stop_signal != TARGET_SIGNAL_0
+         && (ecs->event_thread->control.step_range_start <= stop_pc
+             && stop_pc < ecs->event_thread->control.step_range_end)
          && frame_id_eq (get_stack_frame_id (frame),
-                         ecs->event_thread->step_stack_frame_id)
-         && ecs->event_thread->step_resume_breakpoint == NULL)
+                         ecs->event_thread->control.step_stack_frame_id)
+         && ecs->event_thread->control.step_resume_breakpoint == NULL)
        {
          /* The inferior is about to take a signal that will take it
             out of the single step range.  Set a breakpoint at the
@@ -4032,6 +4187,8 @@ process_event_stop_test:
                                 "single-step range\n");
 
          insert_step_resume_breakpoint_at_frame (frame);
+         /* Reset trap_expected to ensure breakpoints are re-inserted.  */
+         ecs->event_thread->control.trap_expected = 0;
          keep_going (ecs);
          return;
        }
@@ -4051,7 +4208,7 @@ process_event_stop_test:
     CORE_ADDR jmp_buf_pc;
     struct bpstat_what what;
 
-    what = bpstat_what (ecs->event_thread->stop_bpstat);
+    what = bpstat_what (ecs->event_thread->control.stop_bpstat);
 
     if (what.call_dummy)
       {
@@ -4077,23 +4234,34 @@ process_event_stop_test:
 
        ecs->event_thread->stepping_over_breakpoint = 1;
 
-       if (!gdbarch_get_longjmp_target_p (gdbarch)
-           || !gdbarch_get_longjmp_target (gdbarch, frame, &jmp_buf_pc))
+       if (what.is_longjmp)
          {
-           if (debug_infrun)
-             fprintf_unfiltered (gdb_stdlog, "\
-infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
-           keep_going (ecs);
-           return;
-         }
+           if (!gdbarch_get_longjmp_target_p (gdbarch)
+               || !gdbarch_get_longjmp_target (gdbarch,
+                                               frame, &jmp_buf_pc))
+             {
+               if (debug_infrun)
+                 fprintf_unfiltered (gdb_stdlog,
+                                     "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME "
+                                     "(!gdbarch_get_longjmp_target)\n");
+               keep_going (ecs);
+               return;
+             }
 
-       /* We're going to replace the current step-resume breakpoint
-          with a longjmp-resume breakpoint.  */
-       delete_step_resume_breakpoint (ecs->event_thread);
+           /* We're going to replace the current step-resume breakpoint
+              with a longjmp-resume breakpoint.  */
+           delete_step_resume_breakpoint (ecs->event_thread);
 
-       /* Insert a breakpoint at resume address.  */
-       insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
+           /* Insert a breakpoint at resume address.  */
+           insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
+         }
+       else
+         {
+           struct symbol *func = get_frame_function (frame);
 
+           if (func)
+             check_exception_resume (ecs, frame, func);
+         }
        keep_going (ecs);
        return;
 
@@ -4102,11 +4270,57 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          fprintf_unfiltered (gdb_stdlog,
                              "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
 
-       gdb_assert (ecs->event_thread->step_resume_breakpoint != NULL);
-       delete_step_resume_breakpoint (ecs->event_thread);
+       if (what.is_longjmp)
+         {
+           gdb_assert (ecs->event_thread->control.step_resume_breakpoint
+                       != NULL);
+           delete_step_resume_breakpoint (ecs->event_thread);
+         }
+       else
+         {
+           /* There are several cases to consider.
+
+              1. The initiating frame no longer exists.  In this case
+              we must stop, because the exception has gone too far.
+
+              2. The initiating frame exists, and is the same as the
+              current frame.  We stop, because the exception has been
+              caught.
+
+              3. The initiating frame exists and is different from
+              the current frame.  This means the exception has been
+              caught beneath the initiating frame, so keep going.  */
+           struct frame_info *init_frame
+             = frame_find_by_id (ecs->event_thread->initiating_frame);
 
-       ecs->event_thread->stop_step = 1;
-       print_stop_reason (END_STEPPING_RANGE, 0);
+           gdb_assert (ecs->event_thread->control.exception_resume_breakpoint
+                       != NULL);
+           delete_exception_resume_breakpoint (ecs->event_thread);
+
+           if (init_frame)
+             {
+               struct frame_id current_id
+                 = get_frame_id (get_current_frame ());
+               if (frame_id_eq (current_id,
+                                ecs->event_thread->initiating_frame))
+                 {
+                   /* Case 2.  Fall through.  */
+                 }
+               else
+                 {
+                   /* Case 3.  */
+                   keep_going (ecs);
+                   return;
+                 }
+             }
+
+           /* For Cases 1 and 2, remove the step-resume breakpoint,
+              if it exists.  */
+           delete_step_resume_breakpoint (ecs->event_thread);
+         }
+
+       ecs->event_thread->control.stop_step = 1;
+       print_end_stepping_range_reason ();
        stop_stepping (ecs);
        return;
 
@@ -4192,8 +4406,8 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          /* However, if the current thread is blocked on some internal
             breakpoint, and we simply need to step over that breakpoint
             to get it going again, do that first.  */
-         if ((ecs->event_thread->trap_expected
-              && ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP)
+         if ((ecs->event_thread->control.trap_expected
+              && ecs->event_thread->suspend.stop_signal != TARGET_SIGNAL_TRAP)
              || ecs->event_thread->stepping_over_breakpoint)
            {
              keep_going (ecs);
@@ -4223,8 +4437,9 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
              || !target_thread_alive (tp->ptid))
            {
              if (debug_infrun)
-               fprintf_unfiltered (gdb_stdlog, "\
-infrun: not switching back to stepped thread, it has vanished\n");
+               fprintf_unfiltered (gdb_stdlog,
+                                   "infrun: not switching back to "
+                                   "stepped thread, it has vanished\n");
 
              delete_thread (tp->ptid);
              keep_going (ecs);
@@ -4234,7 +4449,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
          /* Otherwise, we no longer expect a trap in the current thread.
             Clear the trap_expected flag before switching back -- this is
             what keep_going would do as well, if we called it.  */
-         ecs->event_thread->trap_expected = 0;
+         ecs->event_thread->control.trap_expected = 0;
 
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog,
@@ -4254,11 +4469,12 @@ infrun: not switching back to stepped thread, it has vanished\n");
   if (ecs->event_thread->stepping_through_solib_after_catch)
     {
 #if defined(SOLIB_ADD)
-      /* Have we reached our destination?  If not, keep going. */
+      /* Have we reached our destination?  If not, keep going.  */
       if (SOLIB_IN_DYNAMIC_LINKER (PIDGET (ecs->ptid), stop_pc))
        {
           if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog, "infrun: stepping in dynamic linker\n");
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: stepping in dynamic linker\n");
          ecs->event_thread->stepping_over_breakpoint = 1;
          keep_going (ecs);
          return;
@@ -4267,10 +4483,10 @@ infrun: not switching back to stepped thread, it has vanished\n");
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: step past dynamic linker\n");
       /* Else, stop and report the catchpoint(s) whose triggering
-         caused us to begin stepping. */
+         caused us to begin stepping.  */
       ecs->event_thread->stepping_through_solib_after_catch = 0;
-      bpstat_clear (&ecs->event_thread->stop_bpstat);
-      ecs->event_thread->stop_bpstat
+      bpstat_clear (&ecs->event_thread->control.stop_bpstat);
+      ecs->event_thread->control.stop_bpstat
        = bpstat_copy (ecs->event_thread->stepping_through_solib_catchpoints);
       bpstat_clear (&ecs->event_thread->stepping_through_solib_catchpoints);
       stop_print_frame = 1;
@@ -4278,7 +4494,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
       return;
     }
 
-  if (ecs->event_thread->step_resume_breakpoint)
+  if (ecs->event_thread->control.step_resume_breakpoint)
     {
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog,
@@ -4291,7 +4507,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
       return;
     }
 
-  if (ecs->event_thread->step_range_end == 0)
+  if (ecs->event_thread->control.step_range_end == 0)
     {
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: no stepping, continue\n");
@@ -4316,27 +4532,27 @@ infrun: not switching back to stepped thread, it has vanished\n");
      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->step_range_start
-      && stop_pc < ecs->event_thread->step_range_end
+  if (stop_pc >= ecs->event_thread->control.step_range_start
+      && stop_pc < ecs->event_thread->control.step_range_end
       && (execution_direction != EXEC_REVERSE
          || frame_id_eq (get_frame_id (frame),
-                         ecs->event_thread->step_frame_id)))
+                         ecs->event_thread->control.step_frame_id)))
     {
       if (debug_infrun)
        fprintf_unfiltered
          (gdb_stdlog, "infrun: stepping inside range [%s-%s]\n",
-          paddress (gdbarch, ecs->event_thread->step_range_start),
-          paddress (gdbarch, ecs->event_thread->step_range_end));
+          paddress (gdbarch, ecs->event_thread->control.step_range_start),
+          paddress (gdbarch, ecs->event_thread->control.step_range_end));
 
       /* When stepping backward, stop at beginning of line range
         (unless it's the function entry point, in which case
         keep going back to the call point).  */
-      if (stop_pc == ecs->event_thread->step_range_start
+      if (stop_pc == ecs->event_thread->control.step_range_start
          && stop_pc != ecs->stop_func_start
          && execution_direction == EXEC_REVERSE)
        {
-         ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         ecs->event_thread->control.stop_step = 1;
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
        }
       else
@@ -4360,14 +4576,15 @@ infrun: not switching back to stepped thread, it has vanished\n");
      down, so there is nothing for us to do here.  */
 
   if (execution_direction != EXEC_REVERSE
-      && ecs->event_thread->step_over_calls == STEP_OVER_UNDEBUGGABLE
+      && ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
       && in_solib_dynsym_resolve_code (stop_pc))
     {
       CORE_ADDR pc_after_resolver =
        gdbarch_skip_solib_resolver (gdbarch, stop_pc);
 
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: stepped into dynsym resolve code\n");
+        fprintf_unfiltered (gdb_stdlog,
+                            "infrun: stepped into dynsym resolve code\n");
 
       if (pc_after_resolver)
        {
@@ -4387,13 +4604,14 @@ infrun: not switching back to stepped thread, it has vanished\n");
       return;
     }
 
-  if (ecs->event_thread->step_range_end != 1
-      && (ecs->event_thread->step_over_calls == STEP_OVER_UNDEBUGGABLE
-         || ecs->event_thread->step_over_calls == STEP_OVER_ALL)
+  if (ecs->event_thread->control.step_range_end != 1
+      && (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
+         || ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
       && get_frame_type (frame) == SIGTRAMP_FRAME)
     {
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: stepped into signal trampoline\n");
+        fprintf_unfiltered (gdb_stdlog,
+                            "infrun: stepped into signal trampoline\n");
       /* The inferior, while doing a "step" or "next", has ended up in
          a signal trampoline (either by a signal being delivered or by
          the signal handler returning).  Just single-step until the
@@ -4421,10 +4639,10 @@ infrun: not switching back to stepped thread, it has vanished\n");
      have code_addr == &_start.  See the comment in frame_id_eq
      for more.  */
   if (!frame_id_eq (get_stack_frame_id (frame),
-                   ecs->event_thread->step_stack_frame_id)
+                   ecs->event_thread->control.step_stack_frame_id)
       && (frame_id_eq (frame_unwind_caller_id (get_current_frame ()),
-                      ecs->event_thread->step_stack_frame_id)
-         && (!frame_id_eq (ecs->event_thread->step_stack_frame_id,
+                      ecs->event_thread->control.step_stack_frame_id)
+         && (!frame_id_eq (ecs->event_thread->control.step_stack_frame_id,
                            outer_frame_id)
              || step_start_function != find_pc_function (stop_pc))))
     {
@@ -4433,8 +4651,8 @@ infrun: not switching back to stepped thread, it has vanished\n");
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepped into subroutine\n");
 
-      if ((ecs->event_thread->step_over_calls == STEP_OVER_NONE)
-         || ((ecs->event_thread->step_range_end == 1)
+      if ((ecs->event_thread->control.step_over_calls == STEP_OVER_NONE)
+         || ((ecs->event_thread->control.step_range_end == 1)
              && in_prologue (gdbarch, ecs->event_thread->prev_pc,
                              ecs->stop_func_start)))
        {
@@ -4445,8 +4663,8 @@ infrun: not switching back to stepped thread, it has vanished\n");
             thought it was a subroutine call but it was not.  Stop as
             well.  FENN */
          /* And this works the same backward as frontward.  MVS */
-         ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         ecs->event_thread->control.stop_step = 1;
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
          return;
        }
@@ -4454,7 +4672,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
       /* Reverse stepping through solib trampolines.  */
 
       if (execution_direction == EXEC_REVERSE
-         && ecs->event_thread->step_over_calls != STEP_OVER_NONE
+         && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE
          && (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc)
              || (ecs->stop_func_start == 0
                  && in_solib_dynsym_resolve_code (stop_pc))))
@@ -4468,7 +4686,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
          return;
        }
 
-      if (ecs->event_thread->step_over_calls == STEP_OVER_ALL)
+      if (ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
        {
          /* We're doing a "next".
 
@@ -4534,7 +4752,6 @@ infrun: not switching back to stepped thread, it has vanished\n");
        struct symtab_and_line tmp_sal;
 
        tmp_sal = find_pc_line (ecs->stop_func_start, 0);
-       tmp_sal.pspace = get_frame_program_space (frame);
        if (tmp_sal.line != 0)
          {
            if (execution_direction == EXEC_REVERSE)
@@ -4548,11 +4765,11 @@ infrun: not switching back to stepped thread, it has vanished\n");
       /* If we have no line number and the step-stop-if-no-debug is
          set, we stop the step so that the user has a chance to switch
          in assembly mode.  */
-      if (ecs->event_thread->step_over_calls == STEP_OVER_UNDEBUGGABLE
+      if (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
          && step_stop_if_no_debug)
        {
-         ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         ecs->event_thread->control.stop_step = 1;
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
          return;
        }
@@ -4581,7 +4798,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
   /* Reverse stepping through solib trampolines.  */
 
   if (execution_direction == EXEC_REVERSE
-      && ecs->event_thread->step_over_calls != STEP_OVER_NONE)
+      && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE)
     {
       if (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc)
          || (ecs->stop_func_start == 0
@@ -4623,12 +4840,13 @@ infrun: not switching back to stepped thread, it has vanished\n");
       real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
 
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: stepped into solib return tramp\n");
+        fprintf_unfiltered (gdb_stdlog,
+                            "infrun: stepped into solib return tramp\n");
 
       /* Only proceed through if we know where it's going.  */
       if (real_stop_pc)
        {
-         /* And put the step-breakpoint there and go until there. */
+         /* And put the step-breakpoint there and go until there.  */
          struct symtab_and_line sr_sal;
 
          init_sal (&sr_sal);   /* initialize to zeroes */
@@ -4654,12 +4872,13 @@ infrun: not switching back to stepped thread, it has vanished\n");
   /* NOTE: tausq/2004-05-24: This if block used to be done before all
      the trampoline processing logic, however, there are some trampolines 
      that have no names, so we should do trampoline handling first.  */
-  if (ecs->event_thread->step_over_calls == STEP_OVER_UNDEBUGGABLE
+  if (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
       && ecs->stop_func_name == NULL
       && stop_pc_sal.line == 0)
     {
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n");
+        fprintf_unfiltered (gdb_stdlog,
+                            "infrun: stepped into undebuggable function\n");
 
       /* The inferior just stepped into, or returned to, an
          undebuggable function (where there is no debugging information
@@ -4675,8 +4894,8 @@ infrun: not switching back to stepped thread, it has vanished\n");
          /* If we have no line number and the step-stop-if-no-debug
             is set, we stop the step so that the user has a chance to
             switch in assembly mode.  */
-         ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         ecs->event_thread->control.stop_step = 1;
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
          return;
        }
@@ -4690,14 +4909,14 @@ infrun: not switching back to stepped thread, it has vanished\n");
        }
     }
 
-  if (ecs->event_thread->step_range_end == 1)
+  if (ecs->event_thread->control.step_range_end == 1)
     {
       /* It is stepi or nexti.  We always want to stop stepping after
          one instruction.  */
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepi/nexti\n");
-      ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      ecs->event_thread->control.stop_step = 1;
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
       return;
     }
@@ -4710,8 +4929,8 @@ infrun: not switching back to stepped thread, it has vanished\n");
          or can this happen as a result of a return or longjmp?).  */
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
-      ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      ecs->event_thread->control.stop_step = 1;
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
       return;
     }
@@ -4721,7 +4940,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
      a new inline function.  */
 
   if (frame_id_eq (get_frame_id (get_current_frame ()),
-                  ecs->event_thread->step_frame_id)
+                  ecs->event_thread->control.step_frame_id)
       && inline_skipped_frames (ecs->ptid))
     {
       struct symtab_and_line call_sal;
@@ -4732,7 +4951,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
 
       find_frame_sal (get_current_frame (), &call_sal);
 
-      if (ecs->event_thread->step_over_calls != STEP_OVER_ALL)
+      if (ecs->event_thread->control.step_over_calls != STEP_OVER_ALL)
        {
          /* For "step", we're going to stop.  But if the call site
             for this inlined function is on the same source line as
@@ -4743,8 +4962,8 @@ infrun: not switching back to stepped thread, it has vanished\n");
              && call_sal.symtab == ecs->event_thread->current_symtab)
            step_into_inline_frame (ecs->ptid);
 
-         ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         ecs->event_thread->control.stop_step = 1;
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
          return;
        }
@@ -4758,8 +4977,8 @@ infrun: not switching back to stepped thread, it has vanished\n");
            keep_going (ecs);
          else
            {
-             ecs->event_thread->stop_step = 1;
-             print_stop_reason (END_STEPPING_RANGE, 0);
+             ecs->event_thread->control.stop_step = 1;
+             print_end_stepping_range_reason ();
              stop_stepping (ecs);
            }
          return;
@@ -4773,20 +4992,20 @@ infrun: not switching back to stepped thread, it has vanished\n");
 
   if (get_frame_type (get_current_frame ()) == INLINE_FRAME
       && !frame_id_eq (get_frame_id (get_current_frame ()),
-                      ecs->event_thread->step_frame_id)
+                      ecs->event_thread->control.step_frame_id)
       && stepped_in_from (get_current_frame (),
-                         ecs->event_thread->step_frame_id))
+                         ecs->event_thread->control.step_frame_id))
     {
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog,
                            "infrun: stepping through inlined function\n");
 
-      if (ecs->event_thread->step_over_calls == STEP_OVER_ALL)
+      if (ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
        keep_going (ecs);
       else
        {
-         ecs->event_thread->stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
+         ecs->event_thread->control.stop_step = 1;
+         print_end_stepping_range_reason ();
          stop_stepping (ecs);
        }
       return;
@@ -4801,9 +5020,10 @@ infrun: not switching back to stepped thread, it has vanished\n");
          That is said to make things like for (;;) statements work
          better.  */
       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);
+        fprintf_unfiltered (gdb_stdlog,
+                            "infrun: stepped to a different line\n");
+      ecs->event_thread->control.stop_step = 1;
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
       return;
     }
@@ -4815,8 +5035,8 @@ infrun: not switching back to stepped thread, it has vanished\n");
      new line in mid-statement, we continue stepping.  This makes
      things like for(;;) statements work better.)  */
 
-  ecs->event_thread->step_range_start = stop_pc_sal.pc;
-  ecs->event_thread->step_range_end = stop_pc_sal.end;
+  ecs->event_thread->control.step_range_start = stop_pc_sal.pc;
+  ecs->event_thread->control.step_range_end = stop_pc_sal.end;
   set_step_info (frame, stop_pc_sal);
 
   if (debug_infrun)
@@ -4829,10 +5049,11 @@ infrun: not switching back to stepped thread, it has vanished\n");
 static int
 currently_stepping (struct thread_info *tp)
 {
-  return ((tp->step_range_end && tp->step_resume_breakpoint == NULL)
-         || tp->trap_expected
-         || tp->stepping_through_solib_after_catch
-         || bpstat_should_step ());
+  return ((tp->control.step_range_end
+          && tp->control.step_resume_breakpoint == NULL)
+         || tp->control.trap_expected
+         || tp->stepping_through_solib_after_catch
+         || bpstat_should_step ());
 }
 
 /* Returns true if any thread *but* the one passed in "data" is in the
@@ -4844,8 +5065,8 @@ currently_stepping_or_nexting_callback (struct thread_info *tp, void *data)
   if (tp == data)
     return 0;
 
-  return (tp->step_range_end
-         || tp->trap_expected
+  return (tp->control.step_range_end
+         || tp->control.trap_expected
          || tp->stepping_through_solib_after_catch);
 }
 
@@ -4903,8 +5124,8 @@ handle_step_into_function (struct gdbarch *gdbarch,
   if (ecs->stop_func_start == stop_pc)
     {
       /* We are already there: stop now.  */
-      ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      ecs->event_thread->control.stop_step = 1;
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
       return;
     }
@@ -4922,7 +5143,8 @@ handle_step_into_function (struct gdbarch *gdbarch,
       insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, null_frame_id);
 
       /* And make sure stepping stops right away then.  */
-      ecs->event_thread->step_range_end = ecs->event_thread->step_range_start;
+      ecs->event_thread->control.step_range_end
+        = ecs->event_thread->control.step_range_start;
     }
   keep_going (ecs);
 }
@@ -4949,8 +5171,8 @@ handle_step_into_function_backward (struct gdbarch *gdbarch,
   if (stop_func_sal.pc == stop_pc)
     {
       /* We're there already.  Just stop stepping now.  */
-      ecs->event_thread->stop_step = 1;
-      print_stop_reason (END_STEPPING_RANGE, 0);
+      ecs->event_thread->control.stop_step = 1;
+      print_end_stepping_range_reason ();
       stop_stepping (ecs);
     }
   else
@@ -4958,8 +5180,8 @@ handle_step_into_function_backward (struct gdbarch *gdbarch,
       /* Else just reset the step range and keep going.
         No step-resume breakpoint, they don't work for
         epilogues, which can have multiple entry paths.  */
-      ecs->event_thread->step_range_start = stop_func_sal.pc;
-      ecs->event_thread->step_range_end = stop_func_sal.end;
+      ecs->event_thread->control.step_range_start = stop_func_sal.pc;
+      ecs->event_thread->control.step_range_end = stop_func_sal.end;
       keep_going (ecs);
     }
   return;
@@ -4976,14 +5198,14 @@ insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch,
   /* There should never be more than one step-resume or longjmp-resume
      breakpoint per thread, so we should never be setting a new
      step_resume_breakpoint when one is already active.  */
-  gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL);
+  gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL);
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
                        "infrun: inserting step-resume breakpoint at %s\n",
                        paddress (gdbarch, sr_sal.pc));
 
-  inferior_thread ()->step_resume_breakpoint
+  inferior_thread ()->control.step_resume_breakpoint
     = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, bp_step_resume);
 }
 
@@ -5060,17 +5282,108 @@ insert_longjmp_resume_breakpoint (struct gdbarch *gdbarch, CORE_ADDR pc)
   /* There should never be more than one step-resume or longjmp-resume
      breakpoint per thread, so we should never be setting a new
      longjmp_resume_breakpoint when one is already active.  */
-  gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL);
+  gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL);
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
                        "infrun: inserting longjmp-resume breakpoint at %s\n",
                        paddress (gdbarch, pc));
 
-  inferior_thread ()->step_resume_breakpoint =
+  inferior_thread ()->control.step_resume_breakpoint =
     set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume);
 }
 
+/* Insert an exception resume breakpoint.  TP is the thread throwing
+   the exception.  The block B is the block of the unwinder debug hook
+   function.  FRAME is the frame corresponding to the call to this
+   function.  SYM is the symbol of the function argument holding the
+   target PC of the exception.  */
+
+static void
+insert_exception_resume_breakpoint (struct thread_info *tp,
+                                   struct block *b,
+                                   struct frame_info *frame,
+                                   struct symbol *sym)
+{
+  struct gdb_exception e;
+
+  /* We want to ignore errors here.  */
+  TRY_CATCH (e, RETURN_MASK_ERROR)
+    {
+      struct symbol *vsym;
+      struct value *value;
+      CORE_ADDR handler;
+      struct breakpoint *bp;
+
+      vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL);
+      value = read_var_value (vsym, frame);
+      /* If the value was optimized out, revert to the old behavior.  */
+      if (! value_optimized_out (value))
+       {
+         handler = value_as_address (value);
+
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: exception resume at %lx\n",
+                               (unsigned long) handler);
+
+         bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
+                                              handler, bp_exception_resume);
+         bp->thread = tp->num;
+         inferior_thread ()->control.exception_resume_breakpoint = bp;
+       }
+    }
+}
+
+/* This is called when an exception has been intercepted.  Check to
+   see whether the exception's destination is of interest, and if so,
+   set an exception resume breakpoint there.  */
+
+static void
+check_exception_resume (struct execution_control_state *ecs,
+                       struct frame_info *frame, struct symbol *func)
+{
+  struct gdb_exception e;
+
+  TRY_CATCH (e, RETURN_MASK_ERROR)
+    {
+      struct block *b;
+      struct dict_iterator iter;
+      struct symbol *sym;
+      int argno = 0;
+
+      /* The exception breakpoint is a thread-specific breakpoint on
+        the unwinder's debug hook, declared as:
+        
+        void _Unwind_DebugHook (void *cfa, void *handler);
+        
+        The CFA argument indicates the frame to which control is
+        about to be transferred.  HANDLER is the destination PC.
+        
+        We ignore the CFA and set a temporary breakpoint at HANDLER.
+        This is not extremely efficient but it avoids issues in gdb
+        with computing the DWARF CFA, and it also works even in weird
+        cases such as throwing an exception from inside a signal
+        handler.  */
+
+      b = SYMBOL_BLOCK_VALUE (func);
+      ALL_BLOCK_SYMBOLS (b, iter, sym)
+       {
+         if (!SYMBOL_IS_ARGUMENT (sym))
+           continue;
+
+         if (argno == 0)
+           ++argno;
+         else
+           {
+             insert_exception_resume_breakpoint (ecs->event_thread,
+                                                 b, frame, sym);
+             break;
+           }
+       }
+    }
+}
+
 static void
 stop_stepping (struct execution_control_state *ecs)
 {
@@ -5083,7 +5396,7 @@ stop_stepping (struct execution_control_state *ecs)
 
 /* 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) */
+/* (Used to be the keep_going: label in the old wait_for_inferior) */
 
 static void
 keep_going (struct execution_control_state *ecs)
@@ -5099,8 +5412,8 @@ keep_going (struct execution_control_state *ecs)
   /* If we did not do break;, it means we should keep running the
      inferior and not return to debugger.  */
 
-  if (ecs->event_thread->trap_expected
-      && ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP)
+  if (ecs->event_thread->control.trap_expected
+      && ecs->event_thread->suspend.stop_signal != TARGET_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
@@ -5108,7 +5421,7 @@ keep_going (struct execution_control_state *ecs)
 
       discard_cleanups (old_cleanups);
       resume (currently_stepping (ecs->event_thread),
-             ecs->event_thread->stop_signal);
+             ecs->event_thread->suspend.stop_signal);
     }
   else
     {
@@ -5153,7 +5466,8 @@ keep_going (struct execution_control_state *ecs)
            }
        }
 
-      ecs->event_thread->trap_expected = ecs->event_thread->stepping_over_breakpoint;
+      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
@@ -5165,15 +5479,15 @@ keep_going (struct execution_control_state *ecs)
          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. */
+         equivalent of a SIGNAL_TRAP to the program being debugged.  */
 
-      if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
-         && !signal_program[ecs->event_thread->stop_signal])
-       ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+      if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
+         && !signal_program[ecs->event_thread->suspend.stop_signal])
+       ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
 
       discard_cleanups (old_cleanups);
       resume (currently_stepping (ecs->event_thread),
-             ecs->event_thread->stop_signal);
+             ecs->event_thread->suspend.stop_signal);
     }
 
   prepare_to_wait (ecs);
@@ -5195,116 +5509,133 @@ prepare_to_wait (struct execution_control_state *ecs)
   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_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
+print_end_stepping_range_reason (void)
 {
-  switch (stop_reason)
+  if ((!inferior_thread ()->step_multi
+       || !inferior_thread ()->control.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
+print_exited_reason (int exitstatus)
+{
+  struct inferior *inf = current_inferior ();
+  const char *pidstr = target_pid_to_str (pid_to_ptid (inf->pid));
+
+  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, "[Inferior ");
+      ui_out_text (uiout, plongest (inf->num));
+      ui_out_text (uiout, " (");
+      ui_out_text (uiout, pidstr);
+      ui_out_text (uiout, ") 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
-         (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, "[Inferior ");
+      ui_out_text (uiout, plongest (inf->num));
+      ui_out_text (uiout, " (");
+      ui_out_text (uiout, pidstr);
+      ui_out_text (uiout, ") 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 ();
+      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));
+                          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 (stop_info));
+                          target_signal_to_string (siggnal));
       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.
@@ -5363,9 +5694,9 @@ normal_stop (void)
       if (remove_breakpoints ())
        {
          target_terminal_ours_for_output ();
-         printf_filtered (_("\
-Cannot remove breakpoints because program is no longer writable.\n\
-Further execution is probably impossible.\n"));
+         printf_filtered (_("Cannot remove breakpoints because "
+                            "program is no longer writable.\nFurther "
+                            "execution is probably impossible.\n"));
        }
     }
 
@@ -5381,7 +5712,7 @@ Further execution is probably impossible.\n"));
       && last.kind != TARGET_WAITKIND_SIGNALLED
       && last.kind != TARGET_WAITKIND_EXITED
       && inferior_thread ()->step_multi
-      && inferior_thread ()->stop_step)
+      && inferior_thread ()->control.stop_step)
     goto done;
 
   target_terminal_ours ();
@@ -5411,7 +5742,7 @@ Further execution is probably impossible.\n"));
   /* Select innermost stack frame - i.e., current frame is frame 0,
      and current location is based on that.
      Don't do this on return from a stack dummy routine,
-     or if the program has exited. */
+     or if the program has exited.  */
 
   if (!stop_stack_dummy)
     {
@@ -5421,7 +5752,7 @@ Further execution is probably impossible.\n"));
          we have changed functions or hit a breakpoint.
          Print source line if we have one.
          bpstat_print() contains the logic deciding in detail
-         what to print, based on the event(s) that just occurred. */
+         what to print, based on the event(s) that just occurred.  */
 
       /* If --batch-silent is enabled then there's no need to print the current
         source location, and to try risks causing an error message about
@@ -5433,7 +5764,7 @@ Further execution is probably impossible.\n"));
          int do_frame_printing = 1;
          struct thread_info *tp = inferior_thread ();
 
-         bpstat_ret = bpstat_print (tp->stop_bpstat);
+         bpstat_ret = bpstat_print (tp->control.stop_bpstat);
          switch (bpstat_ret)
            {
            case PRINT_UNKNOWN:
@@ -5452,16 +5783,19 @@ Further execution is probably impossible.\n"));
              /* FIXME: cagney/2002-12-01: Given that a frame ID does
                 (or should) carry around the function and does (or
                 should) use that when doing a frame comparison.  */
-             if (tp->stop_step
-                 && frame_id_eq (tp->step_frame_id,
+             if (tp->control.stop_step
+                 && frame_id_eq (tp->control.step_frame_id,
                                  get_frame_id (get_current_frame ()))
                  && step_start_function == find_pc_function (stop_pc))
-               source_flag = SRC_LINE; /* finished step, just print source line */
+               source_flag = SRC_LINE;         /* Finished step, just
+                                                  print source line.  */
              else
-               source_flag = SRC_AND_LOC;      /* print location and source line */
+               source_flag = SRC_AND_LOC;      /* Print location and
+                                                  source line.  */
              break;
            case PRINT_SRC_AND_LOC:
-             source_flag = SRC_AND_LOC;        /* print location and source line */
+             source_flag = SRC_AND_LOC;        /* Print location and
+                                                  source line.  */
              break;
            case PRINT_SRC_ONLY:
              source_flag = SRC_LINE;
@@ -5478,7 +5812,7 @@ Further execution is probably impossible.\n"));
             flag is:
             SRC_LINE: Print only source line
             LOCATION: Print only location
-            SRC_AND_LOC: Print location and source line */
+            SRC_AND_LOC: Print location and source line */
          if (do_frame_printing)
            print_stack_frame (get_selected_frame (NULL), 0, source_flag);
 
@@ -5489,7 +5823,7 @@ Further execution is probably impossible.\n"));
 
   /* Save the function value return registers, if we care.
      We might be about to restore their previous contents.  */
-  if (inferior_thread ()->proceed_to_finish)
+  if (inferior_thread ()->control.proceed_to_finish)
     {
       /* This should not be necessary.  */
       if (stop_registers)
@@ -5504,19 +5838,20 @@ Further execution is probably impossible.\n"));
     {
       /* Pop the empty frame that contains the stack dummy.
         This also restores inferior state prior to the call
-        (struct inferior_thread_state).  */
+        (struct infcall_suspend_state).  */
       struct frame_info *frame = get_current_frame ();
 
       gdb_assert (get_frame_type (frame) == DUMMY_FRAME);
       frame_pop (frame);
-      /* frame_pop() calls reinit_frame_cache as the last thing it does
-        which means there's currently no selected frame.  We don't need
-        to re-establish a selected frame if the dummy call returns normally,
-        that will be done by restore_inferior_status.  However, we do have
-        to handle the case where the dummy call is returning after being
-        stopped (e.g. the dummy call previously hit a breakpoint).  We
-        can't know which case we have so just always re-establish a
-        selected frame here.  */
+      /* frame_pop() calls reinit_frame_cache as the last thing it
+        does which means there's currently no selected frame.  We
+        don't need to re-establish a selected frame if the dummy call
+        returns normally, that will be done by
+        restore_infcall_control_state.  However, we do have to handle
+        the case where the dummy call is returning after being
+        stopped (e.g. the dummy call previously hit a breakpoint).
+        We can't know which case we have so just always re-establish
+        a selected frame here.  */
       select_frame (get_current_frame ());
     }
 
@@ -5539,12 +5874,12 @@ done:
       || last.kind == TARGET_WAITKIND_SIGNALLED
       || last.kind == TARGET_WAITKIND_EXITED
       || (!inferior_thread ()->step_multi
-         && !(inferior_thread ()->stop_bpstat
-              && inferior_thread ()->proceed_to_finish)
-         && !inferior_thread ()->in_infcall))
+         && !(inferior_thread ()->control.stop_bpstat
+              && inferior_thread ()->control.proceed_to_finish)
+         && !inferior_thread ()->control.in_infcall))
     {
       if (!ptid_equal (inferior_ptid, null_ptid))
-       observer_notify_normal_stop (inferior_thread ()->stop_bpstat,
+       observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat,
                                     stop_print_frame);
       else
        observer_notify_normal_stop (NULL, stop_print_frame);
@@ -5556,7 +5891,7 @@ done:
          && last.kind != TARGET_WAITKIND_EXITED)
        /* Delete the breakpoint we stopped at, if it wants to be deleted.
           Delete any breakpoint that is to be deleted at the next stop.  */
-       breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
+       breakpoint_auto_delete (inferior_thread ()->control.stop_bpstat);
     }
 
   /* Try to get rid of automatically added inferiors that are no
@@ -5590,12 +5925,29 @@ signal_pass_state (int signo)
   return signal_program[signo];
 }
 
+static void
+signal_cache_update (int signo)
+{
+  if (signo == -1)
+    {
+      for (signo = 0; signo < (int) TARGET_SIGNAL_LAST; signo++)
+       signal_cache_update (signo);
+
+      return;
+    }
+
+  signal_pass[signo] = (signal_stop[signo] == 0
+                       && signal_print[signo] == 0
+                       && signal_program[signo] == 1);
+}
+
 int
 signal_stop_update (int signo, int state)
 {
   int ret = signal_stop[signo];
 
   signal_stop[signo] = state;
+  signal_cache_update (signo);
   return ret;
 }
 
@@ -5605,6 +5957,7 @@ signal_print_update (int signo, int state)
   int ret = signal_print[signo];
 
   signal_print[signo] = state;
+  signal_cache_update (signo);
   return ret;
 }
 
@@ -5614,14 +5967,15 @@ signal_pass_update (int signo, int state)
   int ret = signal_program[signo];
 
   signal_program[signo] = state;
+  signal_cache_update (signo);
   return ret;
 }
 
 static void
 sig_print_header (void)
 {
-  printf_filtered (_("\
-Signal        Stop\tPrint\tPass to program\tDescription\n"));
+  printf_filtered (_("Signal        Stop\tPrint\tPass "
+                    "to program\tDescription\n"));
 }
 
 static void
@@ -5660,13 +6014,13 @@ handle_command (char *args, int from_tty)
       error_no_arg (_("signal to handle"));
     }
 
-  /* Allocate and zero an array of flags for which signals to handle. */
+  /* Allocate and zero an array of flags for which signals to handle.  */
 
   nsigs = (int) TARGET_SIGNAL_LAST;
   sigs = (unsigned char *) alloca (nsigs);
   memset (sigs, 0, nsigs);
 
-  /* Break the command line up into args. */
+  /* Break the command line up into args.  */
 
   argv = gdb_buildargv (args);
   old_chain = make_cleanup_freeargv (argv);
@@ -5674,7 +6028,7 @@ handle_command (char *args, int from_tty)
   /* Walk through the args, looking for signal oursigs, signal names, and
      actions.  Signal numbers and signal names may be interspersed with
      actions, with the actions being performed for all signals cumulatively
-     specified.  Signal ranges can be specified as <LOW>-<HIGH>. */
+     specified.  Signal ranges can be specified as <LOW>-<HIGH>.  */
 
   while (*argv != NULL)
     {
@@ -5688,7 +6042,7 @@ handle_command (char *args, int from_tty)
       if (wordlen >= 1 && !strncmp (*argv, "all", wordlen))
        {
          /* Apply action to all signals except those used by the
-            debugger.  Silently skip those. */
+            debugger.  Silently skip those.  */
          allsigs = 1;
          sigfirst = 0;
          siglast = nsigs - 1;
@@ -5744,7 +6098,7 @@ handle_command (char *args, int from_tty)
            }
          if (sigfirst > siglast)
            {
-             /* Bet he didn't figure we'd think of this case... */
+             /* Bet he didn't figure we'd think of this case...  */
              signum = sigfirst;
              sigfirst = siglast;
              siglast = signum;
@@ -5765,7 +6119,7 @@ handle_command (char *args, int from_tty)
        }
 
       /* If any signal numbers or symbol names were found, set flags for
-         which signals to apply actions to. */
+         which signals to apply actions to.  */
 
       for (signum = sigfirst; signum >= 0 && signum <= siglast; signum++)
        {
@@ -5776,7 +6130,8 @@ handle_command (char *args, int from_tty)
              if (!allsigs && !sigs[signum])
                {
                  if (query (_("%s is used by the debugger.\n\
-Are you sure you want to change it? "), target_signal_to_name ((enum target_signal) signum)))
+Are you sure you want to change it? "),
+                            target_signal_to_name ((enum target_signal) signum)))
                    {
                      sigs[signum] = 1;
                    }
@@ -5804,7 +6159,8 @@ Are you sure you want to change it? "), target_signal_to_name ((enum target_sign
   for (signum = 0; signum < nsigs; signum++)
     if (sigs[signum])
       {
-       target_notice_signals (inferior_ptid);
+       signal_cache_update (-1);
+       target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass);
 
        if (from_tty)
          {
@@ -5830,7 +6186,7 @@ xdb_handle_command (char *args, int from_tty)
   if (args == NULL)
     error_no_arg (_("xdb command"));
 
-  /* Break the command line up into args. */
+  /* Break the command line up into args.  */
 
   argv = gdb_buildargv (args);
   old_chain = make_cleanup_freeargv (argv);
@@ -5926,12 +6282,13 @@ signals_info (char *signum_exp, int from_tty)
        sig_print_info (oursig);
     }
 
-  printf_filtered (_("\nUse the \"handle\" command to change these tables.\n"));
+  printf_filtered (_("\nUse the \"handle\" command "
+                    "to change these tables.\n"));
 }
 
 /* The $_siginfo convenience variable is a bit special.  We don't know
    for sure the type of the value until we actually have a chance to
-   fetch the data.  The type can change depending on gdbarch, so it it
+   fetch the data.  The type can change depending on gdbarch, so it is
    also dependent on which thread you have selected.
 
      1. making $_siginfo be an internalvar that creates a new value on
@@ -6003,31 +6360,78 @@ siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var)
 }
 
 \f
-/* Inferior thread state.
-   These are details related to the inferior itself, and don't include
-   things like what frame the user had selected or what gdb was doing
-   with the target at the time.
-   For inferior function calls these are things we want to restore
-   regardless of whether the function call successfully completes
-   or the dummy frame has to be manually popped.  */
+/* infcall_suspend_state contains state about the program itself like its
+   registers and any signal it received when it last stopped.
+   This state must be restored regardless of how the inferior function call
+   ends (either successfully, or after it hits a breakpoint or signal)
+   if the program is to properly continue where it left off.  */
 
-struct inferior_thread_state
+struct infcall_suspend_state
 {
-  enum target_signal stop_signal;
+  struct thread_suspend_state thread_suspend;
+  struct inferior_suspend_state inferior_suspend;
+
+  /* Other fields:  */
   CORE_ADDR stop_pc;
   struct regcache *registers;
+
+  /* Format of SIGINFO_DATA or NULL if it is not present.  */
+  struct gdbarch *siginfo_gdbarch;
+
+  /* The inferior format depends on SIGINFO_GDBARCH and it has a length of
+     TYPE_LENGTH (gdbarch_get_siginfo_type ()).  For different gdbarch the
+     content would be invalid.  */
+  gdb_byte *siginfo_data;
 };
 
-struct inferior_thread_state *
-save_inferior_thread_state (void)
+struct infcall_suspend_state *
+save_infcall_suspend_state (void)
 {
-  struct inferior_thread_state *inf_state = XMALLOC (struct inferior_thread_state);
+  struct infcall_suspend_state *inf_state;
   struct thread_info *tp = inferior_thread ();
+  struct inferior *inf = current_inferior ();
+  struct regcache *regcache = get_current_regcache ();
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  gdb_byte *siginfo_data = NULL;
+
+  if (gdbarch_get_siginfo_type_p (gdbarch))
+    {
+      struct type *type = gdbarch_get_siginfo_type (gdbarch);
+      size_t len = TYPE_LENGTH (type);
+      struct cleanup *back_to;
+
+      siginfo_data = xmalloc (len);
+      back_to = make_cleanup (xfree, siginfo_data);
+
+      if (target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+                      siginfo_data, 0, len) == len)
+       discard_cleanups (back_to);
+      else
+       {
+         /* Errors ignored.  */
+         do_cleanups (back_to);
+         siginfo_data = NULL;
+       }
+    }
+
+  inf_state = XZALLOC (struct infcall_suspend_state);
+
+  if (siginfo_data)
+    {
+      inf_state->siginfo_gdbarch = gdbarch;
+      inf_state->siginfo_data = siginfo_data;
+    }
+
+  inf_state->thread_suspend = tp->suspend;
+  inf_state->inferior_suspend = inf->suspend;
+
+  /* run_inferior_call will not use the signal due to its `proceed' call with
+     TARGET_SIGNAL_0 anyway.  */
+  tp->suspend.stop_signal = TARGET_SIGNAL_0;
 
-  inf_state->stop_signal = tp->stop_signal;
   inf_state->stop_pc = stop_pc;
 
-  inf_state->registers = regcache_dup (get_current_regcache ());
+  inf_state->registers = regcache_dup (regcache);
 
   return inf_state;
 }
@@ -6035,103 +6439,108 @@ save_inferior_thread_state (void)
 /* Restore inferior session state to INF_STATE.  */
 
 void
-restore_inferior_thread_state (struct inferior_thread_state *inf_state)
+restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
   struct thread_info *tp = inferior_thread ();
+  struct inferior *inf = current_inferior ();
+  struct regcache *regcache = get_current_regcache ();
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
+  tp->suspend = inf_state->thread_suspend;
+  inf->suspend = inf_state->inferior_suspend;
 
-  tp->stop_signal = inf_state->stop_signal;
   stop_pc = inf_state->stop_pc;
 
+  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);
+    }
+
   /* The inferior can be gone if the user types "print exit(0)"
      (and perhaps other times).  */
   if (target_has_execution)
     /* NB: The register write goes through to the target.  */
-    regcache_cpy (get_current_regcache (), inf_state->registers);
-  regcache_xfree (inf_state->registers);
-  xfree (inf_state);
+    regcache_cpy (regcache, inf_state->registers);
+
+  discard_infcall_suspend_state (inf_state);
 }
 
 static void
-do_restore_inferior_thread_state_cleanup (void *state)
+do_restore_infcall_suspend_state_cleanup (void *state)
 {
-  restore_inferior_thread_state (state);
+  restore_infcall_suspend_state (state);
 }
 
 struct cleanup *
-make_cleanup_restore_inferior_thread_state (struct inferior_thread_state *inf_state)
+make_cleanup_restore_infcall_suspend_state
+  (struct infcall_suspend_state *inf_state)
 {
-  return make_cleanup (do_restore_inferior_thread_state_cleanup, inf_state);
+  return make_cleanup (do_restore_infcall_suspend_state_cleanup, inf_state);
 }
 
 void
-discard_inferior_thread_state (struct inferior_thread_state *inf_state)
+discard_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
   regcache_xfree (inf_state->registers);
+  xfree (inf_state->siginfo_data);
   xfree (inf_state);
 }
 
 struct regcache *
-get_inferior_thread_state_regcache (struct inferior_thread_state *inf_state)
+get_infcall_suspend_state_regcache (struct infcall_suspend_state *inf_state)
 {
   return inf_state->registers;
 }
 
-/* Session related state for inferior function calls.
-   These are the additional bits of state that need to be restored
-   when an inferior function call successfully completes.  */
+/* infcall_control_state contains state regarding gdb's control of the
+   inferior itself like stepping control.  It also contains session state like
+   the user's currently selected frame.  */
 
-struct inferior_status
+struct infcall_control_state
 {
-  bpstat stop_bpstat;
-  int stop_step;
+  struct thread_control_state thread_control;
+  struct inferior_control_state inferior_control;
+
+  /* Other fields:  */
   enum stop_stack_kind stop_stack_dummy;
   int stopped_by_random_signal;
-  int stepping_over_breakpoint;
-  CORE_ADDR step_range_start;
-  CORE_ADDR step_range_end;
-  struct frame_id step_frame_id;
-  struct frame_id step_stack_frame_id;
-  enum step_over_calls_kind step_over_calls;
-  CORE_ADDR step_resume_break_address;
   int stop_after_trap;
-  int stop_soon;
 
   /* ID if the selected frame when the inferior function call was made.  */
   struct frame_id selected_frame_id;
-
-  int proceed_to_finish;
-  int in_infcall;
 };
 
 /* Save all of the information associated with the inferior<==>gdb
    connection.  */
 
-struct inferior_status *
-save_inferior_status (void)
+struct infcall_control_state *
+save_infcall_control_state (void)
 {
-  struct inferior_status *inf_status = XMALLOC (struct inferior_status);
+  struct infcall_control_state *inf_status = xmalloc (sizeof (*inf_status));
   struct thread_info *tp = inferior_thread ();
   struct inferior *inf = current_inferior ();
 
-  inf_status->stop_step = tp->stop_step;
+  inf_status->thread_control = tp->control;
+  inf_status->inferior_control = inf->control;
+
+  tp->control.step_resume_breakpoint = NULL;
+  tp->control.exception_resume_breakpoint = NULL;
+
+  /* Save original bpstat chain to INF_STATUS; replace it in TP with copy of
+     chain.  If caller's caller is walking the chain, they'll be happier if we
+     hand them back the original chain when restore_infcall_control_state is
+     called.  */
+  tp->control.stop_bpstat = bpstat_copy (tp->control.stop_bpstat);
+
+  /* Other fields:  */
   inf_status->stop_stack_dummy = stop_stack_dummy;
   inf_status->stopped_by_random_signal = stopped_by_random_signal;
-  inf_status->stepping_over_breakpoint = tp->trap_expected;
-  inf_status->step_range_start = tp->step_range_start;
-  inf_status->step_range_end = tp->step_range_end;
-  inf_status->step_frame_id = tp->step_frame_id;
-  inf_status->step_stack_frame_id = tp->step_stack_frame_id;
-  inf_status->step_over_calls = tp->step_over_calls;
   inf_status->stop_after_trap = stop_after_trap;
-  inf_status->stop_soon = inf->stop_soon;
-  /* Save original bpstat chain here; replace it with copy of chain.
-     If caller's caller is walking the chain, they'll be happier if we
-     hand them back the original chain when restore_inferior_status is
-     called.  */
-  inf_status->stop_bpstat = tp->stop_bpstat;
-  tp->stop_bpstat = bpstat_copy (tp->stop_bpstat);
-  inf_status->proceed_to_finish = tp->proceed_to_finish;
-  inf_status->in_infcall = tp->in_infcall;
 
   inf_status->selected_frame_id = get_frame_id (get_selected_frame (NULL));
 
@@ -6162,27 +6571,28 @@ restore_selected_frame (void *args)
 /* Restore inferior session state to INF_STATUS.  */
 
 void
-restore_inferior_status (struct inferior_status *inf_status)
+restore_infcall_control_state (struct infcall_control_state *inf_status)
 {
   struct thread_info *tp = inferior_thread ();
   struct inferior *inf = current_inferior ();
 
-  tp->stop_step = inf_status->stop_step;
+  if (tp->control.step_resume_breakpoint)
+    tp->control.step_resume_breakpoint->disposition = disp_del_at_next_stop;
+
+  if (tp->control.exception_resume_breakpoint)
+    tp->control.exception_resume_breakpoint->disposition
+      = disp_del_at_next_stop;
+
+  /* Handle the bpstat_copy of the chain.  */
+  bpstat_clear (&tp->control.stop_bpstat);
+
+  tp->control = inf_status->thread_control;
+  inf->control = inf_status->inferior_control;
+
+  /* Other fields:  */
   stop_stack_dummy = inf_status->stop_stack_dummy;
   stopped_by_random_signal = inf_status->stopped_by_random_signal;
-  tp->trap_expected = inf_status->stepping_over_breakpoint;
-  tp->step_range_start = inf_status->step_range_start;
-  tp->step_range_end = inf_status->step_range_end;
-  tp->step_frame_id = inf_status->step_frame_id;
-  tp->step_stack_frame_id = inf_status->step_stack_frame_id;
-  tp->step_over_calls = inf_status->step_over_calls;
   stop_after_trap = inf_status->stop_after_trap;
-  inf->stop_soon = inf_status->stop_soon;
-  bpstat_clear (&tp->stop_bpstat);
-  tp->stop_bpstat = inf_status->stop_bpstat;
-  inf_status->stop_bpstat = NULL;
-  tp->proceed_to_finish = inf_status->proceed_to_finish;
-  tp->in_infcall = inf_status->in_infcall;
 
   if (target_has_stack)
     {
@@ -6202,22 +6612,32 @@ restore_inferior_status (struct inferior_status *inf_status)
 }
 
 static void
-do_restore_inferior_status_cleanup (void *sts)
+do_restore_infcall_control_state_cleanup (void *sts)
 {
-  restore_inferior_status (sts);
+  restore_infcall_control_state (sts);
 }
 
 struct cleanup *
-make_cleanup_restore_inferior_status (struct inferior_status *inf_status)
+make_cleanup_restore_infcall_control_state
+  (struct infcall_control_state *inf_status)
 {
-  return make_cleanup (do_restore_inferior_status_cleanup, inf_status);
+  return make_cleanup (do_restore_infcall_control_state_cleanup, inf_status);
 }
 
 void
-discard_inferior_status (struct inferior_status *inf_status)
+discard_infcall_control_state (struct infcall_control_state *inf_status)
 {
-  /* See save_inferior_status for info on stop_bpstat. */
-  bpstat_clear (&inf_status->stop_bpstat);
+  if (inf_status->thread_control.step_resume_breakpoint)
+    inf_status->thread_control.step_resume_breakpoint->disposition
+      = disp_del_at_next_stop;
+
+  if (inf_status->thread_control.exception_resume_breakpoint)
+    inf_status->thread_control.exception_resume_breakpoint->disposition
+      = disp_del_at_next_stop;
+
+  /* See save_infcall_control_state for info on stop_bpstat.  */
+  bpstat_clear (&inf_status->thread_control.stop_bpstat);
+
   xfree (inf_status);
 }
 \f
@@ -6368,11 +6788,6 @@ ptid_is_pid (ptid_t ptid)
 int
 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)
-             && !ptid_equal (ptid, null_ptid));
-
   if (ptid_equal (filter, minus_one_ptid))
     return 1;
   if (ptid_is_pid (filter)
@@ -6457,8 +6872,8 @@ show_exec_direction_func (struct ui_file *out, int from_tty,
     break;
   case EXEC_ERROR:
   default:
-    fprintf_filtered (out, 
-                     _("Forward (target `%s' does not support exec-direction).\n"),
+    fprintf_filtered (out, _("Forward (target `%s' does not "
+                            "support exec-direction).\n"),
                      target_shortname);
     break;
   }
@@ -6494,8 +6909,8 @@ static void
 show_schedule_multiple (struct ui_file *file, int from_tty,
                        struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Resuming the execution of threads of all processes is %s.\n"), value);
+  fprintf_filtered (file, _("Resuming the execution of threads "
+                           "of all processes is %s.\n"), value);
 }
 
 void
@@ -6562,7 +6977,8 @@ When non-zero, inferior specific debugging is enabled."),
                            show_debug_infrun,
                            &setdebuglist, &showdebuglist);
 
-  add_setshow_boolean_cmd ("displaced", class_maintenance, &debug_displaced, _("\
+  add_setshow_boolean_cmd ("displaced", class_maintenance,
+                          &debug_displaced, _("\
 Set displaced stepping debugging."), _("\
 Show displaced stepping debugging."), _("\
 When non-zero, displaced stepping specific debugging is enabled."),
@@ -6596,6 +7012,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_pass = (unsigned char *)
+    xmalloc (sizeof (signal_program[0]) * numsigs);
   for (i = 0; i < numsigs; i++)
     {
       signal_stop[i] = 1;
@@ -6625,6 +7043,8 @@ leave it stopped or free to run as needed."),
   signal_print[TARGET_SIGNAL_URG] = 0;
   signal_stop[TARGET_SIGNAL_WINCH] = 0;
   signal_print[TARGET_SIGNAL_WINCH] = 0;
+  signal_stop[TARGET_SIGNAL_PRIO] = 0;
+  signal_print[TARGET_SIGNAL_PRIO] = 0;
 
   /* These signals are used internally by user-level thread
      implementations.  (See signal(5) on Solaris.)  Like the above
@@ -6637,6 +7057,9 @@ leave it stopped or free to run as needed."),
   signal_stop[TARGET_SIGNAL_CANCEL] = 0;
   signal_print[TARGET_SIGNAL_CANCEL] = 0;
 
+  /* Update cached state.  */
+  signal_cache_update (-1);
+
   add_setshow_zinteger_cmd ("stop-on-solib-events", class_support,
                            &stop_on_solib_events, _("\
 Set stopping for shared library events."), _("\
This page took 0.074547 seconds and 4 git commands to generate.