2007-11-12 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 346e6c86346ac798c2884be3cd0d5996004f6630..cf7aa02abe1d7e4ce852acd7bfa6f2339cfd8ed2 100644 (file)
@@ -9,7 +9,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -18,9 +18,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "gdb_string.h"
@@ -80,11 +78,10 @@ static int currently_stepping (struct execution_control_state *ecs);
 
 static void xdb_handle_command (char *args, int from_tty);
 
-static int prepare_to_proceed (void);
+static int prepare_to_proceed (int);
 
 void _initialize_infrun (void);
 
-int inferior_ignoring_startup_exec_events = 0;
 int inferior_ignoring_leading_exec_events = 0;
 
 /* When set, stop the 'step' command if we enter a function which has
@@ -448,6 +445,11 @@ static CORE_ADDR singlestep_pc;
    thread here so that we can resume single-stepping it later.  */
 static ptid_t saved_singlestep_ptid;
 static int stepping_past_singlestep_breakpoint;
+
+/* Similarly, if we are stepping another thread past a breakpoint,
+   save the original thread here so that we can resume stepping it later.  */
+static ptid_t stepping_past_breakpoint_ptid;
+static int stepping_past_breakpoint;
 \f
 
 /* Things to clean up if we QUIT out of resume ().  */
@@ -645,7 +647,7 @@ clear_proceed_status (void)
 /* This should be suitable for any targets that support threads. */
 
 static int
-prepare_to_proceed (void)
+prepare_to_proceed (int step)
 {
   ptid_t wait_ptid;
   struct target_waitstatus wait_status;
@@ -653,42 +655,35 @@ prepare_to_proceed (void)
   /* Get the last target status returned by target_wait().  */
   get_last_target_status (&wait_ptid, &wait_status);
 
-  /* Make sure we were stopped either at a breakpoint, or because
-     of a Ctrl-C.  */
+  /* Make sure we were stopped at a breakpoint.  */
   if (wait_status.kind != TARGET_WAITKIND_STOPPED
-      || (wait_status.value.sig != TARGET_SIGNAL_TRAP
-         && wait_status.value.sig != TARGET_SIGNAL_INT))
+      || wait_status.value.sig != TARGET_SIGNAL_TRAP)
     {
       return 0;
     }
 
+  /* Switched over from WAIT_PID.  */
   if (!ptid_equal (wait_ptid, minus_one_ptid)
-      && !ptid_equal (inferior_ptid, wait_ptid))
+      && !ptid_equal (inferior_ptid, wait_ptid)
+      && breakpoint_here_p (read_pc_pid (wait_ptid)))
     {
-      /* Switched over from WAIT_PID.  */
-      CORE_ADDR wait_pc = read_pc_pid (wait_ptid);
-
-      if (wait_pc != read_pc ())
+      /* If stepping, remember current thread to switch back to.  */
+      if (step)
        {
-         /* Switch back to WAIT_PID thread.  */
-         inferior_ptid = wait_ptid;
-
-         /* FIXME: This stuff came from switch_to_thread() in
-            thread.c (which should probably be a public function).  */
-         reinit_frame_cache ();
-         registers_changed ();
-         stop_pc = wait_pc;
+         stepping_past_breakpoint = 1;
+         stepping_past_breakpoint_ptid = inferior_ptid;
        }
 
+      /* Switch back to WAIT_PID thread.  */
+      switch_to_thread (wait_ptid);
+
       /* We return 1 to indicate that there is a breakpoint here,
-         so we need to step over it before continuing to avoid
-         hitting it straight away. */
-      if (breakpoint_here_p (wait_pc))
-       return 1;
+        so we need to step over it before continuing to avoid
+        hitting it straight away. */
+      return 1;
     }
 
   return 0;
-
 }
 
 /* Record the pc of the program the last time it stopped.  This is
@@ -754,7 +749,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
      prepare_to_proceed checks the current thread against the thread
      that reported the most recent event.  If a step-over is required
      it returns TRUE and sets the current thread to the old thread. */
-  if (prepare_to_proceed () && breakpoint_here_p (read_pc ()))
+  if (prepare_to_proceed (step))
     oneproc = 1;
 
   if (oneproc)
