2009-12-02 Tristan Gingold <gingold@adacore.com>
[binutils-gdb.git] / gdb / infrun.c
index 586746a75be97e1be3975c3f2d9fb03f04f89f19..cb5278c107929138d2f6753f701b0dbaf20aeed3 100644 (file)
@@ -2821,6 +2821,10 @@ handle_inferior_event (struct execution_control_state *ecs)
             dynamically loaded objects (among other things).  */
          if (stop_on_solib_events)
            {
+             /* Make sure we print "Stopped due to solib-event" in
+                normal_stop.  */
+             stop_print_frame = 1;
+
              stop_stepping (ecs);
              return;
            }
@@ -2942,7 +2946,11 @@ handle_inferior_event (struct execution_control_state *ecs)
        = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
                              stop_pc, ecs->ptid);
 
-      ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
+      /* Note that we're interested in knowing the bpstat actually
+        causes a stop, not just if it may explain the signal.
+        Software watchpoints, for example, always appear in the
+        bpstat.  */
+      ecs->random_signal = !bpstat_causes_stop (ecs->event_thread->stop_bpstat);
 
       /* If no catchpoint triggered for this, then keep going.  */
       if (ecs->random_signal)
@@ -3000,6 +3008,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        context_switch (ecs->ptid);
 
       current_inferior ()->waiting_for_vfork_done = 0;
+      current_inferior ()->pspace->breakpoints_not_allowed = 0;
       /* This also takes care of reinserting breakpoints in the
         previously locked inferior.  */
       keep_going (ecs);
@@ -3126,6 +3135,9 @@ targets should add new threads to the thread list themselves in non-stop mode.")
     {
       struct regcache *regcache = get_thread_regcache (ecs->ptid);
       struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      struct cleanup *old_chain = save_inferior_ptid ();
+
+      inferior_ptid = ecs->ptid;
 
       fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
                           paddress (gdbarch, stop_pc));
@@ -3142,6 +3154,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
             fprintf_unfiltered (gdb_stdlog,
                                 "infrun: (no data address available)\n");
        }
+
+      do_cleanups (old_chain);
     }
 
   if (stepping_past_singlestep_breakpoint)
@@ -3579,6 +3593,21 @@ targets should add new threads to the thread list themselves in non-stop mode.")
         function.  */
       stop_print_frame = 1;
 
+      /* This is where we handle "moribund" watchpoints.  Unlike
+        software breakpoints traps, hardware watchpoint traps are
+        always distinguishable from random traps.  If no high-level
+        watchpoint is associated with the reported stop data address
+        anymore, then the bpstat does not explain the signal ---
+        simply make sure to ignore it if `stopped_by_watchpoint' is
+        set.  */
+
+      if (debug_infrun
+         && ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
+         && !bpstat_explains_signal (ecs->event_thread->stop_bpstat)
+         && stopped_by_watchpoint)
+       fprintf_unfiltered (gdb_stdlog, "\
+infrun: no user watchpoint explains watchpoint SIGTRAP, ignoring\n");
+
       /* NOTE: cagney/2003-03-29: These two checks for a random signal
          at one stage in the past included checks for an inferior
          function call's call dummy's return breakpoint.  The original
@@ -3602,6 +3631,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
       if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
        ecs->random_signal
          = !(bpstat_explains_signal (ecs->event_thread->stop_bpstat)
+             || stopped_by_watchpoint
              || ecs->event_thread->trap_expected
              || (ecs->event_thread->step_range_end
                  && ecs->event_thread->step_resume_breakpoint == NULL));
@@ -4812,6 +4842,10 @@ stop_stepping (struct execution_control_state *ecs)
 static void
 keep_going (struct execution_control_state *ecs)
 {
+  /* Make sure normal_stop is called if we get a QUIT handled before
+     reaching resume.  */
+  struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
+
   /* Save the pc before execution, to compare with pc after stop.  */
   ecs->event_thread->prev_pc
     = regcache_read_pc (get_thread_regcache (ecs->ptid));
@@ -4825,6 +4859,8 @@ keep_going (struct execution_control_state *ecs)
       /* We took a signal (which we are supposed to pass through to
         the inferior, else we'd not get here) and we haven't yet
         gotten our trap.  Simply continue.  */
+
+      discard_cleanups (old_cleanups);
       resume (currently_stepping (ecs->event_thread),
              ecs->event_thread->stop_signal);
     }
@@ -4887,6 +4923,7 @@ keep_going (struct execution_control_state *ecs)
          && !signal_program[ecs->event_thread->stop_signal])
        ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
 
+      discard_cleanups (old_cleanups);
       resume (currently_stepping (ecs->event_thread),
              ecs->event_thread->stop_signal);
     }