2004-06-07 Randolph Chung <tausq@debian.org>
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 74134e6a6e80e52b181fd4a4481af1527f83aade..f85c49c0e5aba2909dd816434b1540d9364ab577 100644 (file)
@@ -262,14 +262,6 @@ static int trap_expected;
 static int stop_on_solib_events;
 #endif
 
-#ifdef HP_OS_BUG
-/* Nonzero if the next time we try to continue the inferior, it will
-   step one instruction and generate a spurious trace trap.
-   This is used to compensate for a bug in HP-UX.  */
-
-static int trap_expected_after_continue;
-#endif
-
 /* Nonzero means expecting a trace trap
    and should stop the inferior and return silently when it happens.  */
 
@@ -768,18 +760,6 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   if (prepare_to_proceed () && breakpoint_here_p (read_pc ()))
     oneproc = 1;
 
-#ifdef HP_OS_BUG
-  if (trap_expected_after_continue)
-    {
-      /* If (step == 0), a trap will be automatically generated after
-         the first instruction is executed.  Force step one
-         instruction to clear this condition.  This should not occur
-         if step is nonzero, but it is harmless in that case.  */
-      oneproc = 1;
-      trap_expected_after_continue = 0;
-    }
-#endif /* HP_OS_BUG */
-
   if (oneproc)
     /* We will get a trace trap after one instruction.
        Continue it automatically and insert breakpoints then.  */
@@ -880,9 +860,6 @@ init_wait_for_inferior (void)
   /* These are meaningless until the first time through wait_for_inferior.  */
   prev_pc = 0;
 
-#ifdef HP_OS_BUG
-  trap_expected_after_continue = 0;
-#endif
   breakpoints_inserted = 0;
   breakpoint_init_inferior (inf_starting);
 
@@ -950,7 +927,6 @@ struct execution_control_state
   int handling_longjmp;                /* FIXME */
   ptid_t ptid;
   ptid_t saved_inferior_ptid;
-  int update_step_sp;
   int stepping_through_solib_after_catch;
   bpstat stepping_through_solib_catchpoints;
   int enable_hw_watchpoints_after_wait;
@@ -964,11 +940,9 @@ 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 step_into_function (struct execution_control_state *ecs);
-static void step_over_function (struct execution_control_state *ecs);
 static void insert_step_resume_breakpoint (struct frame_info *step_frame,
                                           struct execution_control_state *ecs);
 static void stop_stepping (struct execution_control_state *ecs);
@@ -1103,7 +1077,6 @@ init_execution_control_state (struct execution_control_state *ecs)
   ecs->random_signal = 0;
   ecs->remove_breakpoints_on_following_step = 0;
   ecs->handling_longjmp = 0;   /* FIXME */
-  ecs->update_step_sp = 0;
   ecs->stepping_through_solib_after_catch = 0;
   ecs->stepping_through_solib_catchpoints = NULL;
   ecs->enable_hw_watchpoints_after_wait = 0;
@@ -1162,7 +1135,7 @@ context_switch (struct execution_control_state *ecs)
                         ecs->stepping_through_solib_after_catch,
                         ecs->stepping_through_solib_catchpoints,
                         ecs->stepping_through_sigtramp,
-                        ecs->current_line, ecs->current_symtab, step_sp);
+                        ecs->current_line, ecs->current_symtab);
 
       /* Load infrun state for the new thread.  */
       load_infrun_state (ecs->ptid, &prev_pc,
@@ -1173,91 +1146,15 @@ context_switch (struct execution_control_state *ecs)
                         &ecs->stepping_through_solib_after_catch,
                         &ecs->stepping_through_solib_catchpoints,
                         &ecs->stepping_through_sigtramp,
-                        &ecs->current_line, &ecs->current_symtab, &step_sp);
+                        &ecs->current_line, &ecs->current_symtab);
     }
   inferior_ptid = ecs->ptid;
 }
 
-/* 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".  */
-      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;
+  CORE_ADDR breakpoint_pc;
 
   /* If this target does not decrement the PC after breakpoints, then
      we have nothing to do.  */
@@ -1291,40 +1188,53 @@ adjust_pc_after_break (struct execution_control_state *ecs)
   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);
