Fix compile time warning messages.
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 1527ed93607b71bfbe8e439da90c313aceacee85..d6075770ac6ec9ce92092788651a40df4bc449a2 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-struct-independent code to start (run) and stop an inferior process.
-   Copyright 1986-1989, 1991-1999 Free Software Foundation, Inc.
+   Copyright 1986-1989, 1991-2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -25,7 +25,7 @@
 #include "frame.h"
 #include "inferior.h"
 #include "breakpoint.h"
-#include "wait.h"
+#include "gdb_wait.h"
 #include "gdbcore.h"
 #include "gdbcmd.h"
 #include "target.h"
@@ -34,7 +34,7 @@
 #include "symfile.h"           /* for overlay functions */
 #include "top.h"
 #include <signal.h>
-#include "event-loop.h"
+#include "inf-loop.h"
 
 /* Prototypes for local functions */
 
@@ -46,7 +46,7 @@ static void sig_print_info (enum target_signal);
 
 static void sig_print_header (void);
 
-static void resume_cleanups (int);
+static void resume_cleanups (void *);
 
 static int hook_stop_stub (void *);
 
@@ -55,8 +55,6 @@ static void delete_breakpoint_current_contents (void *);
 static void set_follow_fork_mode_command (char *arg, int from_tty,
                                          struct cmd_list_element * c);
 
-static void complete_execution (void);
-
 static struct inferior_status *xmalloc_inferior_status (void);
 
 static void free_inferior_status (struct inferior_status *);
@@ -75,10 +73,6 @@ static void follow_vfork (int parent_pid, int child_pid);
 static void set_schedlock_func (char *args, int from_tty,
                                struct cmd_list_element * c);
 
-static int is_internal_shlib_eventpoint (struct breakpoint * ep);
-
-static int stopped_for_internal_shlib_event (bpstat bs);
-
 struct execution_control_state;
 
 static int currently_stepping (struct execution_control_state *ecs);
@@ -98,17 +92,7 @@ int sync_execution = 0;
    when the inferior stopped in a different thread than it had been
    running in.  */
 
-static int switched_from_inferior_pid;
-
-/* This will be true for configurations that may actually report an
-   inferior pid different from the original.  At present this is only
-   true for HP-UX native.  */
-
-#ifndef MAY_SWITCH_FROM_INFERIOR_PID
-#define MAY_SWITCH_FROM_INFERIOR_PID (0)
-#endif
-
-static int may_switch_from_inferior_pid = MAY_SWITCH_FROM_INFERIOR_PID;
+static int previous_inferior_pid;
 
 /* This is true for configurations that may follow through execl() and
    similar functions.  At present this is only true for HP-UX native.  */
@@ -176,15 +160,53 @@ static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
 #define DYNAMIC_TRAMPOLINE_NEXTPC(pc) 0
 #endif
 
-/* On SVR4 based systems, determining the callee's address is exceedingly
-   difficult and depends on the implementation of the run time loader.
-   If we are stepping at the source level, we single step until we exit
-   the run time loader code and reach the callee's address.  */
+/* If the program uses ELF-style shared libraries, then calls to
+   functions in shared libraries go through stubs, which live in a
+   table called the PLT (Procedure Linkage Table).  The first time the
+   function is called, the stub sends control to the dynamic linker,
+   which looks up the function's real address, patches the stub so
+   that future calls will go directly to the function, and then passes
+   control to the function.
+
+   If we are stepping at the source level, we don't want to see any of
+   this --- we just want to skip over the stub and the dynamic linker.
+   The simple approach is to single-step until control leaves the
+   dynamic linker.
+
+   However, on some systems (e.g., Red Hat Linux 5.2) the dynamic
+   linker calls functions in the shared C library, so you can't tell
+   from the PC alone whether the dynamic linker is still running.  In
+   this case, we use a step-resume breakpoint to get us past the
+   dynamic linker, as if we were using "next" to step over a function
+   call.
+
+   IN_SOLIB_DYNSYM_RESOLVE_CODE says whether we're in the dynamic
+   linker code or not.  Normally, this means we single-step.  However,
+   if SKIP_SOLIB_RESOLVER then returns non-zero, then its value is an
+   address where we can place a step-resume breakpoint to get past the
+   linker's symbol resolution function.
+
+   IN_SOLIB_DYNSYM_RESOLVE_CODE can generally be implemented in a
+   pretty portable way, by comparing the PC against the address ranges
+   of the dynamic linker's sections.
+
+   SKIP_SOLIB_RESOLVER is generally going to be system-specific, since
+   it depends on internal details of the dynamic linker.  It's usually
+   not too hard to figure out where to put a breakpoint, but it
+   certainly isn't portable.  SKIP_SOLIB_RESOLVER should do plenty of
+   sanity checking.  If it can't figure things out, returning zero and
+   getting the (possibly confusing) stepping behavior is better than
+   signalling an error, which will obscure the change in the
+   inferior's state.  */
 
 #ifndef IN_SOLIB_DYNSYM_RESOLVE_CODE
 #define IN_SOLIB_DYNSYM_RESOLVE_CODE(pc) 0
 #endif
 
+#ifndef SKIP_SOLIB_RESOLVER
+#define SKIP_SOLIB_RESOLVER(pc) 0
+#endif
+
 /* For SVR4 shared libraries, each call goes through a small piece of
    trampoline code in the ".plt" section.  IN_SOLIB_CALL_TRAMPOLINE evaluates
    to nonzero if we are current stopped in one of these. */
@@ -230,6 +252,26 @@ static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
 #define INSTRUCTION_NULLIFIED 0
 #endif
 
+/* We can't step off a permanent breakpoint in the ordinary way, because we
+   can't remove it.  Instead, we have to advance the PC to the next
+   instruction.  This macro should expand to a pointer to a function that
+   does that, or zero if we have no such function.  If we don't have a
+   definition for it, we have to report an error.  */
+#ifndef SKIP_PERMANENT_BREAKPOINT 
+#define SKIP_PERMANENT_BREAKPOINT (default_skip_permanent_breakpoint)
+static void
+default_skip_permanent_breakpoint (void)
+{
+  error_begin ();
+  fprintf_filtered (gdb_stderr, "\
+The program is stopped at a permanent breakpoint, but GDB does not know\n\
+how to step past a permanent breakpoint on this architecture.  Try using\n\
+a command like `return' or `jump' to continue execution.\n");
+  return_to_top_level (RETURN_ERROR);
+}
+#endif
+   
+
 /* Convert the #defines into values.  This is temporary until wfi control
    flow is completely sorted out.  */
 
@@ -254,6 +296,13 @@ static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
 #define HAVE_CONTINUABLE_WATCHPOINT 1
 #endif
 
+#ifndef CANNOT_STEP_HW_WATCHPOINTS
+#define CANNOT_STEP_HW_WATCHPOINTS 0
+#else
+#undef  CANNOT_STEP_HW_WATCHPOINTS
+#define CANNOT_STEP_HW_WATCHPOINTS 1
+#endif
+
 /* Tables of how to react to signals; the user sets them.  */
 
 static unsigned char *signal_stop;
@@ -387,13 +436,13 @@ static int follow_vfork_when_exec;
 
 static char *follow_fork_mode_kind_names[] =
 {
-/* ??rehrauer:  The "both" option is broken, by what may be a 10.20
-   kernel problem.  It's also not terribly useful without a GUI to
-   help the user drive two debuggers.  So for now, I'm disabling
-   the "both" option.
-   "parent", "child", "both", "ask" };
- */
-  "parent", "child", "ask"};
+  /* ??rehrauer: The "both" option is broken, by what may be a 10.20
+     kernel problem.  It's also not terribly useful without a GUI to
+     help the user drive two debuggers.  So for now, I'm disabling the
+     "both" option. */
+  /* "parent", "child", "both", "ask" */
+  "parent", "child", "ask", NULL
+};
 
 static char *follow_fork_mode_string = NULL;
 \f
@@ -703,7 +752,7 @@ static int singlestep_breakpoints_inserted_p = 0;
 /* Things to clean up if we QUIT out of resume ().  */
 /* ARGSUSED */
 static void
