import gdb-1999-10-04 snapshot
[binutils-gdb.git] / gdb / infrun.c
index efb1caf91527c1207d86ac5b1c019440e52562c6..cc8c1bfc960b828f0cbfe59b12cc8ee2a4636670 100644 (file)
 #include "symfile.h"           /* for overlay functions */
 #include "top.h"
 #include <signal.h>
-#include "event-loop.h"
+#include "inf-loop.h"
 
 /* Prototypes for local functions */
 
-static void signals_info PARAMS ((char *, int));
+static void signals_info (char *, int);
 
-static void handle_command PARAMS ((char *, int));
+static void handle_command (char *, int);
 
-static void sig_print_info PARAMS ((enum target_signal));
+static void sig_print_info (enum target_signal);
 
-static void sig_print_header PARAMS ((void));
+static void sig_print_header (void);
 
-static void resume_cleanups PARAMS ((int));
+static void resume_cleanups (int);
 
-static int hook_stop_stub PARAMS ((PTR));
+static int hook_stop_stub (void *);
 
-static void delete_breakpoint_current_contents PARAMS ((PTR));
+static void delete_breakpoint_current_contents (void *);
 
-static void set_follow_fork_mode_command PARAMS ((char *arg, int from_tty, struct cmd_list_element * c));
+static void set_follow_fork_mode_command (char *arg, int from_tty,
+                                         struct cmd_list_element * c);
 
-static void complete_execution PARAMS ((void));
+static struct inferior_status *xmalloc_inferior_status (void);
+
+static void free_inferior_status (struct inferior_status *);
+
+static int restore_selected_frame (void *);
+
+static void build_infrun (void);
+
+static void follow_inferior_fork (int parent_pid, int child_pid,
+                                 int has_forked, int has_vforked);
+
+static void follow_fork (int parent_pid, int child_pid);
+
+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);
+
+static void xdb_handle_command (char *args, int from_tty);
+
+void _initialize_infrun (void);
 
 int inferior_ignoring_startup_exec_events = 0;
 int inferior_ignoring_leading_exec_events = 0;
 
 /* In asynchronous mode, but simulating synchronous execution. */
+
 int sync_execution = 0;
 
 /* wait_for_inferior and normal_stop use this to notify the user
    when the inferior stopped in a different thread than it had been
-   running in. */
+   running in.  */
+
 static int switched_from_inferior_pid;
 
 /* This will be true for configurations that may actually report an
@@ -98,7 +129,8 @@ static int may_follow_exec = MAY_FOLLOW_EXEC;
 
    Versions of gdb which don't use the "step == this thread steps
    and others continue" model but instead use the "step == this
-   thread steps and others wait" shouldn't do this. */
+   thread steps and others wait" shouldn't do this.  */
+
 static int thread_step_needed = 0;
 
 /* This is true if thread_step_needed should actually be used.  At
@@ -110,34 +142,6 @@ static int thread_step_needed = 0;
 
 static int use_thread_step_needed = USE_THREAD_STEP_NEEDED;
 
-static void follow_inferior_fork PARAMS ((int parent_pid,
-                                         int child_pid,
-                                         int has_forked,
-                                         int has_vforked));
-
-static void follow_fork PARAMS ((int parent_pid, int child_pid));
-
-static void follow_vfork PARAMS ((int parent_pid, int child_pid));
-
-static void set_schedlock_func PARAMS ((char *args, int from_tty,
-                                       struct cmd_list_element * c));
-
-static int is_internal_shlib_eventpoint PARAMS ((struct breakpoint * ep));
-
-static int stopped_for_internal_shlib_event PARAMS ((bpstat bs));
-
-static int stopped_for_shlib_catchpoint PARAMS ((bpstat bs,
-                                                struct breakpoint ** cp_p));
-
-#if __STDC__
-struct execution_control_state;
-#endif
-static int currently_stepping PARAMS ((struct execution_control_state * ecs));
-
-static void xdb_handle_command PARAMS ((char *args, int from_tty));
-
-void _initialize_infrun PARAMS ((void));
-
 /* GET_LONGJMP_TARGET returns the PC at which longjmp() will resume the
    program.  It needs to examine the jmp_buf argument and extract the PC
    from it.  The return value is non-zero on success, zero otherwise. */
@@ -170,15 +174,53 @@ void _initialize_infrun PARAMS ((void));
 #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. */
@@ -224,6 +266,26 @@ void _initialize_infrun PARAMS ((void));
 #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 ()