@@ -828,7 +823,7 @@ start_remote (int from_tty)
 {
   init_thread_list ();
   init_wait_for_inferior ();
-  stop_soon = STOP_QUIETLY;
+  stop_soon = STOP_QUIETLY_REMOTE;
   trap_expected = 0;
 
   /* Always go on waiting for the target, regardless of the mode. */
@@ -875,6 +870,7 @@ init_wait_for_inferior (void)
   clear_proceed_status ();
 
   stepping_past_singlestep_breakpoint = 0;
+  stepping_past_breakpoint = 0;
 }
 \f
 /* This enum encodes possible reasons for doing a target_wait, so that
@@ -885,6 +881,7 @@ enum infwait_states
 {
   infwait_normal_state,
   infwait_thread_hop_state,
+  infwait_step_watch_state,
   infwait_nonstep_watch_state
 };
 
@@ -1144,8 +1141,8 @@ context_switch (struct execution_control_state *ecs)
                         &ecs->stepping_through_solib_catchpoints,
                         &ecs->current_line, &ecs->current_symtab);
     }
-  inferior_ptid = ecs->ptid;
-  reinit_frame_cache ();
+
+  switch_to_thread (ecs->ptid);
 }
 
 static void
@@ -1224,17 +1221,12 @@ adjust_pc_after_break (struct execution_control_state *ecs)
    by an event from the inferior, figure out what it means and take
    appropriate action.  */
 
-int stepped_after_stopped_by_watchpoint;
-
 void
 handle_inferior_event (struct execution_control_state *ecs)
 {
-  /* NOTE: bje/2005-05-02: If you're looking at this code and thinking
-     that the variable stepped_after_stopped_by_watchpoint isn't used,
-     then you're wrong!  See remote.c:remote_stopped_data_address.  */
-
   int sw_single_step_trap_p = 0;
-  int stopped_by_watchpoint = -1;      /* Mark as unknown.  */
+  int stopped_by_watchpoint;
+  int stepped_after_stopped_by_watchpoint = 0;
 
   /* Cache the last pid/waitstatus. */
   target_last_wait_ptid = ecs->ptid;
@@ -1254,7 +1246,14 @@ handle_inferior_event (struct execution_control_state *ecs)
     case infwait_normal_state:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: infwait_normal_state\n");
-      stepped_after_stopped_by_watchpoint = 0;
+      break;
+
+    case infwait_step_watch_state:
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog,
+                           "infrun: infwait_step_watch_state\n");
+
+      stepped_after_stopped_by_watchpoint = 1;
       break;
 
     case infwait_nonstep_watch_state:
@@ -1297,16 +1296,22 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_LOADED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
-      /* Ignore gracefully during startup of the inferior, as it
-         might be the shell which has just loaded some objects,
-         otherwise add the symbols for the newly loaded objects.  */
-#ifdef SOLIB_ADD
+      /* Ignore gracefully during startup of the inferior, as it might
+         be the shell which has just loaded some objects, otherwise
+         add the symbols for the newly loaded objects.  Also ignore at
+         the beginning of an attach or remote session; we will query
+         the full list of libraries once the connection is
+         established.  */
       if (stop_soon == NO_STOP_QUIETLY)
        {
+         int breakpoints_were_inserted;
+
          /* Remove breakpoints, SOLIB_ADD might adjust
             breakpoint addresses via breakpoint_re_set.  */
+         breakpoints_were_inserted = breakpoints_inserted;
          if (breakpoints_inserted)
            remove_breakpoints ();
+         breakpoints_inserted = 0;
 
          /* Check for any newly added shared libraries if we're
             supposed to be adding them automatically.  Switch
@@ -1328,17 +1333,46 @@ handle_inferior_event (struct execution_control_state *ecs)
             exec/process stratum, instead relying on the target stack
             to propagate relevant changes (stop, section table
             changed, ...) up to other layers.  */
+#ifdef SOLIB_ADD
          SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
+#else
+         solib_add (NULL, 0, &current_target, auto_solib_add);
+#endif
          target_terminal_inferior ();
 
+         /* If requested, stop when the dynamic linker notifies
+            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)
+           {
+             stop_stepping (ecs);
+             return;
+           }
+
+         /* NOTE drow/2007-05-11: This might be a good place to check
+            for "catch load".  */
+
          /* Reinsert breakpoints and continue.  */
-         if (breakpoints_inserted)
-           insert_breakpoints ();
+         if (breakpoints_were_inserted)
+           {
+             insert_breakpoints ();
+             breakpoints_inserted = 1;
+           }
+       }
+
+      /* If we are skipping through a shell, or through shared library
+        loading that we aren't interested in, resume the program.  If
+        we're running the program normally, also resume.  But stop if
+        we're attaching or setting up a remote connection.  */
+      if (stop_soon == STOP_QUIETLY || stop_soon == NO_STOP_QUIETLY)
+       {
+         resume (0, TARGET_SIGNAL_0);
+         prepare_to_wait (ecs);
+         return;
        }