-resume_cleanups (int arg)
+resume_cleanups (void *ignore)
 {
   normal_stop ();
 }
@@ -713,7 +762,12 @@ static char schedlock_on[] = "on";
 static char schedlock_step[] = "step";
 static char *scheduler_mode = schedlock_off;
 static char *scheduler_enums[] =
-{schedlock_off, schedlock_on, schedlock_step};
+{
+  schedlock_off,
+  schedlock_on,
+  schedlock_step,
+  NULL
+};
 
 static void
 set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
@@ -728,6 +782,8 @@ set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
 }
 
 
+
+
 /* Resume the inferior, but allow a QUIT.  This is useful if the user
    wants to interrupt some lengthy single-stepping operation
    (for child processes, the SIGINT goes to the inferior, and so
@@ -740,8 +796,7 @@ void
 resume (int step, enum target_signal sig)
 {
   int should_resume = 1;
-  struct cleanup *old_cleanups = make_cleanup ((make_cleanup_func)
-                                              resume_cleanups, 0);
+  struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
   QUIT;
 
 #ifdef CANNOT_STEP_BREAKPOINT
@@ -752,6 +807,25 @@ resume (int step, enum target_signal sig)
     step = 0;
 #endif
 
+  /* Some targets (e.g. Solaris x86) have a kernel bug when stepping
+     over an instruction that causes a page fault without triggering
+     a hardware watchpoint. The kernel properly notices that it shouldn't
+     stop, because the hardware watchpoint is not triggered, but it forgets
+     the step request and continues the program normally.
+     Work around the problem by removing hardware watchpoints if a step is
+     requested, GDB will check for a hardware watchpoint trigger after the
+     step anyway.  */
+  if (CANNOT_STEP_HW_WATCHPOINTS && step && breakpoints_inserted)
+    remove_hw_watchpoints ();
+     
+
+  /* Normally, by the time we reach `resume', the breakpoints are either
+     removed or inserted, as appropriate.  The exception is if we're sitting
+     at a permanent breakpoint; we need to step over it, but permanent
+     breakpoints can't be removed.  So we have to test for it here.  */
+  if (breakpoint_here_p (read_pc ()) == permanent_breakpoint_here)
+    SKIP_PERMANENT_BREAKPOINT ();
+
   if (SOFTWARE_SINGLE_STEP_P && step)
     {
       /* Do it the hard way, w/temp breakpoints */
@@ -810,6 +884,8 @@ resume (int step, enum target_signal sig)
 
   if (should_resume)
     {
+      int resume_pid;
+
       if (use_thread_step_needed && thread_step_needed)
        {
          /* We stopped on a BPT instruction;
@@ -821,7 +897,7 @@ resume (int step, enum target_signal sig)
            {
              /* Breakpoint deleted: ok to do regular resume
                 where all the threads either step or continue. */
-             target_resume (-1, step, sig);
+             resume_pid = -1;
            }
          else
            {
@@ -833,20 +909,19 @@ resume (int step, enum target_signal sig)
                  trap_expected = 1;
                  step = 1;
                }
-
-             target_resume (inferior_pid, step, sig);
+             resume_pid = inferior_pid;
            }
        }
       else
        {
          /* Vanilla resume. */
-
          if ((scheduler_mode == schedlock_on) ||
              (scheduler_mode == schedlock_step && step != 0))
-           target_resume (inferior_pid, step, sig);
+           resume_pid = inferior_pid;
          else
-           target_resume (-1, step, sig);
+           resume_pid = -1;
        }
+      target_resume (resume_pid, step, sig);
     }
 
   discard_cleanups (old_cleanups);
@@ -895,7 +970,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   if (step < 0)
     stop_after_trap = 1;
 
-  if (addr == (CORE_ADDR) - 1)
+  if (addr == (CORE_ADDR) -1)
     {
       /* If there is a breakpoint at the address we will resume at,
          step one instruction before inserting breakpoints
@@ -973,9 +1048,11 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
       int temp = insert_breakpoints ();
       if (temp)
        {
-         print_sys_errmsg ("ptrace", temp);
+         print_sys_errmsg ("insert_breakpoints", temp);
          error ("Cannot insert breakpoints.\n\
-The same program may be running in another process.");
+The same program may be running in another process,\n\
+or you may have requested too many hardware\n\
+breakpoints and/or watchpoints.\n");
        }
 
       breakpoints_inserted = 1;
@@ -1001,7 +1078,7 @@ The same program may be running in another process.");
      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. */
-  if (!async_p || !target_has_async)
+  if (!event_loop_p || !target_can_async_p ())
     {
       wait_for_inferior ();
       normal_stop ();
@@ -1027,23 +1104,22 @@ start_remote (void)
   stop_soon_quietly = 1;
   trap_expected = 0;
 
-  /* Go on waiting only in case gdb is not started in async mode, or
-     in case the target doesn't support async execution. */
-  if (!async_p || !target_has_async)
-    {
-      wait_for_inferior ();
-      normal_stop ();
-    }
-  else
-    {
-      /* The 'tar rem' command should always look synchronous,
-         i.e. display the prompt only once it has connected and
-         started the target. */
-      sync_execution = 1;
-      push_prompt ("", "", "");
-      delete_file_handler (input_fd);
-      target_executing = 1;
-    }
+  /* Always go on waiting for the target, regardless of the mode. */
+  /* FIXME: cagney/1999-09-23: At present it isn't possible to
+     indicate th 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. */
+  /* 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 ();
+  normal_stop ();
 }
 
 /* Initialize static vars when a new inferior begins.  */
@@ -1100,6 +1176,24 @@ 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
+{
+  /* We don't know why. */
+  STOP_UNKNOWN,
+  /* Step, next, nexti, stepi finished. */
+  END_STEPPING_RANGE,
+  /* Found breakpoint. */
+  BREAKPOINT_HIT,
+  /* Inferior terminated by signal. */
+  SIGNAL_EXITED,
+  /* Inferior exited. */
+  EXITED,
+  /* Inferior received signal, and user asked to be notified. */
+  SIGNAL_RECEIVED
+};
+
 /* This structure contains what used to be local variables in
    wait_for_inferior.  Probably many of them can return to being
    locals in handle_inferior_event.  */
@@ -1137,8 +1231,12 @@ void init_execution_control_state (struct execution_control_state * ecs);
 void handle_inferior_event (struct execution_control_state * ecs);
 
 static void check_sigtramp2 (struct execution_control_state *ecs);
+static void step_into_function (struct execution_control_state *ecs);
+static void step_over_function (struct execution_control_state *ecs);
 static void stop_stepping (struct execution_control_state *ecs);
 static void prepare_to_wait (struct execution_control_state *ecs);
+static void keep_going (struct execution_control_state *ecs);
+static void print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info);
 
 /* Wait for control to return from inferior to debugger.
    If inferior gets a signal, we may decide to start it up again
@@ -1168,8 +1266,7 @@ wait_for_inferior (void)
   thread_step_needed = 0;
 
   /* We'll update this if & when we switch to a new thread. */
-  if (may_switch_from_inferior_pid)
-    switched_from_inferior_pid = inferior_pid;
+  previous_inferior_pid = inferior_pid;
 
   overlay_cache_invalid = 1;
 
@@ -1210,7 +1307,8 @@ struct execution_control_state async_ecss;
 struct execution_control_state *async_ecs;
 
 void
-fetch_inferior_event (void)
+fetch_inferior_event (client_data)
+     void *client_data;
 {
   static struct cleanup *old_cleanups;
 
@@ -1229,8 +1327,7 @@ fetch_inferior_event (void)
       thread_step_needed = 0;
 
       /* We'll update this if & when we switch to a new thread. */
-      if (may_switch_from_inferior_pid)
-       switched_from_inferior_pid = inferior_pid;
+      previous_inferior_pid = inferior_pid;
 
       overlay_cache_invalid = 1;
 
@@ -1258,11 +1355,10 @@ fetch_inferior_event (void)
         if there are any. */
       do_exec_cleanups (old_cleanups);
       normal_stop ();
-      /* Is there anything left to do for the command issued to
-         complete? */
-      do_all_continuations ();
-      /* Reset things after target has stopped for the async commands. */
-      complete_execution ();
+      if (step_multi && stop_step)
+       inferior_event_handler (INF_EXEC_CONTINUE, NULL);
+      else
+       inferior_event_handler (INF_EXEC_COMPLETE, NULL);
     }
 }
 