+  /* Find the location where (if we've hit a breakpoint) the
+     breakpoint would be.  */
+  breakpoint_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
+
+  if (SOFTWARE_SINGLE_STEP_P ())
+    {
+      /* When using software single-step, a SIGTRAP can only indicate
+        an inserted breakpoint.  This actually makes things
+        easier.  */
+      if (singlestep_breakpoints_inserted_p)
+       /* When software single stepping, the instruction at [prev_pc]
+          is never a breakpoint, but the instruction following
+          [prev_pc] (in program execution order) always is.  Assume
+          that following instruction was reached and hence a software
+          breakpoint was hit.  */
+       write_pc_pid (breakpoint_pc, ecs->ptid);
+      else if (software_breakpoint_inserted_here_p (breakpoint_pc))
+       /* The inferior was free running (i.e., no single-step
+          breakpoints inserted) and it hit a software breakpoint.  */
+       write_pc_pid (breakpoint_pc, ecs->ptid);
+    }
+  else
+    {
+      /* When using hardware single-step, a SIGTRAP is reported for
+        both a completed single-step and a software breakpoint.  Need
+        to differentiate between the two as the latter needs
+        adjusting but the former does not.  */
+      if (currently_stepping (ecs))
+       {
+         if (prev_pc == breakpoint_pc
+             && software_breakpoint_inserted_here_p (breakpoint_pc))
+           /* Hardware single-stepped a software breakpoint (as
+              occures when the inferior is resumed with PC pointing
+              at not-yet-hit software breakpoint).  Since the
+              breakpoint really is executed, the inferior needs to be
+              backed up to the breakpoint address.  */
+           write_pc_pid (breakpoint_pc, ecs->ptid);
+       }
+      else
+       {
+         if (software_breakpoint_inserted_here_p (breakpoint_pc))
+           /* The inferior was free running (i.e., no hardware
+              single-step and no possibility of a false SIGTRAP) and
+              hit a software breakpoint.  */
+           write_pc_pid (breakpoint_pc, ecs->ptid);
+       }
+    }
 }
 
 /* Given an execution control state that has been freshly filled in
@@ -1342,6 +1252,7 @@ handle_inferior_event (struct execution_control_state *ecs)
      defined in the file "config/pa/nm-hppah.h", accesses the variable
      indirectly.  Mutter something rude about the HP merge.  */
   int sw_single_step_trap_p = 0;
+  int stopped_by_watchpoint = 0;
 
   /* Cache the last pid/waitstatus. */
   target_last_wait_ptid = ecs->ptid;
@@ -1398,6 +1309,7 @@ handle_inferior_event (struct execution_control_state *ecs)
   /* If it's a new process, add it to the thread database */
 
   ecs->new_thread_event = (!ptid_equal (ecs->ptid, inferior_ptid)
+                          && !ptid_equal (ecs->ptid, minus_one_ptid)
                           && !in_thread_list (ecs->ptid));
 
   if (ecs->ws.kind != TARGET_WAITKIND_EXITED
@@ -1531,7 +1443,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       stop_pc = read_pc ();
 
-      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid, 0);
 
       ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
 
@@ -1580,7 +1492,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       ecs->saved_inferior_ptid = inferior_ptid;
       inferior_ptid = ecs->ptid;
 
-      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid, 0);
 
       ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
       inferior_ptid = ecs->saved_inferior_ptid;
@@ -1896,7 +1808,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   /* It may be possible to simply continue after a watchpoint.  */
   if (HAVE_CONTINUABLE_WATCHPOINT)
-    STOPPED_BY_WATCHPOINT (ecs->ws);
+    stopped_by_watchpoint = STOPPED_BY_WATCHPOINT (ecs->ws);
 
   ecs->stop_func_start = 0;
   ecs->stop_func_end = 0;
@@ -1976,7 +1888,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);
+         stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid, 
+                                           stopped_by_watchpoint);
 
          /* Following in case break condition called a
             function.  */
@@ -2084,9 +1997,6 @@ process_event_stop_test:
     if (what.call_dummy)
       {
        stop_stack_dummy = 1;
-#ifdef HP_OS_BUG
-       trap_expected_after_continue = 1;
-#endif
       }
 
     switch (what.main_action)
@@ -2395,23 +2305,6 @@ process_event_stop_test:
       return;
     }
 
-  if (step_over_calls == STEP_OVER_UNDEBUGGABLE
-      && ecs->stop_func_name == NULL)
-    {
-      /* There is no symbol, not even a minimal symbol, corresponding
-         to the address where we just stopped.  So we just stepped
-         inside undebuggable code.  Since we want to step over this
-         kind of code, we keep going until the inferior returns from
-         the current function.  */
-      handle_step_into_function (ecs);
-      return;
-    }
-
-  /* We can't update step_sp every time through the loop, because
-     reading the stack pointer would slow down stepping too much.
-     But we can update it every time we leave the step range.  */
-  ecs->update_step_sp = 1;
-
   if (step_range_end != 1
       && (step_over_calls == STEP_OVER_UNDEBUGGABLE
          || step_over_calls == STEP_OVER_ALL)
@@ -2426,11 +2319,112 @@ process_event_stop_test:
       return;
     }
 