-#endif
-      resume (0, TARGET_SIGNAL_0);
-      prepare_to_wait (ecs);
-      return;
+
+      break;
 
     case TARGET_WAITKIND_SPURIOUS:
       if (debug_infrun)
@@ -1404,7 +1438,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       stop_pc = read_pc ();
 
-      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid, 0);
+      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
 
       ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
 
@@ -1452,7 +1486,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, 0);
+      stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
 
       ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
       inferior_ptid = ecs->saved_inferior_ptid;
@@ -1568,6 +1602,37 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   stepping_past_singlestep_breakpoint = 0;
 
+  if (stepping_past_breakpoint)
+    {
+      stepping_past_breakpoint = 0;
+
+      /* If we stopped for some other reason than single-stepping, ignore
+        the fact that we were supposed to switch back.  */
+      if (stop_signal == TARGET_SIGNAL_TRAP)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: stepping_past_breakpoint\n");
+
+         /* Pull the single step breakpoints out of the target.  */
+         if (singlestep_breakpoints_inserted_p)
+           {
+             remove_single_step_breakpoints ();
+             singlestep_breakpoints_inserted_p = 0;
+           }
+
+         /* Note: We do not call context_switch at this point, as the
+            context is already set up for stepping the original thread.  */
+         switch_to_thread (stepping_past_breakpoint_ptid);
+         /* Suppress spurious "Switching to ..." message.  */
+         previous_inferior_ptid = inferior_ptid;
+
+         resume (1, TARGET_SIGNAL_0);
+         prepare_to_wait (ecs);
+         return;
+       }
+    }
+
   /* 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.  */
@@ -1734,24 +1799,20 @@ handle_inferior_event (struct execution_control_state *ecs)
       singlestep_breakpoints_inserted_p = 0;
     }
 
-  /* It may not be necessary to disable the watchpoint to stop over
-     it.  For example, the PA can (with some kernel cooperation)
-     single step over a watchpoint without disabling the watchpoint.  */
-  if (HAVE_STEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
+  if (stepped_after_stopped_by_watchpoint)
+    stopped_by_watchpoint = 0;
+  else
+    stopped_by_watchpoint = watchpoints_triggered (&ecs->ws);
+
+  /* If necessary, step over this watchpoint.  We'll be back to display
+     it in a moment.  */
+  if (stopped_by_watchpoint
+      && (HAVE_STEPPABLE_WATCHPOINT
+         || gdbarch_have_nonsteppable_watchpoint (current_gdbarch)))
     {
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
-      resume (1, 0);
-      prepare_to_wait (ecs);
-      return;
-    }
 
-  /* It is far more common to need to disable a watchpoint to step
-     the inferior over it.  FIXME.  What else might a debug
-     register or page protection watchpoint scheme need here?  */
-  if (gdbarch_have_nonsteppable_watchpoint (current_gdbarch)
-      && STOPPED_BY_WATCHPOINT (ecs->ws))
-    {
       /* At this point, we are stopped at an instruction which has
          attempted to write to a piece of memory under control of
          a watchpoint.  The instruction hasn't actually executed
@@ -1761,31 +1822,31 @@ handle_inferior_event (struct execution_control_state *ecs)
 
          In order to make watchpoints work `right', we really need
          to complete the memory write, and then evaluate the
-         watchpoint expression.  The following code does that by
-         removing the watchpoint (actually, all watchpoints and
-         breakpoints), single-stepping the target, re-inserting
-         watchpoints, and then falling through to let normal
-         single-step processing handle proceed.  Since this
-         includes evaluating watchpoints, things will come to a
-         stop in the correct manner.  */
-
-      if (debug_infrun)
-       fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
-      remove_breakpoints ();
+         watchpoint expression.  We do this by single-stepping the
+        target.
+
+        It may not be necessary to disable the watchpoint to stop over
+        it.  For example, the PA can (with some kernel cooperation)
+        single step over a watchpoint without disabling the watchpoint.
+
+        It is far more common to need to disable a watchpoint to step
+        the inferior over it.  If we have non-steppable watchpoints,
+        we must disable the current watchpoint; it's simplest to
+        disable all watchpoints and breakpoints.  */
+        
+      if (!HAVE_STEPPABLE_WATCHPOINT)
+       remove_breakpoints ();
       registers_changed ();
       target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);   /* Single step */
-
       ecs->waiton_ptid = ecs->ptid;
-      ecs->wp = &(ecs->ws);
-      ecs->infwait_state = infwait_nonstep_watch_state;
+      if (HAVE_STEPPABLE_WATCHPOINT)
+       ecs->infwait_state = infwait_step_watch_state;
+      else
+       ecs->infwait_state = infwait_nonstep_watch_state;
       prepare_to_wait (ecs);
       return;
     }
 