@@ -1272,6 +1368,7 @@ fetch_inferior_event (void)
 void
 init_execution_control_state (struct execution_control_state *ecs)
 {
+  /* ecs->another_trap? */
   ecs->random_signal = 0;
   ecs->remove_breakpoints_on_following_step = 0;
   ecs->handling_longjmp = 0;   /* FIXME */
@@ -1370,7 +1467,13 @@ handle_inferior_event (struct execution_control_state *ecs)
       {
        add_thread (ecs->pid);
 
+#ifdef UI_OUT
+       ui_out_text (uiout, "[New ");
+       ui_out_text (uiout, target_pid_or_tid_to_str (ecs->pid));
+       ui_out_text (uiout, "]\n");
+#else
        printf_filtered ("[New %s]\n", target_pid_or_tid_to_str (ecs->pid));
+#endif
 
 #if 0
        /* NOTE: This block is ONLY meant to be invoked in case of a
@@ -1439,12 +1542,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       case TARGET_WAITKIND_EXITED:
        target_terminal_ours ();        /* Must do this before mourn anyway */
-       annotate_exited (ecs->ws.value.integer);
-       if (ecs->ws.value.integer)
-         printf_filtered ("\nProgram exited with code 0%o.\n",
-                          (unsigned int) ecs->ws.value.integer);
-       else
-         printf_filtered ("\nProgram exited normally.\n");
+       print_stop_reason (EXITED, ecs->ws.value.integer);
 
        /* Record the exit code in the convenience variable $_exitcode, so
           that the user can inspect this again later.  */
@@ -1462,27 +1560,15 @@ handle_inferior_event (struct execution_control_state *ecs)
        stop_print_frame = 0;
        stop_signal = ecs->ws.value.sig;
        target_terminal_ours ();        /* Must do this before mourn anyway */
-       annotate_signalled ();
-
-       /* This looks pretty bogus to me.  Doesn't TARGET_WAITKIND_SIGNALLED
-          mean it is already dead?  This has been here since GDB 2.8, so
-          perhaps it means rms didn't understand unix waitstatuses?
-          For the moment I'm just kludging around this in remote.c
-          rather than trying to change it here --kingdon, 5 Dec 1994.  */
-       target_kill ();         /* kill mourns as well */
-
-       printf_filtered ("\nProgram terminated with signal ");
-       annotate_signal_name ();
-       printf_filtered ("%s", target_signal_to_name (stop_signal));
-       annotate_signal_name_end ();
-       printf_filtered (", ");
-       annotate_signal_string ();
-       printf_filtered ("%s", target_signal_to_string (stop_signal));
-       annotate_signal_string_end ();
-       printf_filtered (".\n");
-
-       printf_filtered ("The program no longer exists.\n");
-       gdb_flush (gdb_stdout);
+
+       /* Note: By definition of TARGET_WAITKIND_SIGNALLED, we shouldn't
+          reach here unless the inferior is dead.  However, for years
+          target_kill() was called here, which hints that fatal signals aren't
+          really fatal on some systems.  If that's true, then some changes
+          may be needed. */
+       target_mourn_inferior ();
+
+       print_stop_reason (SIGNAL_EXITED, stop_signal);
        singlestep_breakpoints_inserted_p = 0;  /*SOFTWARE_SINGLE_STEP_P */
        stop_stepping (ecs);
        return;
@@ -1515,13 +1601,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        stop_pc = read_pc_pid (ecs->pid);
        ecs->saved_inferior_pid = inferior_pid;
        inferior_pid = ecs->pid;
-       stop_bpstat = bpstat_stop_status
-         (&stop_pc,
-          (DECR_PC_AFTER_BREAK ?
-           (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
-            && currently_stepping (ecs))
-           : 0)
-         );
+       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        inferior_pid = ecs->saved_inferior_pid;
        goto process_event_stop_test;
@@ -1569,13 +1649,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          }
 
        stop_pc = read_pc ();
-       stop_bpstat = bpstat_stop_status
-         (&stop_pc,
-          (DECR_PC_AFTER_BREAK ?
-           (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
-            && currently_stepping (ecs))
-           : 0)
-         );
+       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        goto process_event_stop_test;
 
@@ -1640,13 +1714,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        stop_pc = read_pc_pid (ecs->pid);
        ecs->saved_inferior_pid = inferior_pid;
        inferior_pid = ecs->pid;
-       stop_bpstat = bpstat_stop_status
-         (&stop_pc,
-          (DECR_PC_AFTER_BREAK ?
-           (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
-            && currently_stepping (ecs))
-           : 0)
-         );
+       stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
        ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
        inferior_pid = ecs->saved_inferior_pid;
        goto process_event_stop_test;
@@ -1707,6 +1775,17 @@ handle_inferior_event (struct execution_control_state *ecs)
       case TARGET_WAITKIND_STOPPED:
        stop_signal = ecs->ws.value.sig;
        break;
+
+       /* We had an event in the inferior, but we are not interested
+          in handling it at this level. The lower layers have already
+          done what needs to be done, if anything. This case can
+          occur only when the target is async or extended-async. One
+          of the circumstamces for this to happen is when the
+          inferior produces output for the console. The inferior has
+          not stopped, and we are ignoring the event. */
+      case TARGET_WAITKIND_IGNORE:
+       ecs->wait_some_more = 1;
+       return;
       }
 
     /* We may want to consider not doing a resume here in order to give
@@ -1853,39 +1932,44 @@ handle_inferior_event (struct execution_control_state *ecs)
        /* It's a SIGTRAP or a signal we're interested in.  Switch threads,
           and fall into the rest of wait_for_inferior().  */
 
-       /* Save infrun state for the old thread.  */
-       save_infrun_state (inferior_pid, prev_pc,
-                          prev_func_start, prev_func_name,
-                          trap_expected, step_resume_breakpoint,
-                          through_sigtramp_breakpoint,
-                          step_range_start, step_range_end,
-                          step_frame_address, ecs->handling_longjmp,
-                          ecs->another_trap,
-                          ecs->stepping_through_solib_after_catch,
-                          ecs->stepping_through_solib_catchpoints,
-                          ecs->stepping_through_sigtramp);
-
-       if (may_switch_from_inferior_pid)
-         switched_from_inferior_pid = inferior_pid;
+       /* Caution: it may happen that the new thread (or the old one!)
+          is not in the thread list.  In this case we must not attempt
+          to "switch context", or we run the risk that our context may
+          be lost.  This may happen as a result of the target module
+          mishandling thread creation.  */
+
+       if (in_thread_list (inferior_pid) && in_thread_list (ecs->pid))
+         { /* Perform infrun state context switch: */
+           /* Save infrun state for the old thread.  */
+           save_infrun_state (inferior_pid, prev_pc,
+                              prev_func_start, prev_func_name,
+                              trap_expected, step_resume_breakpoint,
+                              through_sigtramp_breakpoint,
+                              step_range_start, step_range_end,
+                              step_frame_address, ecs->handling_longjmp,
+                              ecs->another_trap,
+                              ecs->stepping_through_solib_after_catch,
+                              ecs->stepping_through_solib_catchpoints,
+                              ecs->stepping_through_sigtramp);
+
+           /* Load infrun state for the new thread.  */
+           load_infrun_state (ecs->pid, &prev_pc,
+                              &prev_func_start, &prev_func_name,
+                              &trap_expected, &step_resume_breakpoint,
+                              &through_sigtramp_breakpoint,
+                              &step_range_start, &step_range_end,
+                              &step_frame_address, &ecs->handling_longjmp,
+                              &ecs->another_trap,
+                              &ecs->stepping_through_solib_after_catch,
+                              &ecs->stepping_through_solib_catchpoints,
+                              &ecs->stepping_through_sigtramp);
+         }
 
        inferior_pid = ecs->pid;
 
