2004-03-23 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 0b85cc691c1643b9acb12d10c1bfc32ace434654..aaf6ac85d50db5464adc1df1edaa51684246b14b 100644 (file)
@@ -2,8 +2,8 @@
    process.
 
    Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software
-   Foundation, Inc.
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free
+   Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -44,7 +44,7 @@
 #include "value.h"
 #include "observer.h"
 #include "language.h"
-#include "exec.h"
+#include "gdb_assert.h"
 
 /* Prototypes for local functions */
 
@@ -62,9 +62,6 @@ static int hook_stop_stub (void *);
 
 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 int restore_selected_frame (void *);
 
 static void build_infrun (void);
@@ -341,12 +338,10 @@ static struct
 }
 pending_follow;
 
-static const char follow_fork_mode_ask[] = "ask";
 static const char follow_fork_mode_child[] = "child";
 static const char follow_fork_mode_parent[] = "parent";
 
 static const char *follow_fork_mode_kind_names[] = {
-  follow_fork_mode_ask,
   follow_fork_mode_child,
   follow_fork_mode_parent,
   NULL
@@ -358,16 +353,7 @@ static const char *follow_fork_mode_string = follow_fork_mode_parent;
 static int
 follow_fork (void)
 {
-  const char *follow_mode = follow_fork_mode_string;
-  int follow_child = (follow_mode == follow_fork_mode_child);
-
-  /* Or, did the user not know, and want us to ask? */
-  if (follow_fork_mode_string == follow_fork_mode_ask)
-    {
-      internal_error (__FILE__, __LINE__,
-                     "follow_inferior_fork: \"ask\" mode not implemented");
-      /* follow_mode = follow_fork_mode_...; */
-    }
+  int follow_child = (follow_fork_mode_string == follow_fork_mode_child);
 
   return target_follow_fork (follow_child);
 }
@@ -489,6 +475,14 @@ follow_exec (int pid, char *execd_pathname)
    because we cannot remove the breakpoints in the inferior process
    until after the `wait' in `wait_for_inferior'.  */
 static int singlestep_breakpoints_inserted_p = 0;
+
+/* The thread we inserted single-step breakpoints for.  */
+static ptid_t singlestep_ptid;
+
+/* If another thread hit the singlestep breakpoint, we save the original
+   thread here so that we can resume single-stepping it later.  */
+static ptid_t saved_singlestep_ptid;
+static int stepping_past_singlestep_breakpoint;
 \f
 
 /* Things to clean up if we QUIT out of resume ().  */
@@ -575,6 +569,7 @@ resume (int step, enum target_signal sig)
       /* and do not pull these breakpoints until after a `wait' in
          `wait_for_inferior' */
       singlestep_breakpoints_inserted_p = 1;
+      singlestep_ptid = inferior_ptid;
     }
 
   /* Handle any optimized stores to the inferior NOW...  */