-  /* It may be possible to simply continue after a watchpoint.  */
-  if (HAVE_CONTINUABLE_WATCHPOINT)
-    stopped_by_watchpoint = STOPPED_BY_WATCHPOINT (ecs->ws);
-
   ecs->stop_func_start = 0;
   ecs->stop_func_end = 0;
   ecs->stop_func_name = 0;
@@ -1862,7 +1923,8 @@ handle_inferior_event (struct execution_control_state *ecs)
          && (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)
+      || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
+      || stop_soon == STOP_QUIETLY_REMOTE)
     {
       if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
        {
@@ -1875,7 +1937,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       /* This is originated from start_remote(), start_inferior() and
          shared libraries hook functions.  */
-      if (stop_soon == STOP_QUIETLY)
+      if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
        {
           if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
@@ -1906,8 +1968,7 @@ 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,
-                                           stopped_by_watchpoint);
+         stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
 
          /* Following in case break condition called a
             function.  */
@@ -2209,10 +2270,6 @@ process_event_stop_test:
 #endif
          target_terminal_inferior ();
 
-         /* Try to reenable shared library breakpoints, additional
-            code segments in shared libraries might be mapped in now. */
-         re_enable_breakpoints_in_shlibs ();
-
          /* If requested, stop when the dynamic linker notifies
             gdb of events.  This allows the user to get control
             and place breakpoints in initializer routines for
@@ -2669,8 +2726,10 @@ process_event_stop_test:
      function.  Fortunately, those days are nearly upon us.  */
 #endif
   {
-    struct frame_id current_frame = get_frame_id (get_current_frame ());
-    if (!(frame_id_inner (current_frame, step_frame_id)))
+    struct frame_info *frame = get_current_frame ();
+    struct frame_id current_frame = get_frame_id (frame);
+    if (!(frame_id_inner (get_frame_arch (frame), current_frame,
+                         step_frame_id)))
       step_frame_id = current_frame;
   }
 
@@ -2801,6 +2860,7 @@ insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
 {
   struct symtab_and_line sr_sal;
 
+  gdb_assert (return_frame != NULL);
   init_sal (&sr_sal);          /* initialize to zeros */
 
   sr_sal.pc = gdbarch_addr_bits_remove
@@ -3160,6 +3220,18 @@ Further execution is probably impossible.\n"));
          switch (bpstat_ret)
            {
            case PRINT_UNKNOWN:
+             /* If we had hit a shared library event breakpoint,
+                bpstat_print would print out this message.  If we hit
+                an OS-level shared library event, do the same
+                thing.  */
+             if (last.kind == TARGET_WAITKIND_LOADED)
+               {
+                 printf_filtered (_("Stopped due to shared library event\n"));
+                 source_flag = SRC_LINE;       /* something bogus */
+                 do_frame_printing = 0;
+                 break;
+               }
+
              /* FIXME: cagney/2002-12-01: Given that a frame ID does
                 (or should) carry around the function and does (or
                 should) use that when doing a frame comparison.  */
This page took 0.030112 seconds and 4 git commands to generate.