-       /* Load infrun state for the new thread.  */
-       load_infrun_state (inferior_pid, &prev_pc,
-                          &prev_func_start, &prev_func_name,
-                          &trap_expected, &step_resume_breakpoint,
-                          &through_sigtramp_breakpoint,
-                          &step_range_start, &step_range_end,
-                          &step_frame_address, &ecs->handling_longjmp,
-                          &ecs->another_trap,
-                          &ecs->stepping_through_solib_after_catch,
-                          &ecs->stepping_through_solib_catchpoints,
-                          &ecs->stepping_through_sigtramp);
-
        if (context_hook)
          context_hook (pid_to_thread_id (ecs->pid));
 
-       printf_filtered ("[Switching to %s]\n", target_pid_to_str (ecs->pid));
        flush_cached_frames ();
       }
 
@@ -2032,22 +2116,15 @@ handle_inferior_event (struct execution_control_state *ecs)
            /* See if there is a breakpoint at the current PC.  */
            stop_bpstat = bpstat_stop_status
              (&stop_pc,
-              (DECR_PC_AFTER_BREAK ?
-           /* Notice the case of stepping through a jump
-              that lands just after a breakpoint.
-              Don't confuse that with hitting the breakpoint.
-              What we check for is that 1) stepping is going on
-              and 2) the pc before the last insn does not match
-              the address of the breakpoint before the current pc
-              and 3) we didn't hit a breakpoint in a signal handler
-              without an intervening stop in sigtramp, which is
-              detected by a new stack pointer value below
-              any usual function calling stack adjustments.  */
+           /* Pass TRUE if our reason for stopping is something other
+              than hitting a breakpoint.  We do this by checking that
+              1) stepping is going on and 2) we didn't hit a breakpoint
+              in a signal handler without an intervening stop in
+              sigtramp, which is detected by a new stack pointer value
+              below any usual function calling stack adjustments.  */
                (currently_stepping (ecs)
-                && prev_pc != stop_pc - DECR_PC_AFTER_BREAK
                 && !(step_range_end
-                     && INNER_THAN (read_sp (), (step_sp - 16)))) :
-               0)
+                     && INNER_THAN (read_sp (), (step_sp - 16))))
              );
            /* Following in case break condition called a
               function.  */
@@ -2108,15 +2185,17 @@ handle_inferior_event (struct execution_control_state *ecs)
          {
            trap_expected = 1;
            stop_signal = TARGET_SIGNAL_0;
-           goto keep_going;
+           keep_going (ecs);
+           return;
          }
       }
     else if (ecs->ws.kind == TARGET_WAITKIND_VFORKED)
       {
        if (ecs->random_signal) /* I.e., no catchpoint triggered for this. */
          {
-           stop_signal = TARGET_SIGNAL_0;
-           goto keep_going;
+           stop_signal = TARGET_SIGNAL_0;      
+           keep_going (ecs);
+           return;
          }
       }
     else if (ecs->ws.kind == TARGET_WAITKIND_EXECD)
@@ -2126,7 +2205,8 @@ handle_inferior_event (struct execution_control_state *ecs)
          {
            trap_expected = 1;
            stop_signal = TARGET_SIGNAL_0;
-           goto keep_going;
+           keep_going (ecs);
+           return;
          }
       }
 
@@ -2144,17 +2224,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          {
            printed = 1;
            target_terminal_ours_for_output ();
-           annotate_signal ();
-           printf_filtered ("\nProgram received signal ");
-           annotate_signal_name ();
-           printf_filtered ("%s", target_signal_to_name (stop_signal));
-           annotate_signal_name_end ();
-           printf_filtered (", ");
-           annotate_signal_string ();
-           printf_filtered ("%s", target_signal_to_string (stop_signal));
-           annotate_signal_string_end ();
-           printf_filtered (".\n");
-           gdb_flush (gdb_stdout);
+           print_stop_reason (SIGNAL_RECEIVED, stop_signal);
          }
        if (signal_stop[stop_signal])
          {
@@ -2182,7 +2252,7 @@ handle_inferior_event (struct execution_control_state *ecs)
           that case, when we reach this point, there is already a
           step-resume breakpoint established, right where it should be:
           immediately after the function call the user is "next"-ing
-          over.  If we jump to step_over_function now, two bad things
+          over.  If we call step_over_function now, two bad things
           happen:
 
           - we'll create a new breakpoint, at wherever the current
@@ -2203,6 +2273,8 @@ handle_inferior_event (struct execution_control_state *ecs)
            the HP-UX maintainer to furnish a fix that doesn't break other
            platforms.  --JimB, 20 May 1999 */
        check_sigtramp2 (ecs);
+       keep_going (ecs);
+       return;
       }
 
     /* Handle cases caused by hitting a breakpoint.  */
@@ -2230,7 +2302,10 @@ handle_inferior_event (struct execution_control_state *ecs)
          remove_breakpoints ();
          breakpoints_inserted = 0;
          if (!GET_LONGJMP_TARGET (&jmp_buf_pc))
-           goto keep_going;
+           {
+             keep_going (ecs);
+             return;
+           }
 
          /* Need to blow away step-resume breakpoint, as it
             interferes with us */
@@ -2256,7 +2331,8 @@ handle_inferior_event (struct execution_control_state *ecs)
 #endif /* 0 */
            set_longjmp_resume_breakpoint (jmp_buf_pc, NULL);
          ecs->handling_longjmp = 1;    /* FIXME */
-         goto keep_going;
+         keep_going (ecs);
+         return;
 
        case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
        case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE:
@@ -2269,7 +2345,8 @@ handle_inferior_event (struct execution_control_state *ecs)
                              step_frame_address)))
            {
              ecs->another_trap = 1;
-             goto keep_going;
+             keep_going (ecs);
+             return;
            }
 #endif /* 0 */
          disable_longjmp_breakpoint ();
@@ -2380,7 +2457,6 @@ handle_inferior_event (struct execution_control_state *ecs)
               dynamically loaded objects (among other things).  */
            if (stop_on_solib_events)
              {
-               stop_print_frame = 0;
                stop_stepping (ecs);
                return;
              }
@@ -2452,7 +2528,8 @@ handle_inferior_event (struct execution_control_state *ecs)
        if (SOLIB_IN_DYNAMIC_LINKER (ecs->pid, stop_pc))
          {
            ecs->another_trap = 1;
-           goto keep_going;
+           keep_going (ecs);
+           return;
          }
 #endif
        /* Else, stop and report the catchpoint(s) whose triggering
@@ -2499,7 +2576,8 @@ handle_inferior_event (struct execution_control_state *ecs)
        /* I'm not sure whether this needs to be check_sigtramp2 or
           whether it could/should be keep_going.  */
        check_sigtramp2 (ecs);
-       goto keep_going;
+       keep_going (ecs);
+       return;
       }
     
     if (step_range_end == 0)
@@ -2508,7 +2586,8 @@ handle_inferior_event (struct execution_control_state *ecs)
        /* I'm not sure whether this needs to be check_sigtramp2 or
           whether it could/should be keep_going.  */
        check_sigtramp2 (ecs);
-       goto keep_going;
+       keep_going (ecs);
+       return;
       }
 
     /* If stepping through a line, keep going if still within it.
@@ -2522,7 +2601,8 @@ handle_inferior_event (struct execution_control_state *ecs)
        /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
           So definately need to check for sigtramp here.  */
        check_sigtramp2 (ecs);
-       goto keep_going;
+       keep_going (ecs);
+       return;
       }
 
     /* We stepped out of the stepping range.  */
@@ -2532,7 +2612,27 @@ handle_inferior_event (struct execution_control_state *ecs)
        until we exit the run time loader code and reach the callee's
        address.  */
     if (step_over_calls < 0 && IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))