-  if (frame_id_eq (get_frame_id (get_prev_frame (get_current_frame ())),
+  if (step_over_calls == STEP_OVER_UNDEBUGGABLE
+      && ecs->stop_func_name == NULL)
+    {
+      /* The inferior just stepped into, or returned to, an
+         undebuggable function (where there is no symbol, not even a
+         minimal symbol, corresponding to the address where the
+         inferior stopped).  Since we want to skip this kind of code,
+         we keep going until the inferior returns from this
+         function.  */
+      if (step_stop_if_no_debug)
+       {
+         /* 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.  */
+         stop_step = 1;
+         print_stop_reason (END_STEPPING_RANGE, 0);
+         stop_stepping (ecs);
+         return;
+       }
+      else
+       {
+         /* Set a breakpoint at callee's return address (the address
+            at which the caller will resume).  */
+         insert_step_resume_breakpoint (get_prev_frame (get_current_frame ()),
+                                        ecs);
+         keep_going (ecs);
+         return;
+       }
+    }
+
+  if (frame_id_eq (frame_unwind_id (get_current_frame ()),
                    step_frame_id))
     {
       /* It's a subroutine call.  */
-      handle_step_into_function (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", set a breakpoint at callee's return
+            address (the address at which the caller will
+            resume).  */
+         insert_step_resume_breakpoint (get_prev_frame (get_current_frame ()),
+                                        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;
+       }
+
+      /* Set a breakpoint at callee's return address (the address at
+        which the caller will resume).  */
+      insert_step_resume_breakpoint (get_prev_frame (get_current_frame ()), ecs);
+      keep_going (ecs);
       return;
     }
 
@@ -2662,8 +2656,12 @@ insert_step_resume_breakpoint (struct frame_info *step_frame,
   /* This is only used within the step-resume range/frame.  */
   gdb_assert (frame_id_eq (step_frame_id, get_frame_id (step_frame)));
   gdb_assert (step_range_end != 0);
-  gdb_assert (get_frame_pc (step_frame) >= step_range_start
-             && get_frame_pc (step_frame) < step_range_end);
+  /* Remember, if the call instruction is the last in the step range,
+     the breakpoint will land just beyond that.  Hence ``<=
+     step_range_end''.  Also, ignore check when "nexti".  */
+  gdb_assert (step_range_start == step_range_end
+             || (get_frame_pc (step_frame) >= step_range_start
+                 && get_frame_pc (step_frame) <= step_range_end));
 
   init_sal (&sr_sal);          /* initialize to zeros */
 
@@ -2680,83 +2678,6 @@ insert_step_resume_breakpoint (struct frame_info *step_frame,
     insert_breakpoints ();
 }
 
-/* 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 caller.
-
-   To do this, we set the step_resume bp's frame to our current
-   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 */
-
-  /* NOTE: cagney/2003-04-06:
-
-     At this point the equality get_frame_pc() == get_frame_func()
-     should hold.  This may make it possible for this code to tell the
-     frame where it's function is, instead of the reverse.  This would
-     avoid the need to search for the frame's function, which can get
-     very messy when there is no debug info available (look at the
-     heuristic find pc start code found in targets like the MIPS).  */
-
-  /* NOTE: cagney/2003-04-06:
-
-     The intent of DEPRECATED_SAVED_PC_AFTER_CALL was to:
-
-     - provide a very light weight equivalent to frame_unwind_pc()
-     (nee FRAME_SAVED_PC) that avoids the prologue analyzer
-
-     - avoid handling the case where the PC hasn't been saved in the
-     prologue analyzer
-
-     Unfortunately, not five lines further down, is a call to
-     get_frame_id() and that is guarenteed to trigger the prologue
-     analyzer.
-     
-     The `correct fix' is for the prologe analyzer to handle the case
-     where the prologue is incomplete (PC in prologue) and,
-     consequently, the return pc has not yet been saved.  It should be
-     noted that the prologue analyzer needs to handle this case
-     anyway: frameless leaf functions that don't save the return PC;
-     single stepping through a prologue.
-
-     The d10v handles all this by bailing out of the prologue analsis
-     when it reaches the current instruction.  */
-
-  if (DEPRECATED_SAVED_PC_AFTER_CALL_P ())
-    sr_sal.pc = ADDR_BITS_REMOVE (DEPRECATED_SAVED_PC_AFTER_CALL (get_current_frame ()));
-  else
-    sr_sal.pc = ADDR_BITS_REMOVE (frame_pc_unwind (get_current_frame ()));
-  sr_sal.section = find_pc_overlay (sr_sal.pc);
-
-  check_for_old_step_resume_breakpoint ();
-
-  /* NOTE: cagney/2004-03-31: Code using the current value of
-     "step_frame_id", instead of unwinding that frame ID, removed.  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.  */
-  sr_id = frame_unwind_id (get_current_frame ());
-
-  step_resume_breakpoint = set_momentary_breakpoint (sr_sal, sr_id, bp_step_resume);
-
-  if (breakpoints_inserted)
-    insert_breakpoints ();
-}
-
 static void
 stop_stepping (struct execution_control_state *ecs)
 {
@@ -2774,10 +2695,6 @@ keep_going (struct execution_control_state *ecs)
   /* Save the pc before execution, to compare with pc after stop.  */
   prev_pc = read_pc ();                /* Might have been DECR_AFTER_BREAK */
 
-  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.  */
 
This page took 0.028749 seconds and 4 git commands to generate.