@@ -612,7 +607,8 @@ resume (int step, enum target_signal sig)
       resume_ptid = RESUME_ALL;        /* Default */
 
       if ((step || singlestep_breakpoints_inserted_p) &&
-         !breakpoints_inserted && breakpoint_here_p (read_pc ()))
+         (stepping_past_singlestep_breakpoint
+          || (!breakpoints_inserted && breakpoint_here_p (read_pc ()))))
        {
          /* Stepping past a breakpoint without inserting breakpoints.
             Make sure only the current thread gets to step, so that
@@ -911,6 +907,8 @@ init_wait_for_inferior (void)
   number_of_threads_in_syscalls = 0;
 
   clear_proceed_status ();
+
+  stepping_past_singlestep_breakpoint = 0;
 }
 
 static void
@@ -988,6 +986,7 @@ struct execution_control_state
 
 void init_execution_control_state (struct execution_control_state *ecs);
 
+static void handle_step_into_function (struct execution_control_state *ecs);
 void handle_inferior_event (struct execution_control_state *ecs);
 
 static void check_sigtramp2 (struct execution_control_state *ecs);
@@ -1204,8 +1203,8 @@ context_switch (struct execution_control_state *ecs)
   inferior_ptid = ecs->ptid;
 }
 
-/* Wrapper for PC_IN_SIGTRAMP that takes care of the need to find the
-   function's name.
+/* Wrapper for DEPRECATED_PC_IN_SIGTRAMP that takes care of the need
+   to find the function's name.
 
    In a classic example of "left hand VS right hand", "infrun.c" was
    trying to improve GDB's performance by caching the result of calls
@@ -1234,9 +1233,176 @@ pc_in_sigtramp (CORE_ADDR pc)
 {
   char *name;
   find_pc_partial_function (pc, &name, NULL, NULL);
-  return PC_IN_SIGTRAMP (pc, name);
+  return DEPRECATED_PC_IN_SIGTRAMP (pc, name);
+}
+
+/* Handle the inferior event in the cases when we just stepped
+   into a function.  */
+
+static void
+handle_step_into_function (struct execution_control_state *ecs)
+{
+  CORE_ADDR real_stop_pc;
+
+  if ((step_over_calls == STEP_OVER_NONE)
+      || ((step_range_end == 1)
+          && in_prologue (prev_pc, ecs->stop_func_start)))
+    {
+      /* I presume that step_over_calls is only 0 when we're
+         supposed to be stepping at the assembly language level
+         ("stepi").  Just stop.  */
+      /* Also, maybe we just did a "nexti" inside a prolog,
+         so we thought it was a subroutine call but it was not.
+         Stop as well.  FENN */
+      stop_step = 1;
+      print_stop_reason (END_STEPPING_RANGE, 0);
+      stop_stepping (ecs);
+      return;
+    }
+
+  if (step_over_calls == STEP_OVER_ALL || IGNORE_HELPER_CALL (stop_pc))
+    {
+      /* We're doing a "next".  */
+
+      if (legacy_frame_p (current_gdbarch)
+         && pc_in_sigtramp (stop_pc)
+          && frame_id_inner (step_frame_id,
+                             frame_id_build (read_sp (), 0)))
+       /* NOTE: cagney/2004-03-15: This is only needed for legacy
+          systems.  On non-legacy systems step_over_function doesn't
+          use STEP_FRAME_ID and hence the below update "hack" isn't
+          needed.  */
+        /* 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_id, 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_id = null_frame_id;
+
+      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
+     function.  That's what tells us (a) whether we want to step
+     into it at all, and (b) what prologue we want to run to
+     the end of, if we do step into it.  */
+  real_stop_pc = skip_language_trampoline (stop_pc);
+  if (real_stop_pc == 0)
+    real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+  if (real_stop_pc != 0)
+    ecs->stop_func_start = real_stop_pc;
+
+  /* If we have line number information for the function we
+     are thinking of stepping into, step into it.
+
+     If there are several symtabs at that PC (e.g. with include
+     files), just want to know whether *any* of them have line
+     numbers.  find_pc_line handles this.  */
+  {
+    struct symtab_and_line tmp_sal;
+
+    tmp_sal = find_pc_line (ecs->stop_func_start, 0);
+    if (tmp_sal.line != 0)
+      {
+        step_into_function (ecs);
+        return;
+      }
+  }
+
+  /* If we have no line number and the step-stop-if-no-debug
+     is set, we stop the step so that the user has a chance to
+     switch in assembly mode.  */
+  if (step_over_calls == STEP_OVER_UNDEBUGGABLE && step_stop_if_no_debug)
+    {
+      stop_step = 1;
+      print_stop_reason (END_STEPPING_RANGE, 0);
+      stop_stepping (ecs);
+      return;
+    }
+
+  step_over_function (ecs);
+  keep_going (ecs);
+  return;
 }
 
+static void
+adjust_pc_after_break (struct execution_control_state *ecs)
+{
+  CORE_ADDR stop_pc;
+
+  /* If this target does not decrement the PC after breakpoints, then
+     we have nothing to do.  */
+  if (DECR_PC_AFTER_BREAK == 0)
+    return;
+
+  /* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP.  If
+     we aren't, just return.
+
+     We assume that waitkinds other than TARGET_WAITKIND_STOPPED are not
+     affected by DECR_PC_AFTER_BREAK.  Other waitkinds which are implemented
+     by software breakpoints should be handled through the normal breakpoint
+     layer.
+     
+     NOTE drow/2004-01-31: On some targets, breakpoints may generate
+     different signals (SIGILL or SIGEMT for instance), but it is less
+     clear where the PC is pointing afterwards.  It may not match
+     DECR_PC_AFTER_BREAK.  I don't know any specific target that generates
+     these signals at breakpoints (the code has been in GDB since at least
+     1992) so I can not guess how to handle them here.
+     
+     In earlier versions of GDB, a target with HAVE_NONSTEPPABLE_WATCHPOINTS
+     would have the PC after hitting a watchpoint affected by
+     DECR_PC_AFTER_BREAK.  I haven't found any target with both of these set
+     in GDB history, and it seems unlikely to be correct, so
+     HAVE_NONSTEPPABLE_WATCHPOINTS is not checked here.  */
+
+  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
+    return;
+
+  if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
+    return;
+
+  /* Find the location where (if we've hit a breakpoint) the breakpoint would
+     be.  */
+  stop_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
+
+  /* If we're software-single-stepping, then assume this is a breakpoint.
+     NOTE drow/2004-01-17: This doesn't check that the PC matches, or that
+     we're even in the right thread.  The software-single-step code needs
+     some modernization.
+
+     If we're not software-single-stepping, then we first check that there
+     is an enabled software breakpoint at this address.  If there is, and
+     we weren't using hardware-single-step, then we've hit the breakpoint.
+
+     If we were using hardware-single-step, we check prev_pc; if we just
+     stepped over an inserted software breakpoint, then we should decrement
+     the PC and eventually report hitting the breakpoint.  The prev_pc check
+     prevents us from decrementing the PC if we just stepped over a jump
+     instruction and landed on the instruction after a breakpoint.
+
+     The last bit checks that 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.
+
+     NOTE drow/2004-01-17: I'm not sure that this is necessary.  The check
+     predates checking for software single step at the same time.  Also,
+     if we've moved into a signal handler we should have seen the
+     signal.  */
+
+  if ((SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+      || (software_breakpoint_inserted_here_p (stop_pc)
+         && !(currently_stepping (ecs)
+              && prev_pc != stop_pc
+              && !(step_range_end && INNER_THAN (read_sp (), (step_sp - 16))))))
+    write_pc_pid (stop_pc, ecs->ptid);
+}
 
 /* Given an execution control state that has been freshly filled in
    by an event from the inferior, figure out what it means and take
@@ -1245,7 +1411,6 @@ pc_in_sigtramp (CORE_ADDR pc)
 void
 handle_inferior_event (struct execution_control_state *ecs)
 {
-  CORE_ADDR real_stop_pc;
   /* NOTE: cagney/2003-03-28: If you're looking at this code and
      thinking that the variable stepped_after_stopped_by_watchpoint
      isn't used, then you're wrong!  The macro STOPPED_BY_WATCHPOINT,
@@ -1258,6 +1423,8 @@ handle_inferior_event (struct execution_control_state *ecs)
   target_last_wait_ptid = ecs->ptid;
   target_last_waitstatus = *ecs->wp;
 
+  adjust_pc_after_break (ecs);
+
   switch (ecs->infwait_state)
     {
     case infwait_thread_hop_state:
@@ -1363,7 +1530,22 @@ handle_inferior_event (struct execution_control_state *ecs)
             terminal for any messages produced by
             breakpoint_re_set.  */
          target_terminal_ours_for_output ();
-         SOLIB_ADD (NULL, 0, &exec_ops, auto_solib_add);
+         /* NOTE: cagney/2003-11-25: Make certain that the target
+             stack's section table is kept up-to-date.  Architectures,
+             (e.g., PPC64), use the section table to perform
+             operations such as address => section name and hence
+             require the table to contain all sections (including
+             those found in shared libraries).  */
+         /* NOTE: cagney/2003-11-25: Pass current_target and not
+             exec_ops to SOLIB_ADD.  This is because current GDB is
+             only tooled to propagate section_table changes out from
+             the "current_target" (see target_resize_to_sections), and
+             not up from the exec stratum.  This, of course, isn't
+             right.  "infrun.c" should only interact with the
+             exec/process stratum, instead relying on the target stack
+             to propagate relevant changes (stop, section table
+             changed, ...) up to other layers.  */
+         SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
          target_terminal_inferior ();
 
          /* Reinsert breakpoints and continue.  */
@@ -1425,13 +1607,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       stop_pc = read_pc ();
 
-      /* Assume that catchpoints are not really software breakpoints.  If
-        some future target implements them using software breakpoints then
-        that target is responsible for fudging DECR_PC_AFTER_BREAK.  Thus
-        we pass 1 for the NOT_A_SW_BREAKPOINT argument, so that
-        bpstat_stop_status will not decrement the PC.  */
-
-      stop_bpstat = bpstat_stop_status (&stop_pc, 1);
+      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
 
       ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
 
@@ -1480,13 +1656,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       ecs->saved_inferior_ptid = inferior_ptid;
       inferior_ptid = ecs->ptid;
 
-      /* Assume that catchpoints are not really software breakpoints.  If
-        some future target implements them using software breakpoints then
-        that target is responsible for fudging DECR_PC_AFTER_BREAK.  Thus
-        we pass 1 for the NOT_A_SW_BREAKPOINT argument, so that
-        bpstat_stop_status will not decrement the PC.  */
-
-      stop_bpstat = bpstat_stop_status (&stop_pc, 1);
+      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
 
       ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
       inferior_ptid = ecs->saved_inferior_ptid;
@@ -1587,28 +1757,84 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   stop_pc = read_pc_pid (ecs->ptid);
 
+  if (stepping_past_singlestep_breakpoint)
+    {
+      gdb_assert (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p);
+      gdb_assert (ptid_equal (singlestep_ptid, ecs->ptid));
+      gdb_assert (!ptid_equal (singlestep_ptid, saved_singlestep_ptid));
+
+      stepping_past_singlestep_breakpoint = 0;
+
+      /* We've either finished single-stepping past the single-step
+        breakpoint, or stopped for some other reason.  It would be nice if
+        we could tell, but we can't reliably.  */
+      if (stop_signal == TARGET_SIGNAL_TRAP)
+        {
+         /* Pull the single step breakpoints out of the target.  */
+         SOFTWARE_SINGLE_STEP (0, 0);
+         singlestep_breakpoints_inserted_p = 0;
+
+         ecs->random_signal = 0;
+
+         ecs->ptid = saved_singlestep_ptid;
+         context_switch (ecs);
+         if (context_hook)
+           context_hook (pid_to_thread_id (ecs->ptid));
+
+         resume (1, TARGET_SIGNAL_0);
+         prepare_to_wait (ecs);
+         return;
+       }
+    }
+
+  stepping_past_singlestep_breakpoint = 0;
+
   /* See if a thread hit a thread-specific breakpoint that was meant for
      another thread.  If so, then step that thread past the breakpoint,
      and continue it.  */
 
   if (stop_signal == TARGET_SIGNAL_TRAP)
     {
+      int thread_hop_needed = 0;
+
       /* Check if a regular breakpoint has been hit before checking
          for a potential single step breakpoint. Otherwise, GDB will
          not see this breakpoint hit when stepping onto breakpoints.  */
-      if (breakpoints_inserted
-          && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+      if (breakpoints_inserted && breakpoint_here_p (stop_pc))
        {
          ecs->random_signal = 0;
-         if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK,
-                                       ecs->ptid))
+         if (!breakpoint_thread_match (stop_pc, ecs->ptid))
+           thread_hop_needed = 1;
+       }
+      else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+       {
+         ecs->random_signal = 0;
+         /* The call to in_thread_list is necessary because PTIDs sometimes
+            change when we go from single-threaded to multi-threaded.  If
+            the singlestep_ptid is still in the list, assume that it is
+            really different from ecs->ptid.  */
+         if (!ptid_equal (singlestep_ptid, ecs->ptid)
+             && in_thread_list (singlestep_ptid))
+           {
+             thread_hop_needed = 1;
+             stepping_past_singlestep_breakpoint = 1;
+             saved_singlestep_ptid = singlestep_ptid;
+           }
+       }
+
+      if (thread_hop_needed)
            {
              int remove_status;
 
              /* Saw a breakpoint, but it was hit by the wrong thread.
                 Just continue. */
-             if (DECR_PC_AFTER_BREAK)
-               write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, ecs->ptid);
+
+             if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+               {
+                 /* Pull the single step breakpoints out of the target. */
+                 SOFTWARE_SINGLE_STEP (0, 0);
+                 singlestep_breakpoints_inserted_p = 0;
+               }
 
              remove_status = remove_breakpoints ();
              /* Did we fail to remove breakpoints?  If so, try
@@ -1621,7 +1847,7 @@ handle_inferior_event (struct execution_control_state *ecs)
              if (remove_status != 0)
                {
                  /* FIXME!  This is obviously non-portable! */
-                 write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK + 4, ecs->ptid);
+                 write_pc_pid (stop_pc + 4, ecs->ptid);
                  /* We need to restart all the threads now,
                   * unles we're running in scheduler-locked mode. 
                   * Use currently_stepping to determine whether to 
@@ -1651,21 +1877,9 @@ handle_inferior_event (struct execution_control_state *ecs)
                  registers_changed ();
                  return;
                }
-           }
        }
       else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
         {
-          /* Readjust the stop_pc as it is off by DECR_PC_AFTER_BREAK
-             compared to the value it would have if the system stepping
-             capability was used. This allows the rest of the code in
-             this function to use this address without having to worry
-             whether software single step is in use or not.  */
-          if (DECR_PC_AFTER_BREAK)
-            {
-              stop_pc -= DECR_PC_AFTER_BREAK;
-              write_pc_pid (stop_pc, ecs->ptid);
-            }
-
           sw_single_step_trap_p = 1;
           ecs->random_signal = 0;
         }
@@ -1674,61 +1888,9 @@ handle_inferior_event (struct execution_control_state *ecs)
     ecs->random_signal = 1;
 
   /* See if something interesting happened to the non-current thread.  If
-     so, then switch to that thread, and eventually give control back to
-     the user.
-
-     Note that if there's any kind of pending follow (i.e., of a fork,
-     vfork or exec), we don't want to do this now.  Rather, we'll let
-     the next resume handle it. */
-  if (!ptid_equal (ecs->ptid, inferior_ptid) &&
-      (pending_follow.kind == TARGET_WAITKIND_SPURIOUS))
+     so, then switch to that thread.  */
+  if (!ptid_equal (ecs->ptid, inferior_ptid))
     {
-      int printed = 0;
-
-      /* If it's a random signal for a non-current thread, notify user
-         if he's expressed an interest. */
-      if (ecs->random_signal && signal_print[stop_signal])
-       {
-/* ??rehrauer: I don't understand the rationale for this code.  If the
-   inferior will stop as a result of this signal, then the act of handling
-   the stop ought to print a message that's couches the stoppage in user
-   terms, e.g., "Stopped for breakpoint/watchpoint".  If the inferior
-   won't stop as a result of the signal -- i.e., if the signal is merely
-   a side-effect of something GDB's doing "under the covers" for the
-   user, such as stepping threads over a breakpoint they shouldn't stop
-   for -- then the message seems to be a serious annoyance at best.
-
-   For now, remove the message altogether. */
-#if 0
-         printed = 1;
-         target_terminal_ours_for_output ();
-         printf_filtered ("\nProgram received signal %s, %s.\n",
-                          target_signal_to_name (stop_signal),
-                          target_signal_to_string (stop_signal));
-         gdb_flush (gdb_stdout);
-#endif
-       }
-
-      /* If it's not SIGTRAP and not a signal we want to stop for, then
-         continue the thread. */
-
-      if (stop_signal != TARGET_SIGNAL_TRAP && !signal_stop[stop_signal])
-       {
-         if (printed)
-           target_terminal_inferior ();
-
-         /* Clear the signal if it should not be passed.  */
-         if (signal_program[stop_signal] == 0)
-           stop_signal = TARGET_SIGNAL_0;
-
-         target_resume (ecs->ptid, 0, stop_signal);
-         prepare_to_wait (ecs);
-         return;
-       }
-
-      /* It's a SIGTRAP or a signal we're interested in.  Switch threads,
-         and fall into the rest of wait_for_inferior().  */
-
       context_switch (ecs);
 
       if (context_hook)
@@ -1797,9 +1959,6 @@ handle_inferior_event (struct execution_control_state *ecs)
          includes evaluating watchpoints, things will come to a
          stop in the correct manner.  */
 
-      if (DECR_PC_AFTER_BREAK)
-       write_pc (stop_pc - DECR_PC_AFTER_BREAK);
-
       remove_breakpoints ();
       registers_changed ();
       target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);   /* Single step */
@@ -1841,15 +2000,20 @@ handle_inferior_event (struct execution_control_state *ecs)
      will be made according to the signal handling tables.  */
 
   /* First, distinguish signals caused by the debugger from signals
-     that have to do with the program's own actions.
-     Note that breakpoint insns may cause SIGTRAP or SIGILL
-     or SIGEMT, depending on the operating system version.
-     Here we detect when a SIGILL or SIGEMT is really a breakpoint
-     and change it to SIGTRAP.  */
+     that have to do with the program's own actions.  Note that
+     breakpoint insns may cause SIGTRAP or SIGILL or SIGEMT, depending
+     on the operating system version.  Here we detect when a SIGILL or
+     SIGEMT is really a breakpoint and change it to SIGTRAP.  We do
+     something similar for SIGSEGV, since a SIGSEGV will be generated
+     when we're trying to execute a breakpoint instruction on a
+     non-executable stack.  This happens for call dummy breakpoints
+     for architectures like SPARC that place call dummies on the
+     stack.  */
 
   if (stop_signal == TARGET_SIGNAL_TRAP
       || (breakpoints_inserted &&
          (stop_signal == TARGET_SIGNAL_ILL
+          || stop_signal == TARGET_SIGNAL_SEGV
           || stop_signal == TARGET_SIGNAL_EMT))
       || stop_soon == STOP_QUIETLY
       || stop_soon == STOP_QUIETLY_NO_SIGSTOP)
@@ -1894,29 +2058,8 @@ handle_inferior_event (struct execution_control_state *ecs)
       else
        {
          /* See if there is a breakpoint at the current PC.  */
+         stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
 
-         /* The second argument of bpstat_stop_status is meant to help
-            distinguish between a breakpoint trap and a singlestep trap.
-            This is only important on targets where DECR_PC_AFTER_BREAK
-            is non-zero.  The prev_pc test is meant to distinguish between
-            singlestepping a trap instruction, and singlestepping thru a
-            jump to the instruction following a trap instruction.
-
-             Therefore, pass TRUE if our reason for stopping is
-             something other than hitting a breakpoint.  We do this by
-             checking that either: we detected earlier a software single
-             step trap or, 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.  */
-         stop_bpstat =
-            bpstat_stop_status
-              (&stop_pc,
-               sw_single_step_trap_p
-               || (currently_stepping (ecs)
-                   && prev_pc != stop_pc - DECR_PC_AFTER_BREAK
-                   && !(step_range_end
-                        && INNER_THAN (read_sp (), (step_sp - 16)))));
          /* Following in case break condition called a
             function.  */
          stop_print_frame = 1;
@@ -1933,10 +2076,14 @@ handle_inferior_event (struct execution_control_state *ecs)
 
          If someone ever tries to get get call dummys on a
          non-executable stack to work (where the target would stop
-         with something like a SIGSEG), then those tests might need to
-         be re-instated.  Given, however, that the tests were only
+         with something like a SIGSEGV), then those tests might need
+         to be re-instated.  Given, however, that the tests were only
          enabled when momentary breakpoints were not being used, I
-         suspect that it won't be the case.  */
+         suspect that it won't be the case.
+
+        NOTE: kettenis/2004-02-05: Indeed such checks don't seem to
+        be necessary for call dummies on a non-executable stack on
+        SPARC.  */
 
       if (stop_signal == TARGET_SIGNAL_TRAP)
        ecs->random_signal
@@ -2186,7 +2333,22 @@ process_event_stop_test:
             terminal for any messages produced by
             breakpoint_re_set.  */
          target_terminal_ours_for_output ();
-         SOLIB_ADD (NULL, 0, &exec_ops, auto_solib_add);
+         /* NOTE: cagney/2003-11-25: Make certain that the target
+             stack's section table is kept up-to-date.  Architectures,
+             (e.g., PPC64), use the section table to perform
+             operations such as address => section name and hence
+             require the table to contain all sections (including
+             those found in shared libraries).  */
+         /* NOTE: cagney/2003-11-25: Pass current_target and not
+             exec_ops to SOLIB_ADD.  This is because current GDB is
+             only tooled to propagate section_table changes out from
+             the "current_target" (see target_resize_to_sections), and
+             not up from the exec stratum.  This, of course, isn't
+             right.  "infrun.c" should only interact with the
+             exec/process stratum, instead relying on the target stack
+             to propagate relevant changes (stop, section table
+             changed, ...) up to other layers.  */
+         SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
          target_terminal_inferior ();
 
          /* Try to reenable shared library breakpoints, additional
@@ -2197,7 +2359,7 @@ process_event_stop_test:
             gdb of events.  This allows the user to get control
             and place breakpoints in initializer routines for
             dynamically loaded objects (among other things).  */
-         if (stop_on_solib_events)
+         if (stop_on_solib_events || stop_stack_dummy)
            {
              stop_stepping (ecs);
              return;
@@ -2359,22 +2521,19 @@ process_event_stop_test:
      But we can update it every time we leave the step range.  */
   ecs->update_step_sp = 1;
 
-  /* Did we just take a signal?  */
-  if (pc_in_sigtramp (stop_pc)
-      && !pc_in_sigtramp (prev_pc)
-      && INNER_THAN (read_sp (), step_sp))
+  /* Did we just step into a singal trampoline (either by stepping out
+     of a handler, or by taking a signal)?  */
+  /* NOTE: cagney/2004-03-16: Replaced (except for legacy) a check for
+     "pc_in_sigtramp(stop_pc) != pc_in_sigtramp(step_pc)" with
+     frame_type == SIGTRAMP && !frame_id_eq.  The latter is far more
+     robust as it will correctly handle nested signal trampolines.  */
+  if (legacy_frame_p (current_gdbarch)
+      ? (pc_in_sigtramp (stop_pc)
+        && !pc_in_sigtramp (prev_pc)
+        && INNER_THAN (read_sp (), step_sp))
+      : (get_frame_type (get_current_frame ()) == SIGTRAMP_FRAME
+        && !frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id)))
     {
-      /* We've just taken a signal; go until we are back to
-         the point where we took it and one more.  */
-
-      /* Note: The test above succeeds not only when we stepped
-         into a signal handler, but also when we step past the last
-         statement of a signal handler and end up in the return stub
-         of the signal handler trampoline.  To distinguish between
-         these two cases, check that the frame is INNER_THAN the
-         previous one below. pai/1997-09-11 */
-
-
       {
        struct frame_id current_frame = get_frame_id (get_current_frame ());
 
@@ -2450,88 +2609,8 @@ process_event_stop_test:
       || ecs->stop_func_name == 0)
     {
       /* It's a subroutine call.  */
-
-      if ((step_over_calls == STEP_OVER_NONE)
-         || ((step_range_end == 1)
-             && in_prologue (prev_pc, ecs->stop_func_start)))
-       {
-         /* I presume that step_over_calls is only 0 when we're
-            supposed to be stepping at the assembly language level
-            ("stepi").  Just stop.  */
-         /* Also, maybe we just did a "nexti" inside a prolog,
-            so we thought it was a subroutine call but it was not.
-            Stop as well.  FENN */
-         stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
-         stop_stepping (ecs);
-         return;
-       }
-
-      if (step_over_calls == STEP_OVER_ALL || IGNORE_HELPER_CALL (stop_pc))
-       {
-         /* We're doing a "next".  */
-
-         if (pc_in_sigtramp (stop_pc)
-             && frame_id_inner (step_frame_id,
-                                frame_id_build (read_sp (), 0)))
-           /* 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_id, 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_id = null_frame_id;
-
-         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
-         function.  That's what tells us (a) whether we want to step
-         into it at all, and (b) what prologue we want to run to
-         the end of, if we do step into it.  */
-      real_stop_pc = skip_language_trampoline (stop_pc);
-      if (real_stop_pc == 0)
-       real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
-      if (real_stop_pc != 0)
-       ecs->stop_func_start = real_stop_pc;
-
-      /* If we have line number information for the function we
-         are thinking of stepping into, step into it.
-
-         If there are several symtabs at that PC (e.g. with include
-         files), just want to know whether *any* of them have line
-         numbers.  find_pc_line handles this.  */
-      {
-       struct symtab_and_line tmp_sal;
-
-       tmp_sal = find_pc_line (ecs->stop_func_start, 0);
-       if (tmp_sal.line != 0)
-         {
-           step_into_function (ecs);
-           return;
-         }
-      }
-
-      /* If we have no line number and the step-stop-if-no-debug
-         is set, we stop the step so that the user has a chance to
-         switch in assembly mode.  */
-      if (step_over_calls == STEP_OVER_UNDEBUGGABLE && step_stop_if_no_debug)
-       {
-         stop_step = 1;
-         print_stop_reason (END_STEPPING_RANGE, 0);
-         stop_stepping (ecs);
-         return;
-       }
-
-      step_over_function (ecs);
-      keep_going (ecs);
+      handle_step_into_function (ecs);
       return;
-
     }
 
   /* We've wandered out of the step range.  */
@@ -2553,7 +2632,7 @@ process_event_stop_test:
   if (IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
     {
       /* Determine where this trampoline returns.  */
-      real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+      CORE_ADDR real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
 
       /* Only proceed through if we know where it's going.  */
       if (real_stop_pc)
@@ -2733,6 +2812,29 @@ step_into_function (struct execution_control_state *ecs)
       && ecs->sal.end < ecs->stop_func_end)
     ecs->stop_func_start = ecs->sal.end;
 
+  /* Architectures which require breakpoint adjustment might not be able
+     to place a breakpoint at the computed address.  If so, the test
+     ``ecs->stop_func_start == stop_pc'' will never succeed.  Adjust
+     ecs->stop_func_start to an address at which a breakpoint may be
+     legitimately placed.
+     
+     Note:  kevinb/2004-01-19:  On FR-V, if this adjustment is not
+     made, GDB will enter an infinite loop when stepping through
+     optimized code consisting of VLIW instructions which contain
+     subinstructions corresponding to different source lines.  On
+     FR-V, it's not permitted to place a breakpoint on any but the
+     first subinstruction of a VLIW instruction.  When a breakpoint is
+     set, GDB will adjust the breakpoint address to the beginning of
+     the VLIW instruction.  Thus, we need to make the corresponding
+     adjustment here when computing the stop address.  */
+     
+  if (gdbarch_adjust_breakpoint_address_p (current_gdbarch))
+    {
+      ecs->stop_func_start
+       = gdbarch_adjust_breakpoint_address (current_gdbarch,
+                                            ecs->stop_func_start);
+    }
+
   if (ecs->stop_func_start == stop_pc)
     {
       /* We are already there: stop now.  */
@@ -2768,16 +2870,16 @@ step_into_function (struct execution_control_state *ecs)
      
    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.
+   of the caller.
 
    To do this, we set the step_resume bp's frame to our current
-   caller's frame (step_frame_id, which is set by the "next" or
-   "until" command, before execution begins).  */
+   caller's frame (obtained by doing a frame ID unwind).  */
 
 static void
 step_over_function (struct execution_control_state *ecs)
 {
   struct symtab_and_line sr_sal;
+  struct frame_id sr_id;
 
   init_sal (&sr_sal);          /* initialize to zeros */
 
@@ -2821,13 +2923,45 @@ step_over_function (struct execution_control_state *ecs)
   sr_sal.section = find_pc_overlay (sr_sal.pc);
 
   check_for_old_step_resume_breakpoint ();
-  step_resume_breakpoint =
-    set_momentary_breakpoint (sr_sal, get_frame_id (get_current_frame ()),
-                             bp_step_resume);
 
-  if (frame_id_p (step_frame_id)
-      && !IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
-    step_resume_breakpoint->frame_id = step_frame_id;
+  /* NOTE: cagney/2004-03-15: Code using the current value of
+     "step_frame_id", instead of unwinding that frame ID, removed (at
+     least for non-legacy platforms).  On s390 GNU/Linux, after taking
+     a signal, the program is directly resumed at the signal handler
+     and, consequently, the PC would point at at the first instruction
+     of that signal handler but STEP_FRAME_ID would [incorrectly] at
+     the interrupted code when it should point at the signal
+     trampoline.  By always and locally doing a frame ID unwind, it's
+     possible to assert that the code is always using the correct
+     ID.  */
+  if (legacy_frame_p (current_gdbarch))
+    {
+      if (frame_id_p (step_frame_id)
+         && !IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
+       /* NOTE: cagney/2004-02-27: Use the global state's idea of the
+          stepping frame ID.  I suspect this is done as it is lighter
+          weight than a call to get_prev_frame.  */
+       /* NOTE: cagney/2004-03-15: See comment above about how this
+          is also broken.  */
+       sr_id = step_frame_id;
+      else
+       /* NOTE: cagney/2004-03-15: This is the way it was 'cos this
+          is the way it always was.  It should be using the unwound
+          (or caller's) ID, and not this (or the callee's) ID.  It
+          appeared to work because: legacy architectures used the
+          wrong end of the frame for the ID.stack (inner-most rather
+          than outer-most) so that the callee's id.stack (un
+          adjusted) matched the caller's id.stack giving the
+          "correct" id; more often than not
+          !IN_SOLIB_DYNSYM_RESOLVE_CODE and hence the code above (it
+          was originally later in the function) fixed the ID by using
+          global state.  */
+       sr_id = get_frame_id (get_current_frame ());
+    }
+  else
+    sr_id = get_frame_id (get_prev_frame (get_current_frame ()));
+
+  step_resume_breakpoint = set_momentary_breakpoint (sr_sal, sr_id, bp_step_resume);
 
   if (breakpoints_inserted)
     insert_breakpoints ();
@@ -2916,17 +3050,6 @@ keep_going (struct execution_control_state *ecs)
       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);
     }
@@ -3085,6 +3208,7 @@ normal_stop (void)
       previous_inferior_ptid = inferior_ptid;
     }
 
+  /* NOTE drow/2004-01-17: Is this still necessary?  */
   /* Make sure that the current_frame's pc is correct.  This
      is a correction for setting up the frame info before doing
      DECR_PC_AFTER_BREAK */
@@ -3927,8 +4051,8 @@ _initialize_infrun (void)
   int numsigs;
   struct cmd_list_element *c;
 
-  register_gdbarch_swap (&stop_registers, sizeof (stop_registers), NULL);
-  register_gdbarch_swap (NULL, 0, build_infrun);
+  DEPRECATED_REGISTER_GDBARCH_SWAP (stop_registers);
+  deprecated_register_gdbarch_swap (NULL, 0, build_infrun);
 
   add_info ("signals", signals_info,
            "What debugger does when program gets various signals.\n\
@@ -4037,31 +4161,12 @@ to the user would be loading/unloading of a new library.\n", &setlist), &showlis
   c = add_set_enum_cmd ("follow-fork-mode",
                        class_run,
                        follow_fork_mode_kind_names, &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
-   the "both" option.  */
-/*                      "Set debugger response to a program call of fork \
-   or vfork.\n\
-   A fork or vfork creates a new process.  follow-fork-mode can be:\n\
-   parent  - the original process is debugged after a fork\n\
-   child   - the new process is debugged after a fork\n\
-   both    - both the parent and child are debugged after a fork\n\
-   ask     - the debugger will ask for one of the above choices\n\
-   For \"both\", another copy of the debugger will be started to follow\n\
-   the new child process.  The original debugger will continue to follow\n\
-   the original parent process.  To distinguish their prompts, the\n\
-   debugger copy's prompt will be changed.\n\
-   For \"parent\" or \"child\", the unfollowed process will run free.\n\
-   By default, the debugger will follow the parent process.",
- */
                        "Set debugger response to a program call of fork \
 or vfork.\n\
 A fork or vfork creates a new process.  follow-fork-mode can be:\n\
   parent  - the original process is debugged after a fork\n\
   child   - the new process is debugged after a fork\n\
-  ask     - the debugger will ask for one of the above choices\n\
-For \"parent\" or \"child\", the unfollowed process will run free.\n\
+The unfollowed process will continue to run.\n\
 By default, the debugger will follow the parent process.", &setlist);
   add_show_from_set (c, &showlist);
 
This page took 0.044462 seconds and 4 git commands to generate.