-      goto keep_going;
+      {
+       CORE_ADDR pc_after_resolver = SKIP_SOLIB_RESOLVER (stop_pc);
+
+       if (pc_after_resolver)
+         {
+           /* Set up a step-resume breakpoint at the address
+              indicated by SKIP_SOLIB_RESOLVER.  */
+           struct symtab_and_line sr_sal;
+           INIT_SAL (&sr_sal);
+           sr_sal.pc = pc_after_resolver;
+
+           check_for_old_step_resume_breakpoint ();
+           step_resume_breakpoint =
+             set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+           if (breakpoints_inserted)
+             insert_breakpoints ();
+         }
+
+       keep_going (ecs);
+       return;
+      }
 
     /* We can't update step_sp every time through the loop, because
        reading the stack pointer would slow down stepping too much.
@@ -2591,7 +2691,7 @@ handle_inferior_event (struct execution_control_state *ecs)
              /* We just stepped out of a signal handler and into
                 its calling trampoline.
 
-                Normally, we'd jump to step_over_function from
+                Normally, we'd call step_over_function from
                 here, but for some reason GDB can't unwind the
                 stack correctly to find the real PC for the point
                 user code where the signal trampoline will return
@@ -2620,7 +2720,8 @@ handle_inferior_event (struct execution_control_state *ecs)
          step_range_end = (step_range_start = prev_pc) + 1;
 
        ecs->remove_breakpoints_on_following_step = 1;
-       goto keep_going;
+       keep_going (ecs);
+       return;
       }
 
     if (stop_pc == ecs->stop_func_start                /* Quick test */
@@ -2637,13 +2738,32 @@ handle_inferior_event (struct execution_control_state *ecs)
               supposed to be stepping at the assembly language level
               ("stepi").  Just stop.  */
            stop_step = 1;
+           print_stop_reason (END_STEPPING_RANGE, 0);
            stop_stepping (ecs);
            return;
          }
 
        if (step_over_calls > 0 || IGNORE_HELPER_CALL (stop_pc))
-         /* We're doing a "next".  */
-         goto step_over_function;
+         {
+           /* We're doing a "next".  */
+
+           if (IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
+               && INNER_THAN (step_frame_address, read_sp()))
+             /* We stepped out of a signal handler, and into its
+                 calling trampoline.  This is misdetected as a
+                 subroutine call, but stepping over the signal
+                 trampoline isn't such a bad idea.  In order to do
+                 that, we have to ignore the value in
+                 step_frame_address, since that doesn't represent the
+                 frame that'll reach when we return from the signal
+                 trampoline.  Otherwise we'll probably continue to the
+                 end of the program.  */
+             step_frame_address = 0;
+
+           step_over_function (ecs);
+           keep_going (ecs);
+           return;
+         }
 
        /* If we are in a function call trampoline (a stub between
           the calling routine and the real function), locate the real
@@ -2668,7 +2788,8 @@ handle_inferior_event (struct execution_control_state *ecs)
                step_resume_breakpoint =
                  set_momentary_breakpoint (xxx, NULL, bp_step_resume);
                insert_breakpoints ();
-               goto keep_going;
+               keep_going (ecs);
+               return;
              }
          }
 
@@ -2683,96 +2804,15 @@ handle_inferior_event (struct execution_control_state *ecs)
 
          tmp_sal = find_pc_line (ecs->stop_func_start, 0);
          if (tmp_sal.line != 0)
-           goto step_into_function;
-       }
-
-      step_over_function:
-       /* A subroutine call has happened.  */
-       {
-         /* We've just entered a callee, and we wish to resume until it
-            returns to the caller.  Setting a step_resume breakpoint on
-            the return address will catch a return from the callee.
-
-            However, if the callee is recursing, we want to be careful
-            not to catch returns of those recursive calls, but only of
-            THIS instance of the call.
-
-            To do this, we set the step_resume bp's frame to our current
-            caller's frame (step_frame_address, which is set by the "next"
-            or "until" command, before execution begins).  */
-         struct symtab_and_line sr_sal;
-
-         INIT_SAL (&sr_sal);   /* initialize to zeros */
-         sr_sal.pc = 
-           ADDR_BITS_REMOVE (SAVED_PC_AFTER_CALL (get_current_frame ()));
-         sr_sal.section = find_pc_overlay (sr_sal.pc);
-
-         check_for_old_step_resume_breakpoint ();
-         step_resume_breakpoint =
-           set_momentary_breakpoint (sr_sal, get_current_frame (),
-                                     bp_step_resume);
-
-         if (!IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
-           step_resume_breakpoint->frame = step_frame_address;
-
-         if (breakpoints_inserted)
-           insert_breakpoints ();
-       }
-       goto keep_going;
-
-      step_into_function:
-       /* Subroutine call with source code we should not step over.
-          Do step to the first line of code in it.  */
-       {
-         struct symtab *s;
-
-         s = find_pc_symtab (stop_pc);
-         if (s && s->language != language_asm)
-           ecs->stop_func_start = SKIP_PROLOGUE (ecs->stop_func_start);
+           {
+             step_into_function (ecs); 
+             return;
+           }
        }
-       ecs->sal = find_pc_line (ecs->stop_func_start, 0);
-       /* Use the step_resume_break to step until
-          the end of the prologue, even if that involves jumps
-          (as it seems to on the vax under 4.2).  */
-       /* If the prologue ends in the middle of a source line,
-          continue to the end of that source line (if it is still
-          within the function).  Otherwise, just go to end of prologue.  */
-#ifdef PROLOGUE_FIRSTLINE_OVERLAP
-       /* no, don't either.  It skips any code that's
-          legitimately on the first line.  */
-#else
-       if (ecs->sal.end && ecs->sal.pc != ecs->stop_func_start && ecs->sal.end < ecs->stop_func_end)
-         ecs->stop_func_start = ecs->sal.end;
-#endif
-
-       if (ecs->stop_func_start == stop_pc)
-         {
-           /* We are already there: stop now.  */
-           stop_step = 1;
-           stop_stepping (ecs);
-           return;
-         }
-       else
-         /* Put the step-breakpoint there and go until there. */
-         {
-           struct symtab_and_line sr_sal;
-
-           INIT_SAL (&sr_sal); /* initialize to zeroes */
-           sr_sal.pc = ecs->stop_func_start;
-           sr_sal.section = find_pc_overlay (ecs->stop_func_start);
-           /* Do not specify what the fp should be when we stop
-              since on some machines the prologue
-              is where the new fp value is established.  */
-           check_for_old_step_resume_breakpoint ();
-           step_resume_breakpoint =
-             set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
-           if (breakpoints_inserted)
-             insert_breakpoints ();
+       step_over_function (ecs);
+       keep_going (ecs);
+       return;
 
-           /* And make sure stepping stops right away then.  */
-           step_range_end = step_range_start;
-         }
-       goto keep_going;
       }
 
     /* We've wandered out of the step range.  */
@@ -2784,6 +2824,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        /* It is stepi or nexti.  We always want to stop stepping after
           one instruction.  */
        stop_step = 1;
+       print_stop_reason (END_STEPPING_RANGE, 0);
        stop_stepping (ecs);
        return;
       }
@@ -2817,7 +2858,8 @@ handle_inferior_event (struct execution_control_state *ecs)
 
            /* Restart without fiddling with the step ranges or
               other state.  */
-           goto keep_going;
+           keep_going (ecs);
+           return;
          }
       }
 
@@ -2828,6 +2870,7 @@ handle_inferior_event (struct execution_control_state *ecs)
           when we do "s" in a function with no line numbers,
           or can this happen as a result of a return or longjmp?).  */
        stop_step = 1;
+       print_stop_reason (END_STEPPING_RANGE, 0);
        stop_stepping (ecs);
        return;
       }
@@ -2840,6 +2883,7 @@ handle_inferior_event (struct execution_control_state *ecs)
           That is said to make things like for (;;) statements work
           better.  */
        stop_step = 1;
+       print_stop_reason (END_STEPPING_RANGE, 0);
        stop_stepping (ecs);
        return;
       }
@@ -2859,6 +2903,7 @@ handle_inferior_event (struct execution_control_state *ecs)
           in which after skipping the prologue we better stop even though
           we will be in mid-line.  */
        stop_step = 1;
+       print_stop_reason (END_STEPPING_RANGE, 0);
        stop_stepping (ecs);
        return;
       }
@@ -2877,121 +2922,9 @@ handle_inferior_event (struct execution_control_state *ecs)
        step_frame_address = current_frame;
     }
 