+{
+  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.  */
 
@@ -393,19 +455,15 @@ static char *follow_fork_mode_string = NULL;
 \f
 
 static void
-follow_inferior_fork (parent_pid, child_pid, has_forked, has_vforked)
-     int parent_pid;
-     int child_pid;
-     int has_forked;
-     int has_vforked;
+follow_inferior_fork (int parent_pid, int child_pid, int has_forked,
+                     int has_vforked)
 {
   int followed_parent = 0;
   int followed_child = 0;
-  int ima_clone = 0;
 
   /* Which process did the user want us to follow? */
   char *follow_mode =
-  savestring (follow_fork_mode_string, strlen (follow_fork_mode_string));
+    savestring (follow_fork_mode_string, strlen (follow_fork_mode_string));
 
   /* Or, did the user not know, and want us to ask? */
   if (STREQ (follow_fork_mode_string, "ask"))
@@ -568,21 +626,17 @@ follow_inferior_fork (parent_pid, child_pid, has_forked, has_vforked)
 }
 
 static void
-follow_fork (parent_pid, child_pid)
-     int parent_pid;
-     int child_pid;
+follow_fork (int parent_pid, int child_pid)
 {
   follow_inferior_fork (parent_pid, child_pid, 1, 0);
 }
 
 
 /* Forward declaration. */
-static void follow_exec PARAMS ((int, char *));
+static void follow_exec (int, char *);
 
 static void
-follow_vfork (parent_pid, child_pid)
-     int parent_pid;
-     int child_pid;
+follow_vfork (int parent_pid, int child_pid)
 {
   follow_inferior_fork (parent_pid, child_pid, 0, 1);
 
@@ -597,9 +651,7 @@ follow_vfork (parent_pid, child_pid)
 }
 
 static void
-follow_exec (pid, execd_pathname)
-     int pid;
-     char *execd_pathname;
+follow_exec (int pid, char *execd_pathname)
 {
   int saved_pid = pid;
   struct target_ops *tgt;
@@ -707,8 +759,7 @@ static int singlestep_breakpoints_inserted_p = 0;
 /* Things to clean up if we QUIT out of resume ().  */
 /* ARGSUSED */
 static void
-resume_cleanups (arg)
-     int arg;
+resume_cleanups (int arg)
 {
   normal_stop ();
 }
@@ -721,10 +772,7 @@ static char *scheduler_enums[] =
 {schedlock_off, schedlock_on, schedlock_step};
 
 static void
-set_schedlock_func (args, from_tty, c)
-     char *args;
-     int from_tty;
-     struct cmd_list_element *c;
+set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
 {
   if (c->type == set_cmd)
     if (!target_can_lock_scheduler)
@@ -736,6 +784,8 @@ set_schedlock_func (args, from_tty, 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
@@ -745,9 +795,7 @@ set_schedlock_func (args, from_tty, c)
    STEP nonzero if we should step (zero to continue instead).
    SIG is the signal to give the inferior (zero for none).  */
 void
-resume (step, sig)
-     int step;
-     enum target_signal sig;
+resume (int step, enum target_signal sig)
 {
   int should_resume = 1;
   struct cleanup *old_cleanups = make_cleanup ((make_cleanup_func)
@@ -762,6 +810,13 @@ resume (step, sig)
     step = 0;
 #endif
 
+  /* 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 */
@@ -867,7 +922,7 @@ resume (step, sig)
    First do this, then set the ones you want, then call `proceed'.  */
 
 void
-clear_proceed_status ()
+clear_proceed_status (void)
 {
   trap_expected = 0;
   step_range_start = 0;
@@ -896,10 +951,7 @@ clear_proceed_status ()
    You should call clear_proceed_status before calling proceed.  */
 
 void
-proceed (addr, siggnal, step)
-     CORE_ADDR addr;
-     enum target_signal siggnal;
-     int step;
+proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
 {
   int oneproc = 0;
 
@@ -908,7 +960,7 @@ proceed (addr, siggnal, 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
@@ -1014,7 +1066,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 ();
@@ -1031,37 +1083,37 @@ static char *prev_func_name;
 \f
 
 /* Start remote-debugging of a machine over a serial link.  */
+
 void
-start_remote ()
+start_remote (void)
 {
   init_thread_list ();
   init_wait_for_inferior ();
   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.  */
 
 void
-init_wait_for_inferior ()
+init_wait_for_inferior (void)
 {
   /* These are meaningless until the first time through wait_for_inferior.  */
   prev_pc = 0;
@@ -1090,8 +1142,7 @@ init_wait_for_inferior ()
 }
 
 static void
-delete_breakpoint_current_contents (arg)
-     PTR arg;
+delete_breakpoint_current_contents (void *arg)
 {
   struct breakpoint **breakpointp = (struct breakpoint **) arg;
   if (*breakpointp != NULL)
@@ -1145,9 +1196,16 @@ struct execution_control_state
     int wait_some_more;
   };
 
-void init_execution_control_state PARAMS ((struct execution_control_state * ecs));
+void init_execution_control_state (struct execution_control_state * ecs);
+
+void handle_inferior_event (struct execution_control_state * ecs);
 
-void handle_inferior_event PARAMS ((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);
 
 /* Wait for control to return from inferior to debugger.
    If inferior gets a signal, we may decide to start it up again
@@ -1156,7 +1214,7 @@ void handle_inferior_event PARAMS ((struct execution_control_state * ecs));
    should be left stopped and GDB should read more commands.  */
 
 void
-wait_for_inferior ()
+wait_for_inferior (void)
 {
   struct cleanup *old_cleanups;
   struct execution_control_state ecss;
@@ -1219,7 +1277,8 @@ struct execution_control_state async_ecss;
 struct execution_control_state *async_ecs;
 
 void
-fetch_inferior_event ()
+fetch_inferior_event (client_data)
+     void *client_data;
 {
   static struct cleanup *old_cleanups;
 
@@ -1267,11 +1326,7 @@ fetch_inferior_event ()
         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 ();
+      inferior_event_handler (INF_EXEC_COMPLETE, NULL);
     }
 }
 
@@ -1279,8 +1334,7 @@ fetch_inferior_event ()
    wait_for_inferior-type loop.  */
 
 void
-init_execution_control_state (ecs)
-     struct execution_control_state *ecs;
+init_execution_control_state (struct execution_control_state *ecs)
 {
   ecs->random_signal = 0;
   ecs->remove_breakpoints_on_following_step = 0;
@@ -1299,10 +1353,11 @@ init_execution_control_state (ecs)
 }
 
 /* Call this function before setting step_resume_breakpoint, as a
-   sanity check.  We should never be setting a new
-   step_resume_breakpoint when we have an old one active.  */
+   sanity check.  There should never be more than one step-resume
+   breakpoint per thread, so we should never be setting a new
+   step_resume_breakpoint when one is already active.  */
 static void
-check_for_old_step_resume_breakpoint ()
+check_for_old_step_resume_breakpoint (void)
 {
   if (step_resume_breakpoint)
     warning ("GDB bug: infrun.c (wait_for_inferior): dropping old step_resume breakpoint");
@@ -1313,8 +1368,7 @@ check_for_old_step_resume_breakpoint ()
    appropriate action.  */
 
 void
-handle_inferior_event (ecs)
-     struct execution_control_state *ecs;
+handle_inferior_event (struct execution_control_state *ecs)
 {
   CORE_ADDR tmp;
   int stepped_after_stopped_by_watchpoint;
@@ -1351,7 +1405,8 @@ handle_inferior_event (ecs)
        else
          target_resume (-1, 0, TARGET_SIGNAL_0);
        ecs->infwait_state = infwait_normal_state;
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
 
       case infwait_nullified_state:
        break;
@@ -1402,7 +1457,8 @@ handle_inferior_event (ecs)
           make progress.  */
 
        target_resume (-1, 0, TARGET_SIGNAL_0);
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
 #endif
       }
 
@@ -1437,11 +1493,13 @@ handle_inferior_event (ecs)
          }
 #endif
        resume (0, TARGET_SIGNAL_0);
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
 
       case TARGET_WAITKIND_SPURIOUS:
        resume (0, TARGET_SIGNAL_0);
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
 
       case TARGET_WAITKIND_EXITED:
        target_terminal_ours ();        /* Must do this before mourn anyway */
@@ -1461,7 +1519,8 @@ handle_inferior_event (ecs)
        target_mourn_inferior ();
        singlestep_breakpoints_inserted_p = 0;  /*SOFTWARE_SINGLE_STEP_P */
        stop_print_frame = 0;
-       goto stop_stepping;
+       stop_stepping (ecs);
+       return;
 
       case TARGET_WAITKIND_SIGNALLED:
        stop_print_frame = 0;
@@ -1489,7 +1548,8 @@ handle_inferior_event (ecs)
        printf_filtered ("The program no longer exists.\n");
        gdb_flush (gdb_stdout);
        singlestep_breakpoints_inserted_p = 0;  /*SOFTWARE_SINGLE_STEP_P */
-       goto stop_stepping;
+       stop_stepping (ecs);
+       return;
 
        /* The following are the only cases in which we keep going;
           the above cases end in a continue or goto. */
@@ -1506,7 +1566,8 @@ handle_inferior_event (ecs)
            pending_follow.fork_event.saw_parent_fork = 1;
            pending_follow.fork_event.parent_pid = ecs->pid;
            pending_follow.fork_event.child_pid = ecs->ws.value.related_pid;
-           goto wfi_continue;
+           prepare_to_wait (ecs);
+           return;
          }
        else
          {
@@ -1518,13 +1579,7 @@ handle_inferior_event (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;
@@ -1566,18 +1621,13 @@ handle_inferior_event (ecs)
            if (follow_vfork_when_exec)
              {
                target_resume (ecs->pid, 0, TARGET_SIGNAL_0);
-               goto wfi_continue;
+               prepare_to_wait (ecs);
+               return;
              }
          }
 
        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;
 
@@ -1594,13 +1644,15 @@ handle_inferior_event (ecs)
            if (pending_follow.kind == TARGET_WAITKIND_VFORKED)
              ENSURE_VFORKING_PARENT_REMAINS_STOPPED (pending_follow.fork_event.parent_pid);
            target_resume (ecs->pid, 0, TARGET_SIGNAL_0);
-           goto wfi_continue;
+           prepare_to_wait (ecs);
+           return;
          }
        inferior_ignoring_leading_exec_events =
          target_reported_exec_events_per_exec_call () - 1;
 
-       pending_follow.execd_pathname = savestring (ecs->ws.value.execd_pathname,
-                                    strlen (ecs->ws.value.execd_pathname));
+       pending_follow.execd_pathname =
+         savestring (ecs->ws.value.execd_pathname,
+                     strlen (ecs->ws.value.execd_pathname));
 
        /* Did inferior_pid exec, or did a (possibly not-yet-followed)
           child of a vfork exec?
@@ -1628,7 +1680,8 @@ handle_inferior_event (ecs)
            if (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK ())
              target_resume (ecs->pid, 1, TARGET_SIGNAL_0);
            /* We expect the parent vfork event to be available now. */
-           goto wfi_continue;
+           prepare_to_wait (ecs);
+           return;
          }
 
        /* This causes the eventpoints and symbol table to be reset.  Must
@@ -1639,13 +1692,7 @@ handle_inferior_event (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;
@@ -1674,7 +1721,8 @@ handle_inferior_event (ecs)
            TARGET_DISABLE_HW_WATCHPOINTS (inferior_pid);
          }
        resume (0, TARGET_SIGNAL_0);
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
 
        /* Before examining the threads further, step this thread to
           get it entirely out of the syscall.  (We get notice of the
@@ -1699,7 +1747,8 @@ handle_inferior_event (ecs)
            ecs->enable_hw_watchpoints_after_wait =
              (number_of_threads_in_syscalls == 0);
          }
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
 
       case TARGET_WAITKIND_STOPPED:
        stop_signal = ecs->ws.value.sig;
@@ -1716,7 +1765,8 @@ handle_inferior_event (ecs)
     if (ecs->new_thread_event)
       {
        target_resume (-1, 0, TARGET_SIGNAL_0);
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
       }
 
     stop_pc = read_pc_pid (ecs->pid);
@@ -1763,7 +1813,8 @@ handle_inferior_event (ecs)
                    ecs->waiton_pid = ecs->pid;
                    ecs->wp = &(ecs->ws);
                    ecs->infwait_state = infwait_thread_hop_state;
-                   goto wfi_continue;
+                   prepare_to_wait (ecs);
+                   return;
                  }
 
                /* We need to restart all the threads now,
@@ -1774,7 +1825,8 @@ handle_inferior_event (ecs)
                  target_resume (ecs->pid, 0, TARGET_SIGNAL_0);
                else
                  target_resume (-1, 0, TARGET_SIGNAL_0);
-               goto wfi_continue;
+               prepare_to_wait (ecs);
+               return;
              }
            else
              {
@@ -1840,7 +1892,8 @@ handle_inferior_event (ecs)
              stop_signal = TARGET_SIGNAL_0;
 
            target_resume (ecs->pid, 0, stop_signal);
-           goto wfi_continue;
+           prepare_to_wait (ecs);
+           return;
          }
 
        /* It's a SIGTRAP or a signal we're interested in.  Switch threads,
@@ -1906,7 +1959,8 @@ handle_inferior_event (ecs)
        ecs->infwait_state = infwait_nullified_state;
        ecs->waiton_pid = ecs->pid;
        ecs->wp = &(ecs->tmpstatus);
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
       }
 
     /* It may not be necessary to disable the watchpoint to stop over
@@ -1915,7 +1969,8 @@ handle_inferior_event (ecs)
     if (HAVE_STEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
       {
        resume (1, 0);
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
       }
 
     /* It is far more common to need to disable a watchpoint to step
@@ -1949,7 +2004,8 @@ handle_inferior_event (ecs)
        ecs->waiton_pid = ecs->pid;
        ecs->wp = &(ecs->ws);
        ecs->infwait_state = infwait_nonstep_watch_state;
-       goto wfi_continue;
+       prepare_to_wait (ecs);
+       return;
       }
 
     /* It may be possible to simply continue after a watchpoint.  */
@@ -1998,10 +2054,14 @@ handle_inferior_event (ecs)
        if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
          {
            stop_print_frame = 0;
-           goto wfi_break;
+           stop_stepping (ecs);
+           return;
          }
        if (stop_soon_quietly)
-         goto wfi_break;
+         {
+           stop_stepping (ecs);
+           return;
+         }
 
        /* Don't even think about breakpoints
           if just proceeded over a breakpoint.
@@ -2018,22 +2078,15 @@ handle_inferior_event (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.  */
@@ -2094,15 +2147,17 @@ handle_inferior_event (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)
@@ -2112,7 +2167,8 @@ handle_inferior_event (ecs)
          {
            trap_expected = 1;
            stop_signal = TARGET_SIGNAL_0;
-           goto keep_going;
+           keep_going (ecs);
+           return;
          }
       }
 
@@ -2143,7 +2199,10 @@ handle_inferior_event (ecs)
            gdb_flush (gdb_stdout);
          }
        if (signal_stop[stop_signal])
-         goto wfi_break;
+         {
+           stop_stepping (ecs);
+           return;
+         }
        /* If not going to stop, give terminal back
           if we took it away.  */
        else if (printed)
@@ -2165,7 +2224,7 @@ handle_inferior_event (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
@@ -2185,7 +2244,7 @@ handle_inferior_event (ecs)
            this probably breaks that.  As with anything else, it's up to
            the HP-UX maintainer to furnish a fix that doesn't break other
            platforms.  --JimB, 20 May 1999 */
-       goto check_sigtramp2;
+       check_sigtramp2 (ecs);
       }
 
     /* Handle cases caused by hitting a breakpoint.  */
@@ -2213,7 +2272,10 @@ handle_inferior_event (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 */
@@ -2239,7 +2301,8 @@ handle_inferior_event (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:
@@ -2252,7 +2315,8 @@ handle_inferior_event (ecs)
                              step_frame_address)))
            {
              ecs->another_trap = 1;
-             goto keep_going;
+             keep_going (ecs);
+             return;
            }
 #endif /* 0 */
          disable_longjmp_breakpoint ();
@@ -2280,7 +2344,8 @@ handle_inferior_event (ecs)
             through_sigtramp_breakpoint via the cleanup chain, so
             no need to worry about it here.  */
 
-         goto stop_stepping;
+         stop_stepping (ecs);
+         return;
 
        case BPSTAT_WHAT_STOP_SILENT:
          stop_print_frame = 0;
@@ -2289,7 +2354,8 @@ handle_inferior_event (ecs)
             through_sigtramp_breakpoint via the cleanup chain, so
             no need to worry about it here.  */
 
-         goto stop_stepping;
+         stop_stepping (ecs);
+         return;
 
        case BPSTAT_WHAT_STEP_RESUME:
          /* This proably demands a more elegant solution, but, yeah
@@ -2303,7 +2369,12 @@ handle_inferior_event (ecs)
             If we reach here and step_resume_breakpoint is already
             NULL, then apparently we have multiple active
             step-resume bp's.  We'll just delete the breakpoint we
-            stopped at, and carry on.  */
+            stopped at, and carry on.  
+
+            Correction: what the code currently does is delete a
+            step-resume bp, but it makes no effort to ensure that
+            the one deleted is the one currently stopped at.  MVS  */
+
          if (step_resume_breakpoint == NULL)
            {
              step_resume_breakpoint =
@@ -2357,7 +2428,8 @@ handle_inferior_event (ecs)
            if (stop_on_solib_events)
              {
                stop_print_frame = 0;
-               goto stop_stepping;
+               stop_stepping (ecs);
+               return;
              }
 
            /* If we stopped due to an explicit catchpoint, then the
@@ -2427,7 +2499,8 @@ handle_inferior_event (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
@@ -2437,7 +2510,8 @@ handle_inferior_event (ecs)
        stop_bpstat = bpstat_copy (ecs->stepping_through_solib_catchpoints);
        bpstat_clear (&ecs->stepping_through_solib_catchpoints);
        stop_print_frame = 1;
-       goto stop_stepping;
+       stop_stepping (ecs);
+       return;
       }
 
     if (!CALL_DUMMY_BREAKPOINT_OFFSET_P)
@@ -2460,23 +2534,32 @@ handle_inferior_event (ecs)
 #ifdef HP_OS_BUG
            trap_expected_after_continue = 1;
 #endif
-           goto wfi_break;
+           stop_stepping (ecs);
+           return;
          }
       }
 
     if (step_resume_breakpoint)
-      /* Having a step-resume breakpoint overrides anything
-         else having to do with stepping commands until
-         that breakpoint is reached.  */
-      /* I'm not sure whether this needs to be check_sigtramp2 or
-         whether it could/should be keep_going.  */
-      goto check_sigtramp2;
-
+      {
+       /* Having a step-resume breakpoint overrides anything
+          else having to do with stepping commands until
+          that breakpoint is reached.  */
+       /* I'm not sure whether this needs to be check_sigtramp2 or
+          whether it could/should be keep_going.  */
+       check_sigtramp2 (ecs);
+       keep_going (ecs);
+       return;
+      }
+    
     if (step_range_end == 0)
-      /* Likewise if we aren't even stepping.  */
-      /* I'm not sure whether this needs to be check_sigtramp2 or
-         whether it could/should be keep_going.  */
-      goto check_sigtramp2;
+      {
+       /* Likewise if we aren't even stepping.  */
+       /* I'm not sure whether this needs to be check_sigtramp2 or
+          whether it could/should be keep_going.  */
+       check_sigtramp2 (ecs);
+       keep_going (ecs);
+       return;
+      }
 
     /* If stepping through a line, keep going if still within it.
 
@@ -2488,7 +2571,9 @@ handle_inferior_event (ecs)
       {
        /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
           So definately need to check for sigtramp here.  */
-       goto check_sigtramp2;
+       check_sigtramp2 (ecs);
+       keep_going (ecs);
+       return;
       }
 
     /* We stepped out of the stepping range.  */
@@ -2498,7 +2583,27 @@ handle_inferior_event (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.
@@ -2557,7 +2662,7 @@ handle_inferior_event (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
@@ -2586,7 +2691,8 @@ handle_inferior_event (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 */
@@ -2603,12 +2709,17 @@ handle_inferior_event (ecs)
               supposed to be stepping at the assembly language level
               ("stepi").  Just stop.  */
            stop_step = 1;
-           goto wfi_break;
+           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".  */
+           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
@@ -2633,7 +2744,8 @@ handle_inferior_event (ecs)
                step_resume_breakpoint =
                  set_momentary_breakpoint (xxx, NULL, bp_step_resume);
                insert_breakpoints ();
-               goto keep_going;
+               keep_going (ecs);
+               return;
              }
          }
 
@@ -2648,95 +2760,15 @@ handle_inferior_event (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;
-           goto wfi_break;
-         }
-       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.  */
@@ -2748,7 +2780,8 @@ handle_inferior_event (ecs)
        /* It is stepi or nexti.  We always want to stop stepping after
           one instruction.  */
        stop_step = 1;
-       goto wfi_break;
+       stop_stepping (ecs);
+       return;
       }
 
     /* If we're in the return path from a shared library trampoline,
@@ -2780,7 +2813,8 @@ handle_inferior_event (ecs)
 
            /* Restart without fiddling with the step ranges or
               other state.  */
-           goto keep_going;
+           keep_going (ecs);
+           return;
          }
       }
 
@@ -2791,7 +2825,8 @@ handle_inferior_event (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;
-       goto wfi_break;
+       stop_stepping (ecs);
+       return;
       }
 
     if ((stop_pc == ecs->sal.pc)
@@ -2802,7 +2837,8 @@ handle_inferior_event (ecs)
           That is said to make things like for (;;) statements work
           better.  */
        stop_step = 1;
-       goto wfi_break;
+       stop_stepping (ecs);
+       return;
       }
 
     /* We aren't done stepping.
@@ -2820,7 +2856,8 @@ handle_inferior_event (ecs)
           in which after skipping the prologue we better stop even though
           we will be in mid-line.  */
        stop_step = 1;
-       goto wfi_break;
+       stop_stepping (ecs);
+       return;
       }
     step_range_start = ecs->sal.pc;
     step_range_end = ecs->sal.end;
@@ -2837,182 +2874,160 @@ handle_inferior_event (ecs)
        step_frame_address = current_frame;
     }
 
+    keep_going (ecs);
 
-    goto keep_going;
-
-  check_sigtramp2:
-    if (trap_expected
-       && IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
-       && !IN_SIGTRAMP (prev_pc, prev_func_name)
-       && INNER_THAN (read_sp (), step_sp))
-      {
-       /* What has happened here is that we have just stepped the inferior
-          with a signal (because it is a signal which shouldn't make
-          us stop), thus stepping into sigtramp.
-
-          So we need to set a step_resume_break_address breakpoint
-          and continue until we hit it, and then step.  FIXME: This should
-          be more enduring than a step_resume breakpoint; we should know
-          that we will later need to keep going rather than re-hitting
-          the breakpoint here (see testsuite/gdb.t06/signals.exp where
-          it says "exceedingly difficult").  */
-       struct symtab_and_line sr_sal;
-
-       INIT_SAL (&sr_sal);     /* initialize to zeroes */
-       sr_sal.pc = prev_pc;
-       sr_sal.section = find_pc_overlay (sr_sal.pc);
-       /* We perhaps could set the frame if we kept track of what
-          the frame corresponding to prev_pc was.  But we don't,
-          so don't.  */
-       through_sigtramp_breakpoint =
-         set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp);
-       if (breakpoints_inserted)
-         insert_breakpoints ();
+  } /* extra brace, to preserve old indentation */
+}
 
-       ecs->remove_breakpoints_on_following_step = 1;
-       ecs->another_trap = 1;
-      }
+/* Are we in the middle of stepping?  */
 
-  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;
+static int
+currently_stepping (struct execution_control_state *ecs)
+{
+  return ((through_sigtramp_breakpoint == NULL
+          && !ecs->handling_longjmp
+          && ((step_range_end && step_resume_breakpoint == NULL)
+              || trap_expected))
+         || ecs->stepping_through_solib_after_catch
+         || bpstat_should_step ());
+}
 
-    if (ecs->update_step_sp)
-      step_sp = read_sp ();
-    ecs->update_step_sp = 0;
+static void
+check_sigtramp2 (struct execution_control_state *ecs)
+{
+  if (trap_expected
+      && IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
+      && !IN_SIGTRAMP (prev_pc, prev_func_name)
+      && INNER_THAN (read_sp (), step_sp))
+    {
+      /* What has happened here is that we have just stepped the
+        inferior with a signal (because it is a signal which
+        shouldn't make us stop), thus stepping into sigtramp.
+
+        So we need to set a step_resume_break_address breakpoint and
+        continue until we hit it, and then step.  FIXME: This should
+        be more enduring than a step_resume breakpoint; we should
+        know that we will later need to keep going rather than
+        re-hitting the breakpoint here (see the testsuite,
+        gdb.base/signals.exp where it says "exceedingly difficult").  */
+
+      struct symtab_and_line sr_sal;
+
+      INIT_SAL (&sr_sal);      /* initialize to zeroes */
+      sr_sal.pc = prev_pc;
+      sr_sal.section = find_pc_overlay (sr_sal.pc);
+      /* We perhaps could set the frame if we kept track of what the
+        frame corresponding to prev_pc was.  But we don't, so don't.  */
+      through_sigtramp_breakpoint =
+       set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp);
+      if (breakpoints_inserted)
+       insert_breakpoints ();
 
-    /* If we did not do break;, it means we should keep
-       running the inferior and not return to debugger.  */
+      ecs->remove_breakpoints_on_following_step = 1;
+      ecs->another_trap = 1;
+    }
+}
 
-    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)
-             goto wfi_break;
-           breakpoints_inserted = 1;
-         }
+/* Subroutine call with source code we should not step over.  Do step
+   to the first line of code in it.  */
 
-       trap_expected = ecs->another_trap;
+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
 
-       /* Do not deliver SIGNAL_TRAP (except when the user
-          explicitly specifies that such a signal should be
-          delivered to the target program).
+  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.  */
+      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 ();
 
-          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. */
+      /* And make sure stepping stops right away then.  */
+      step_range_end = step_range_start;
+    }
+  keep_going (ecs);
+}
 
-       if (stop_signal == TARGET_SIGNAL_TRAP
-           && !signal_program[stop_signal])
-         stop_signal = TARGET_SIGNAL_0;
+/* 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.
 
-#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 */
+   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).  */
 
-       resume (currently_stepping (ecs), stop_signal);
-      }
+static void
+step_over_function (struct execution_control_state *ecs)
+{
+  struct symtab_and_line sr_sal;
 
-    /* Former continues in the main loop goto here.  */
-  wfi_continue:
-    /* This used to be at the top of the loop.  */
-    if (ecs->infwait_state == infwait_normal_state)
-      {
-       overlay_cache_invalid = 1;
+  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);
 
-       /* We have to invalidate the registers BEFORE calling
-          target_wait because they can be loaded from the target
-          while in target_wait.  This makes remote debugging a bit
-          more efficient for those targets that provide critical
-          registers as part of their normal status mechanism. */
+  check_for_old_step_resume_breakpoint ();
+  step_resume_breakpoint =
+    set_momentary_breakpoint (sr_sal, get_current_frame (), bp_step_resume);
 
-       registers_changed ();
-       ecs->waiton_pid = -1;
-       ecs->wp = &(ecs->ws);
-      }
-    /* This is the old end of the while loop.  Let everybody know
-       we want to wait for the inferior some more and get called
-       again soon.  */
-    ecs->wait_some_more = 1;
-    return;
-  }
+  if (!IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
+    step_resume_breakpoint->frame = step_frame_address;
 
-  /* Former breaks in the main loop goto here.  */
-wfi_break:
+  if (breakpoints_inserted)
+    insert_breakpoints ();
+}
 
-stop_stepping:
+static void
+stop_stepping (struct execution_control_state *ecs)
+{
   if (target_has_execution)
     {
       /* Are we stopping for a vfork event?  We only stop when we see
          the child's event.  However, we may not yet have seen the
-         parent's event.  And, inferior_pid is still set to the parent's
-         pid, until we resume again and follow either the parent or child.
+         parent's event.  And, inferior_pid is still set to the
+         parent's pid, until we resume again and follow either the
+         parent or child.
 
          To ensure that we can really touch inferior_pid (aka, the
          parent process) -- which calls to functions like read_pc
@@ -3039,22 +3054,148 @@ stop_stepping:
       prev_func_start = ecs->stop_func_start;
       prev_func_name = ecs->stop_func_name;
     }
+
   /* Let callers know we don't want to wait for the inferior anymore.  */
   ecs->wait_some_more = 0;
 }
 
-/* Are we in the middle of stepping?  */
+/* 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 int
-currently_stepping (ecs)
-     struct execution_control_state *ecs;
+static void
+keep_going (struct execution_control_state *ecs)
 {
-  return ((through_sigtramp_breakpoint == NULL
-          && !ecs->handling_longjmp
-          && ((step_range_end && step_resume_breakpoint == NULL)
-              || trap_expected))
-         || ecs->stepping_through_solib_after_catch
-         || bpstat_should_step ());
+  /* ??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.  */
+
+static void
+prepare_to_wait (struct execution_control_state *ecs)
+{
+  if (ecs->infwait_state == infwait_normal_state)
+    {
+      overlay_cache_invalid = 1;
+
+      /* We have to invalidate the registers BEFORE calling
+        target_wait because they can be loaded from the target while
+        in target_wait.  This makes remote debugging a bit more
+        efficient for those targets that provide critical registers
+        as part of their normal status mechanism. */
+
+      registers_changed ();
+      ecs->waiton_pid = -1;
+      ecs->wp = &(ecs->ws);
+    }
+  /* This is the old end of the while loop.  Let everybody know we
+     want to wait for the inferior some more and get called again
+     soon.  */
+  ecs->wait_some_more = 1;
 }
 
 /* This function returns TRUE if ep is an internal breakpoint
@@ -3064,8 +3205,7 @@ currently_stepping (ecs)
    something gdb sets for its own use, and isn't ever shown to a
    user.) */
 static int
-is_internal_shlib_eventpoint (ep)
-     struct breakpoint *ep;
+is_internal_shlib_eventpoint (struct breakpoint *ep)
 {
   return
     (ep->type == bp_shlib_event)
@@ -3075,9 +3215,9 @@ is_internal_shlib_eventpoint (ep)
 /* 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 (bs)
-     bpstat bs;
+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. */
@@ -3091,57 +3231,8 @@ stopped_for_internal_shlib_event (bs)
   /* If we get here, then no candidate was found. */
   return 0;
 }
-
-/* This function returns TRUE if bs indicates that the inferior
-   stopped due to a shared library (aka dynamically-linked library)
-   event caught by a catchpoint.
-
-   If TRUE, cp_p is set to point to the catchpoint.
-
-   Else, the value of cp_p is undefined. */
-static int
-stopped_for_shlib_catchpoint (bs, cp_p)
-     bpstat bs;
-     struct breakpoint **cp_p;
-{
-  /* Note that multiple eventpoints may've caused the stop.  Any
-     that are associated with shlib events will be accepted. */
-  *cp_p = NULL;
-
-  for (; bs != NULL; bs = bs->next)
-    {
-      if ((bs->breakpoint_at != NULL)
-         && ep_is_shlib_catchpoint (bs->breakpoint_at))
-       {
-         *cp_p = 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. */
-static void
-complete_execution ()
-{
-  extern cleanup_sigint_signal_handler PARAMS ((void));
-
-  target_executing = 0;
-  if (sync_execution)
-    {
-      add_file_handler (input_fd, (file_handler_func *) call_readline, 0);
-      pop_prompt ();
-      sync_execution = 0;
-      cleanup_sigint_signal_handler ();
-      display_gdb_prompt (0);
-    }
-}
-
 /* Here to return control to GDB when the inferior stops for real.
    Print appropriate messages, remove breakpoints, give terminal our modes.
 
@@ -3151,7 +3242,7 @@ complete_execution ()
    attempting to insert breakpoints.  */
 
 void
-normal_stop ()
+normal_stop (void)
 {
   /* As with the notification of thread events, we want to delay
      notifying the user that we've switched thread context until
@@ -3313,47 +3404,70 @@ done:
 }
 
 static int
-hook_stop_stub (cmd)
-     PTR cmd;
+hook_stop_stub (void *cmd)
 {
   execute_user_command ((struct cmd_list_element *) cmd, 0);
   return (0);
 }
 \f
 int
-signal_stop_state (signo)
-     int signo;
+signal_stop_state (int signo)
 {
   return signal_stop[signo];
 }
 
 int
-signal_print_state (signo)
-     int signo;
+signal_print_state (int signo)
 {
   return signal_print[signo];
 }
 
 int
-signal_pass_state (signo)
-     int signo;
+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 ()
+sig_print_header (void)
 {
   printf_filtered ("\
 Signal        Stop\tPrint\tPass to program\tDescription\n");
 }
 
 static void
-sig_print_info (oursig)
-     enum target_signal oursig;
+sig_print_info (enum target_signal oursig)
 {
   char *name = target_signal_to_name (oursig);
   int name_padding = 13 - strlen (name);
+
   if (name_padding <= 0)
     name_padding = 0;
 
@@ -3369,9 +3483,7 @@ sig_print_info (oursig)
 /* Specify how various signals in the inferior should be handled.  */
 
 static void
-handle_command (args, from_tty)
-     char *args;
-     int from_tty;
+handle_command (char *args, int from_tty)
 {
   char **argv;
   int digits, wordlen;
@@ -3553,9 +3665,7 @@ Are you sure you want to change it? ",
 }
 
 static void
-xdb_handle_command (args, from_tty)
-     char *args;
-     int from_tty;
+xdb_handle_command (char *args, int from_tty)
 {
   char **argv;
   struct cleanup *old_chain;
@@ -3627,9 +3737,7 @@ xdb_handle_command (args, from_tty)
    targets, all signals should be in the signal tables).  */
 
 static void
-signals_info (signum_exp, from_tty)
-     char *signum_exp;
-     int from_tty;
+signals_info (char *signum_exp, int from_tty)
 {
   enum target_signal oursig;
   sig_print_header ();
@@ -3695,10 +3803,8 @@ struct inferior_status
   int proceed_to_finish;
 };
 
-
-static struct inferior_status *xmalloc_inferior_status PARAMS ((void));
 static struct inferior_status *
-xmalloc_inferior_status ()
+xmalloc_inferior_status (void)
 {
   struct inferior_status *inf_status;
   inf_status = xmalloc (sizeof (struct inferior_status));
@@ -3707,10 +3813,8 @@ xmalloc_inferior_status ()
   return inf_status;
 }
 
-static void free_inferior_status PARAMS ((struct inferior_status *));
 static void
-free_inferior_status (inf_status)
-     struct inferior_status *inf_status;
+free_inferior_status (struct inferior_status *inf_status)
 {
   free (inf_status->registers);
   free (inf_status->stop_registers);
@@ -3718,10 +3822,8 @@ free_inferior_status (inf_status)
 }
 
 void
-write_inferior_status_register (inf_status, regno, val)
-     struct inferior_status *inf_status;
-     int regno;
-     LONGEST val;
+write_inferior_status_register (struct inferior_status *inf_status, int regno,
+                               LONGEST val)
 {
   int size = REGISTER_RAW_SIZE (regno);
   void *buf = alloca (size);
@@ -3729,15 +3831,12 @@ write_inferior_status_register (inf_status, regno, val)
   memcpy (&inf_status->registers[REGISTER_BYTE (regno)], buf, size);
 }
 
-
-
 /* Save all of the information associated with the inferior<==>gdb
    connection.  INF_STATUS is a pointer to a "struct inferior_status"
    (defined in inferior.h).  */
 
 struct inferior_status *
-save_inferior_status (restore_stack_info)
-     int restore_stack_info;
+save_inferior_status (int restore_stack_info)
 {
   struct inferior_status *inf_status = xmalloc_inferior_status ();
 
@@ -3778,11 +3877,8 @@ struct restore_selected_frame_args
   int level;
 };
 
-static int restore_selected_frame PARAMS ((PTR));
-
 static int
-restore_selected_frame (args)
-     PTR args;
+restore_selected_frame (void *args)
 {
   struct restore_selected_frame_args *fr =
   (struct restore_selected_frame_args *) args;
@@ -3813,8 +3909,7 @@ restore_selected_frame (args)
 }
 
 void
-restore_inferior_status (inf_status)
-     struct inferior_status *inf_status;
+restore_inferior_status (struct inferior_status *inf_status)
 {
   stop_signal = inf_status->stop_signal;
   stop_pc = inf_status->stop_pc;
@@ -3871,8 +3966,7 @@ restore_inferior_status (inf_status)
 }
 
 void
-discard_inferior_status (inf_status)
-     struct inferior_status *inf_status;
+discard_inferior_status (struct inferior_status *inf_status)
 {
   /* See save_inferior_status for info on stop_bpstat. */
   bpstat_clear (&inf_status->stop_bpstat);
@@ -3880,10 +3974,8 @@ discard_inferior_status (inf_status)
 }
 
 static void
-set_follow_fork_mode_command (arg, from_tty, c)
-     char *arg;
-     int from_tty;
-     struct cmd_list_element *c;
+set_follow_fork_mode_command (char *arg, int from_tty,
+                             struct cmd_list_element *c)
 {
   if (!STREQ (arg, "parent") &&
       !STREQ (arg, "child") &&
@@ -3896,18 +3988,14 @@ set_follow_fork_mode_command (arg, from_tty, c)
   follow_fork_mode_string = savestring (arg, strlen (arg));
 }
 \f
-
-
-static void build_infrun PARAMS ((void));
 static void
-build_infrun ()
+build_infrun (void)
 {
   stop_registers = xmalloc (REGISTER_BYTES);
 }
 
-
 void
-_initialize_infrun ()
+_initialize_infrun (void)
 {
   register int i;
   register int numsigs;