-  keep_going:
-    /* Come to this label when you need to resume the inferior.
-       It's really much cleaner to do a goto than a maze of if-else
-       conditions.  */
-
-    /* ??rehrauer: ttrace on HP-UX theoretically allows one to debug
-       a vforked child beetween its creation and subsequent exit or
-       call to exec().  However, I had big problems in this rather
-       creaky exec engine, getting that to work.  The fundamental
-       problem is that I'm trying to debug two processes via an
-       engine that only understands a single process with possibly
-       multiple threads.
-
-       Hence, this spot is known to have problems when
-       target_can_follow_vfork_prior_to_exec returns 1. */
-
-    /* Save the pc before execution, to compare with pc after stop.  */
-    prev_pc = read_pc ();      /* Might have been DECR_AFTER_BREAK */
-    prev_func_start = ecs->stop_func_start;    /* Ok, since if DECR_PC_AFTER
-                                                  BREAK is defined, the
-                                                  original pc would not have
-                                                  been at the start of a
-                                                  function. */
-    prev_func_name = ecs->stop_func_name;
-
-    if (ecs->update_step_sp)
-      step_sp = read_sp ();
-    ecs->update_step_sp = 0;
-
-    /* If we did not do break;, it means we should keep
-       running the inferior and not return to debugger.  */
-
-    if (trap_expected && stop_signal != TARGET_SIGNAL_TRAP)
-      {
-       /* We took a signal (which we are supposed to pass through to
-          the inferior, else we'd have done a break above) and we
-          haven't yet gotten our trap.  Simply continue.  */
-       resume (currently_stepping (ecs), stop_signal);
-      }
-    else
-      {
-       /* Either the trap was not expected, but we are continuing
-          anyway (the user asked that this signal be passed to the
-          child)
-          -- or --
-          The signal was SIGTRAP, e.g. it was our signal, but we
-          decided we should resume from it.
-
-          We're going to run this baby now!
-
-          Insert breakpoints now, unless we are trying
-          to one-proceed past a breakpoint.  */
-       /* If we've just finished a special step resume and we don't
-          want to hit a breakpoint, pull em out.  */
-       if (step_resume_breakpoint == NULL
-           && through_sigtramp_breakpoint == NULL
-           && ecs->remove_breakpoints_on_following_step)
-         {
-           ecs->remove_breakpoints_on_following_step = 0;
-           remove_breakpoints ();
-           breakpoints_inserted = 0;
-         }
-       else if (!breakpoints_inserted &&
-                (through_sigtramp_breakpoint != NULL || !ecs->another_trap))
-         {
-           breakpoints_failed = insert_breakpoints ();
-           if (breakpoints_failed)
-             {
-               stop_stepping (ecs);
-               return;
-             }
-           breakpoints_inserted = 1;
-         }
-
-       trap_expected = ecs->another_trap;
-
-       /* Do not deliver SIGNAL_TRAP (except when the user
-          explicitly specifies that such a signal should be
-          delivered to the target program).
-
-          Typically, this would occure when a user is debugging a
-          target monitor on a simulator: the target monitor sets a
-          breakpoint; the simulator encounters this break-point and
-          halts the simulation handing control to GDB; GDB, noteing
-          that the break-point isn't valid, returns control back to
-          the simulator; the simulator then delivers the hardware
-          equivalent of a SIGNAL_TRAP to the program being
-          debugged. */
-
-       if (stop_signal == TARGET_SIGNAL_TRAP
-           && !signal_program[stop_signal])
-         stop_signal = TARGET_SIGNAL_0;
-
-#ifdef SHIFT_INST_REGS
-       /* I'm not sure when this following segment applies.  I do know,
-          now, that we shouldn't rewrite the regs when we were stopped
-          by a random signal from the inferior process.  */
-       /* FIXME: Shouldn't this be based on the valid bit of the SXIP?
-          (this is only used on the 88k).  */
-
-       if (!bpstat_explains_signal (stop_bpstat)
-           && (stop_signal != TARGET_SIGNAL_CHLD)
-           && !stopped_by_random_signal)
-         SHIFT_INST_REGS ();
-#endif /* SHIFT_INST_REGS */
-
-       resume (currently_stepping (ecs), stop_signal);
-      }
-
-    prepare_to_wait (ecs);
-    return;
+    keep_going (ecs);
 
   } /* extra brace, to preserve old indentation */
-
-  stop_stepping (ecs);
 }
 
 /* Are we in the middle of stepping?  */
@@ -3043,6 +2976,97 @@ check_sigtramp2 (struct execution_control_state *ecs)
     }
 }
 
+/* Subroutine call with source code we should not step over.  Do step
+   to the first line of code in it.  */
+
+static void
+step_into_function (struct execution_control_state *ecs)
+{
+  struct symtab *s;
+  struct symtab_and_line sr_sal;
+
+  s = find_pc_symtab (stop_pc);
+  if (s && s->language != language_asm)
+    ecs->stop_func_start = SKIP_PROLOGUE (ecs->stop_func_start);
+
+  ecs->sal = find_pc_line (ecs->stop_func_start, 0);
+  /* Use the step_resume_break to step until the end of the prologue,
+     even if that involves jumps (as it seems to on the vax under
+     4.2).  */
+  /* If the prologue ends in the middle of a source line, continue to
+     the end of that source line (if it is still within the function).
+     Otherwise, just go to end of prologue.  */
+#ifdef PROLOGUE_FIRSTLINE_OVERLAP
+  /* no, don't either.  It skips any code that's legitimately on the
+     first line.  */
+#else
+  if (ecs->sal.end
+      && ecs->sal.pc != ecs->stop_func_start
+      && ecs->sal.end < ecs->stop_func_end)
+    ecs->stop_func_start = ecs->sal.end;
+#endif
+
+  if (ecs->stop_func_start == stop_pc)
+    {
+      /* We are already there: stop now.  */
+      stop_step = 1;
+       print_stop_reason (END_STEPPING_RANGE, 0);
+      stop_stepping (ecs);
+      return;
+    }
+  else
+    {
+      /* Put the step-breakpoint there and go until there.  */
+      INIT_SAL (&sr_sal);      /* initialize to zeroes */
+      sr_sal.pc = ecs->stop_func_start;
+      sr_sal.section = find_pc_overlay (ecs->stop_func_start);
+      /* Do not specify what the fp should be when we stop since on
+        some machines the prologue is where the new fp value is
+        established.  */
+      check_for_old_step_resume_breakpoint ();
+      step_resume_breakpoint =
+       set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+      if (breakpoints_inserted)
+       insert_breakpoints ();
+
+      /* And make sure stepping stops right away then.  */
+      step_range_end = step_range_start;
+    }
+  keep_going (ecs);
+}
+
+/* We've just entered a callee, and we wish to resume until it returns
+   to the caller.  Setting a step_resume breakpoint on the return
+   address will catch a return from the callee.
+     
+   However, if the callee is recursing, we want to be careful not to
+   catch returns of those recursive calls, but only of THIS instance
+   of the call.
+
+   To do this, we set the step_resume bp's frame to our current
+   caller's frame (step_frame_address, which is set by the "next" or
+   "until" command, before execution begins).  */
+
+static void
+step_over_function (struct execution_control_state *ecs)
+{
+  struct symtab_and_line sr_sal;
+
+  INIT_SAL (&sr_sal);  /* initialize to zeros */
+  sr_sal.pc = ADDR_BITS_REMOVE (SAVED_PC_AFTER_CALL (get_current_frame ()));
+  sr_sal.section = find_pc_overlay (sr_sal.pc);
+
+  check_for_old_step_resume_breakpoint ();
+  step_resume_breakpoint =
+    set_momentary_breakpoint (sr_sal, get_current_frame (), bp_step_resume);
+
+  if (step_frame_address && !IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
+    step_resume_breakpoint->frame = step_frame_address;
+
+  if (breakpoints_inserted)
+    insert_breakpoints ();
+}
+
 static void
 stop_stepping (struct execution_control_state *ecs)
 {
@@ -3084,6 +3108,118 @@ stop_stepping (struct execution_control_state *ecs)
   ecs->wait_some_more = 0;
 }
 
+/* This function handles various cases where we need to continue
+   waiting for the inferior.  */
+/* (Used to be the keep_going: label in the old wait_for_inferior) */
+
+static void
+keep_going (struct execution_control_state *ecs)
+{
+  /* ??rehrauer: ttrace on HP-UX theoretically allows one to debug a
+     vforked child between its creation and subsequent exit or call to
+     exec().  However, I had big problems in this rather creaky exec
+     engine, getting that to work.  The fundamental problem is that
+     I'm trying to debug two processes via an engine that only
+     understands a single process with possibly multiple threads.
+
+     Hence, this spot is known to have problems when
+     target_can_follow_vfork_prior_to_exec returns 1. */
+
+  /* Save the pc before execution, to compare with pc after stop.  */
+  prev_pc = read_pc ();        /* Might have been DECR_AFTER_BREAK */
+  prev_func_start = ecs->stop_func_start;      /* Ok, since if DECR_PC_AFTER
+                                                  BREAK is defined, the
+                                                  original pc would not have
+                                                  been at the start of a
+                                                  function. */
+  prev_func_name = ecs->stop_func_name;
+
+  if (ecs->update_step_sp)
+    step_sp = read_sp ();
+  ecs->update_step_sp = 0;
+
+  /* If we did not do break;, it means we should keep running the
+     inferior and not return to debugger.  */
+
+  if (trap_expected && stop_signal != TARGET_SIGNAL_TRAP)
+    {
+      /* We took a signal (which we are supposed to pass through to
+        the inferior, else we'd have done a break above) and we
+        haven't yet gotten our trap.  Simply continue.  */
+      resume (currently_stepping (ecs), stop_signal);
+    }
+  else
+    {
+      /* Either the trap was not expected, but we are continuing
+        anyway (the user asked that this signal be passed to the
+        child)
+        -- or --
+        The signal was SIGTRAP, e.g. it was our signal, but we
+        decided we should resume from it.
+
+        We're going to run this baby now!
+
+        Insert breakpoints now, unless we are trying to one-proceed
+        past a breakpoint.  */
+      /* If we've just finished a special step resume and we don't
+        want to hit a breakpoint, pull em out.  */
+      if (step_resume_breakpoint == NULL
+         && through_sigtramp_breakpoint == NULL
+         && ecs->remove_breakpoints_on_following_step)
+       {
+         ecs->remove_breakpoints_on_following_step = 0;
+         remove_breakpoints ();
+         breakpoints_inserted = 0;
+       }
+      else if (!breakpoints_inserted &&
+              (through_sigtramp_breakpoint != NULL || !ecs->another_trap))
+       {
+         breakpoints_failed = insert_breakpoints ();
+         if (breakpoints_failed)
+           {
+             stop_stepping (ecs);
+             return;
+           }
+         breakpoints_inserted = 1;
+       }
+
+      trap_expected = ecs->another_trap;
+
+      /* Do not deliver SIGNAL_TRAP (except when the user explicitly
+        specifies that such a signal should be delivered to the
+        target program).
+
+        Typically, this would occure when a user is debugging a
+        target monitor on a simulator: the target monitor sets a
+        breakpoint; the simulator encounters this break-point and
+        halts the simulation handing control to GDB; GDB, noteing
+        that the break-point isn't valid, returns control back to the
+        simulator; the simulator then delivers the hardware
+        equivalent of a SIGNAL_TRAP to the program being debugged. */
+
+      if (stop_signal == TARGET_SIGNAL_TRAP
+         && !signal_program[stop_signal])
+       stop_signal = TARGET_SIGNAL_0;
+
+#ifdef SHIFT_INST_REGS
+      /* I'm not sure when this following segment applies.  I do know,
+        now, that we shouldn't rewrite the regs when we were stopped
+        by a random signal from the inferior process.  */
+      /* FIXME: Shouldn't this be based on the valid bit of the SXIP?
+        (this is only used on the 88k).  */
+
+      if (!bpstat_explains_signal (stop_bpstat)
+         && (stop_signal != TARGET_SIGNAL_CHLD)
+         && !stopped_by_random_signal)
+       SHIFT_INST_REGS ();
+#endif /* SHIFT_INST_REGS */
+
+      resume (currently_stepping (ecs), stop_signal);
+    }
+
+    prepare_to_wait (ecs);
+}
+
 /* This function normally comes after a resume, before
    handle_inferior_event exits.  It takes care of any last bits of
    housekeeping, and sets the all-important wait_some_more flag.  */
@@ -3111,64 +3247,128 @@ prepare_to_wait (struct execution_control_state *ecs)
   ecs->wait_some_more = 1;
 }
 
-/* This function returns TRUE if ep is an internal breakpoint
-   set to catch generic shared library (aka dynamically-linked
-   library) events.  (This is *NOT* the same as a catchpoint for a
-   shlib event.  The latter is something a user can set; this is
-   something gdb sets for its own use, and isn't ever shown to a
-   user.) */
-static int
-is_internal_shlib_eventpoint (struct breakpoint *ep)
-{
-  return
-    (ep->type == bp_shlib_event)
-    ;
-}
-
-/* This function returns TRUE if bs indicates that the inferior
-   stopped due to a shared library (aka dynamically-linked library)
-   event. */
-
-static int
-stopped_for_internal_shlib_event (bpstat bs)
-{
-  /* Note that multiple eventpoints may've caused the stop.  Any
-     that are associated with shlib events will be accepted. */
-  for (; bs != NULL; bs = bs->next)
-    {
-      if ((bs->breakpoint_at != NULL)
-         && is_internal_shlib_eventpoint (bs->breakpoint_at))
-       return 1;
-    }
-
-  /* If we get here, then no candidate was found. */
-  return 0;
-}
-\f
-/* Reset proper settings after an asynchronous command has finished.
-   If the execution command was in synchronous mode, register stdin
-   with the event loop, and reset the prompt. */
-
+/* 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.*/
 static void
-complete_execution (void)
+print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
 {
-  extern int cleanup_sigint_signal_handler (void);
-
-  target_executing = 0;
-  if (sync_execution)
+  switch (stop_reason)
     {
-      add_file_handler (input_fd, call_readline, 0);
-      pop_prompt ();
-      sync_execution = 0;
-      cleanup_sigint_signal_handler ();
-      display_gdb_prompt (0);
-    }
-  else
-    {
-      if (exec_done_display_p)
-       printf_unfiltered ("completed.\n");
+    case STOP_UNKNOWN:
+      /* We don't deal with these cases from handle_inferior_event()
+         yet. */
+      break;
+    case END_STEPPING_RANGE:
+      /* We are done with a step/next/si/ni command. */
+      /* For now print nothing. */
+#ifdef UI_OUT
+      /* Print a message only if not in the middle of doing a "step n"
+        operation for n > 1 */
+      if (!step_multi || !stop_step)
+       if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+         ui_out_field_string (uiout, "reason", "end-stepping-range");
+#endif
+      break;
+    case BREAKPOINT_HIT:
+      /* We found a breakpoint. */
+      /* For now print nothing. */
+      break;
+    case SIGNAL_EXITED:
+      /* The inferior was terminated by a signal. */
+#ifdef UI_OUT
+      annotate_signalled ();
+      if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+       ui_out_field_string (uiout, "reason", "exited-signalled");
+      ui_out_text (uiout, "\nProgram terminated with signal ");
+      annotate_signal_name ();
+      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");
+      ui_out_text (uiout, "The program no longer exists.\n");
+#else
+      annotate_signalled ();
+      printf_filtered ("\nProgram terminated with signal ");
+      annotate_signal_name ();
+      printf_filtered ("%s", target_signal_to_name (stop_info));
+      annotate_signal_name_end ();
+      printf_filtered (", ");
+      annotate_signal_string ();
+      printf_filtered ("%s", target_signal_to_string (stop_info));
+      annotate_signal_string_end ();
+      printf_filtered (".\n");
+
+      printf_filtered ("The program no longer exists.\n");
+      gdb_flush (gdb_stdout);
+#endif
+      break;
+    case EXITED:
+      /* The inferior program is finished. */
+#ifdef UI_OUT
+      annotate_exited (stop_info);
+      if (stop_info)
+       {
+         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+           ui_out_field_string (uiout, "reason", "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 (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+           ui_out_field_string (uiout, "reason", "exited-normally");
+         ui_out_text (uiout, "\nProgram exited normally.\n");
+       }
+#else
+      annotate_exited (stop_info);
+      if (stop_info)
+       printf_filtered ("\nProgram exited with code 0%o.\n",
+                        (unsigned int) stop_info);
+      else
+       printf_filtered ("\nProgram exited normally.\n");
+#endif
+      break;
+    case SIGNAL_RECEIVED:
+      /* Signal received. The signal table tells us to print about
+         it. */
+#ifdef UI_OUT
+      annotate_signal ();
+      ui_out_text (uiout, "\nProgram received signal ");
+      annotate_signal_name ();
+      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");
+#else
+      annotate_signal ();
+      printf_filtered ("\nProgram received signal ");
+      annotate_signal_name ();
+      printf_filtered ("%s", target_signal_to_name (stop_info));
+      annotate_signal_name_end ();
+      printf_filtered (", ");
+      annotate_signal_string ();
+      printf_filtered ("%s", target_signal_to_string (stop_info));
+      annotate_signal_string_end ();
+      printf_filtered (".\n");
+      gdb_flush (gdb_stdout);      
+#endif
+      break;
+    default:
+      internal_error ("print_stop_reason: unrecognized enum value");
+      break;
     }
 }
+\f
 
 /* Here to return control to GDB when the inferior stops for real.
    Print appropriate messages, remove breakpoints, give terminal our modes.
@@ -3187,14 +3387,13 @@ normal_stop (void)
 
      (Note that there's no point in saying anything if the inferior
      has exited!) */
-  if (may_switch_from_inferior_pid
-      && (switched_from_inferior_pid != inferior_pid)
+  if ((previous_inferior_pid != inferior_pid)
       && target_has_execution)
     {
       target_terminal_ours_for_output ();
-      printf_filtered ("[Switched to %s]\n",
+      printf_filtered ("[Switching to %s]\n",
                       target_pid_or_tid_to_str (inferior_pid));
-      switched_from_inferior_pid = inferior_pid;
+      previous_inferior_pid = inferior_pid;
     }
 
   /* Make sure that the current_frame's pc is correct.  This
@@ -3206,9 +3405,11 @@ normal_stop (void)
   if (breakpoints_failed)
     {
       target_terminal_ours_for_output ();
-      print_sys_errmsg ("ptrace", breakpoints_failed);
+      print_sys_errmsg ("While inserting breakpoints", breakpoints_failed);
       printf_filtered ("Stopped; cannot insert breakpoints.\n\
-The same program may be running in another process.\n");
+The same program may be running in another process,\n\
+or you may have requested too many hardware breakpoints\n\
+and/or watchpoints.\n");
     }
 
   if (target_has_execution && breakpoints_inserted)
@@ -3242,14 +3443,6 @@ The same program may be running in another process.\n");
 
   target_terminal_ours ();
 
-  /* Did we stop because the user set the stop_on_solib_events
-     variable?  (If so, we report this as a generic, "Stopped due
-     to shlib event" message.) */
-  if (stopped_for_internal_shlib_event (stop_bpstat))
-    {
-      printf_filtered ("Stopped due to shared library event\n");
-    }
-
   /* Look up the hook_stop and run it if it exists.  */
 
   if (stop_command && stop_command->hook)
@@ -3279,36 +3472,54 @@ The same program may be running in another process.\n");
          bpstat_print() contains the logic deciding in detail
          what to print, based on the event(s) that just occurred. */
 
-      if (stop_print_frame)
+      if (stop_print_frame
+         && selected_frame)
        {
          int bpstat_ret;
          int source_flag;
+         int do_frame_printing = 1;
 
          bpstat_ret = bpstat_print (stop_bpstat);
-         /* bpstat_print() returned one of:
-            -1: Didn't print anything
-            0: Printed preliminary "Breakpoint n, " message, desires
-            location tacked on
-            1: Printed something, don't tack on location */
-
-         if (bpstat_ret == -1)
-           if (stop_step
-               && step_frame_address == FRAME_FP (get_current_frame ())
-               && step_start_function == find_pc_function (stop_pc))
-             source_flag = -1; /* finished step, just print source line */
-           else
-             source_flag = 1;  /* print location and source line */
-         else if (bpstat_ret == 0)     /* hit bpt, desire location */
-           source_flag = 1;    /* print location and source line */
-         else                  /* bpstat_ret == 1, hit bpt, do not desire location */
-           source_flag = -1;   /* just print source line */
+         switch (bpstat_ret)
+           {
+           case PRINT_UNKNOWN:
+             if (stop_step
+                 && step_frame_address == FRAME_FP (get_current_frame ())
+                 && step_start_function == find_pc_function (stop_pc))
+               source_flag = SRC_LINE;   /* finished step, just print source line */
+             else
+               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 */
+             break;
+           case PRINT_SRC_ONLY:
+             source_flag = SRC_LINE;
+             break;
+           case PRINT_NOTHING:
+             do_frame_printing = 0;
+             break;
+           default:
+             internal_error ("Unknown value.");
+           }
+#ifdef UI_OUT
+         /* For mi, have the same behavior every time we stop:
+             print everything but the source line. */
+         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+           source_flag = LOC_AND_ADDRESS;
+#endif
 
+#ifdef UI_OUT
+         if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+           ui_out_field_int (uiout, "thread-id", pid_to_thread_id (inferior_pid));
+#endif
          /* The behavior of this routine with respect to the source
             flag is:
-            -1: Print only source line
-            0: Print only location
-            1: Print location and source line */
-         show_and_print_stack_frame (selected_frame, -1, source_flag);
+            SRC_LINE: Print only source line
+            LOCATION: Print only location
+            SRC_AND_LOC: Print location and source line */
+         if (do_frame_printing)
+           show_and_print_stack_frame (selected_frame, -1, source_flag);
 
          /* Display the auto-display expressions.  */
          do_displays ();
@@ -3365,6 +3576,33 @@ signal_pass_state (int signo)
   return signal_program[signo];
 }
 
+int signal_stop_update (signo, state)
+     int signo;
+     int state;
+{
+  int ret = signal_stop[signo];
+  signal_stop[signo] = state;
+  return ret;
+}
+
+int signal_print_update (signo, state)
+     int signo;
+     int state;
+{
+  int ret = signal_print[signo];
+  signal_print[signo] = state;
+  return ret;
+}
+
+int signal_pass_update (signo, state)
+     int signo;
+     int state;
+{
+  int ret = signal_program[signo];
+  signal_program[signo] = state;
+  return ret;
+}
+
 static void
 sig_print_header (void)
 {
@@ -3875,6 +4113,18 @@ restore_inferior_status (struct inferior_status *inf_status)
   free_inferior_status (inf_status);
 }
 
+static void
+do_restore_inferior_status_cleanup (void *sts)
+{
+  restore_inferior_status (sts);
+}
+
+struct cleanup *
+make_cleanup_restore_inferior_status (struct inferior_status *inf_status)
+{
+  return make_cleanup (do_restore_inferior_status_cleanup, inf_status);
+}
+
 void
 discard_inferior_status (struct inferior_status *inf_status)
 {
@@ -4028,7 +4278,7 @@ to the user would be loading/unloading of a new library.\n",
   c = add_set_enum_cmd ("follow-fork-mode",
                        class_run,
                        follow_fork_mode_kind_names,
-                       (char *) &follow_fork_mode_string,
+                       &follow_fork_mode_string,
 /* ??rehrauer:  The "both" option is broken, by what may be a 10.20
    kernel problem.  It's also not terribly useful without a GUI to
    help the user drive two debuggers.  So for now, I'm disabling
@@ -4063,7 +4313,7 @@ By default, the debugger will follow the parent process.",
 
   c = add_set_enum_cmd ("scheduler-locking", class_run,
                        scheduler_enums,        /* array of string names */
-                       (char *) &scheduler_mode,       /* current mode  */
+                       &scheduler_mode,        /* current mode  */
                        "Set mode for locking scheduler during execution.\n\
 off  == no locking (threads may preempt at any time)\n\
 on   == full locking (no thread except the current thread may run)\n\
This page took 0.042272 seconds and 4 git commands to generate.