* value.c (set_internalvar): Use value_free, not xfree.
[binutils-gdb.git] / gdb / infrun.c
index 292200f237f25a83f5c126074fde920c58aed5c7..77aa40d10e3dcf93360e9580ca96fb78d99a2a7c 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
    1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008 Free Software Foundation, Inc.
+   2008, 2009 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -75,6 +75,8 @@ static void set_schedlock_func (char *args, int from_tty,
 
 static int currently_stepping (struct thread_info *tp);
 
+static int currently_stepping_callback (struct thread_info *tp, void *data);
+
 static void xdb_handle_command (char *args, int from_tty);
 
 static int prepare_to_proceed (int);
@@ -230,8 +232,8 @@ show_stop_on_solib_events (struct ui_file *file, int from_tty,
 
 int stop_after_trap;
 
-/* Save register contents here when about to pop a stack dummy frame,
-   if-and-only-if proceed_to_finish is set.
+/* Save register contents here when executing a "finish" command or are
+   about to pop a stack dummy frame, if-and-only-if proceed_to_finish is set.
    Thus this contains the return value from the called function (assuming
    values are returned in a register).  */
 
@@ -963,10 +965,13 @@ resume (int step, enum target_signal sig)
 {
   int should_resume = 1;
   struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
+
+  /* Note that these must be reset if we follow a fork below.  */
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   struct thread_info *tp = inferior_thread ();
   CORE_ADDR pc = regcache_read_pc (regcache);
+
   QUIT;
 
   if (debug_infrun)
@@ -1051,6 +1056,13 @@ a command like `return' or `jump' to continue execution."));
       pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
       if (follow_fork ())
        should_resume = 0;
+
+      /* Following a child fork will change our notion of current
+        thread.  */
+      tp = inferior_thread ();
+      regcache = get_current_regcache ();
+      gdbarch = get_regcache_arch (regcache);
+      pc = regcache_read_pc (regcache);
       break;
 
     case TARGET_WAITKIND_EXECD:
@@ -1146,11 +1158,11 @@ a command like `return' or `jump' to continue execution."));
           displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
         }
 
-      target_resume (resume_ptid, step, sig);
-
       /* Avoid confusing the next resume, if the next stop/resume
         happens to apply to another thread.  */
       tp->stop_signal = TARGET_SIGNAL_0;
+
+      target_resume (resume_ptid, step, sig);
     }
 
   discard_cleanups (old_cleanups);
@@ -1161,31 +1173,59 @@ a command like `return' or `jump' to continue execution."));
 /* Clear out all variables saying what to do when inferior is continued.
    First do this, then set the ones you want, then call `proceed'.  */
 
-void
-clear_proceed_status (void)
+static void
+clear_proceed_status_thread (struct thread_info *tp)
 {
-  if (!ptid_equal (inferior_ptid, null_ptid))
-    {
-      struct thread_info *tp;
-      struct inferior *inferior;
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+                       "infrun: clear_proceed_status_thread (%s)\n",
+                       target_pid_to_str (tp->ptid));
 
-      tp = inferior_thread ();
+  tp->trap_expected = 0;
+  tp->step_range_start = 0;
+  tp->step_range_end = 0;
+  tp->step_frame_id = null_frame_id;
+  tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
+  tp->stop_requested = 0;
 
-      tp->trap_expected = 0;
-      tp->step_range_start = 0;
-      tp->step_range_end = 0;
-      tp->step_frame_id = null_frame_id;
-      tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
-      tp->stop_requested = 0;
+  tp->stop_step = 0;
 
-      tp->stop_step = 0;
+  tp->proceed_to_finish = 0;
 
-      tp->proceed_to_finish = 0;
+  /* Discard any remaining commands or status from previous stop.  */
+  bpstat_clear (&tp->stop_bpstat);
+}
 
-      /* Discard any remaining commands or status from previous
-        stop.  */
-      bpstat_clear (&tp->stop_bpstat);
+static int
+clear_proceed_status_callback (struct thread_info *tp, void *data)
+{
+  if (is_exited (tp->ptid))
+    return 0;
 
+  clear_proceed_status_thread (tp);
+  return 0;
+}
+
+void
+clear_proceed_status (void)
+{
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    {
+      struct inferior *inferior;
+
+      if (non_stop)
+       {
+         /* If in non-stop mode, only delete the per-thread status
+            of the current thread.  */
+         clear_proceed_status_thread (inferior_thread ());
+       }
+      else
+       {
+         /* In all-stop mode, delete the per-thread status of
+            *all* threads.  */
+         iterate_over_threads (clear_proceed_status_callback, NULL);
+       }
+  
       inferior = current_inferior ();
       inferior->stop_soon = NO_STOP_QUIETLY;
     }
@@ -1263,7 +1303,6 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   struct thread_info *tp;
   CORE_ADDR pc = regcache_read_pc (regcache);
   int oneproc = 0;
-  enum target_signal stop_signal;
 
   if (step > 0)
     step_start_function = find_pc_function (pc);
@@ -2102,13 +2141,17 @@ handle_inferior_event (struct execution_control_state *ecs)
     {
       breakpoint_retire_moribund ();
 
-      /* Mark the non-executing threads accordingly.  */
-      if (!non_stop
-         || ecs->ws.kind == TARGET_WAITKIND_EXITED
-         || ecs->ws.kind == TARGET_WAITKIND_SIGNALLED)
-       set_executing (pid_to_ptid (-1), 0);
-      else
-       set_executing (ecs->ptid, 0);
+      /* Mark the non-executing threads accordingly.  In all-stop, all
+        threads of all processes are stopped when we get any event
+        reported.  In non-stop mode, only the event thread stops.  If
+        we're handling a process exit in non-stop mode, there's
+        nothing to do, as threads of the dead process are gone, and
+        threads of any other process were left running.  */
+      if (!non_stop)
+       set_executing (minus_one_ptid, 0);
+      else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+              && ecs->ws.kind != TARGET_WAITKIND_EXITED)
+       set_executing (inferior_ptid, 0);
     }
 
   switch (infwait_state)
@@ -2232,6 +2275,7 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_EXITED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\n");
+      inferior_ptid = ecs->ptid;
       target_terminal_ours (); /* Must do this before mourn anyway */
       print_stop_reason (EXITED, ecs->ws.value.integer);
 
@@ -2250,6 +2294,7 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_SIGNALLED:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n");
+      inferior_ptid = ecs->ptid;
       stop_print_frame = 0;
       target_terminal_ours (); /* Must do this before mourn anyway */
 
@@ -2471,8 +2516,6 @@ targets should add new threads to the thread list themselves in non-stop mode.")
        }
     }
 
-  stepping_past_singlestep_breakpoint = 0;
-
   if (!ptid_equal (deferred_step_ptid, null_ptid))
     {
       /* In non-stop mode, there's never a deferred_step_ptid set.  */
@@ -2482,8 +2525,6 @@ targets should add new threads to the thread list themselves in non-stop mode.")
         the fact that we were supposed to switch back.  */
       if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
        {
-         struct thread_info *tp;
-
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog,
                                "infrun: handling deferred step\n");
@@ -3121,7 +3162,6 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
        break;
 
       case BPSTAT_WHAT_CHECK_SHLIBS:
-      case BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK:
        {
           if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_SHLIBS\n");
@@ -3185,6 +3225,43 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
      test for stepping.  But, if not stepping,
      do not stop.  */
 
+  /* In all-stop mode, if we're currently stepping but have stopped in
+     some other thread, we need to switch back to the stepped thread.  */
+  if (!non_stop)
+    {
+      struct thread_info *tp;
+      tp = iterate_over_threads (currently_stepping_callback,
+                                ecs->event_thread);
+      if (tp)
+       {
+         /* However, if the current thread is blocked on some internal
+            breakpoint, and we simply need to step over that breakpoint
+            to get it going again, do that first.  */
+         if ((ecs->event_thread->trap_expected
+              && ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP)
+             || ecs->event_thread->stepping_over_breakpoint)
+           {
+             keep_going (ecs);
+             return;
+           }
+
+         /* Otherwise, we no longer expect a trap in the current thread.
+            Clear the trap_expected flag before switching back -- this is
+            what keep_going would do as well, if we called it.  */
+         ecs->event_thread->trap_expected = 0;
+
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: switching back to stepped thread\n");
+
+         ecs->event_thread = tp;
+         ecs->ptid = tp->ptid;
+         context_switch (ecs->ptid);
+         keep_going (ecs);
+         return;
+       }
+    }
+
   /* Are we stepping to get the inferior out of the dynamic linker's
      hook (and possibly the dld itself) after catching a shlib
      event?  */
@@ -3603,13 +3680,26 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
 
 /* Are we in the middle of stepping?  */
 
+static int
+currently_stepping_thread (struct thread_info *tp)
+{
+  return (tp->step_range_end && tp->step_resume_breakpoint == NULL)
+        || tp->trap_expected
+        || tp->stepping_through_solib_after_catch;
+}
+
+static int
+currently_stepping_callback (struct thread_info *tp, void *data)
+{
+  /* Return true if any thread *but* the one passed in "data" is
+     in the middle of stepping.  */
+  return tp != data && currently_stepping_thread (tp);
+}
+
 static int
 currently_stepping (struct thread_info *tp)
 {
-  return (((tp->step_range_end && tp->step_resume_breakpoint == NULL)
-          || tp->trap_expected)
-         || tp->stepping_through_solib_after_catch
-         || bpstat_should_step ());
+  return currently_stepping_thread (tp) || bpstat_should_step ();
 }
 
 /* Inferior has stepped into a subroutine call with source code that
@@ -4286,17 +4376,25 @@ done:
       else
        observer_notify_normal_stop (NULL);
     }
-  if (target_has_execution
-      && last.kind != TARGET_WAITKIND_SIGNALLED
-      && last.kind != TARGET_WAITKIND_EXITED)
-    {
-      /* Delete the breakpoint we stopped at, if it wants to be deleted.
-        Delete any breakpoint that is to be deleted at the next stop.  */
-      breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
 
+  if (target_has_execution)
+    {
+      if (last.kind != TARGET_WAITKIND_SIGNALLED
+         && last.kind != TARGET_WAITKIND_EXITED)
+       /* Delete the breakpoint we stopped at, if it wants to be deleted.
+          Delete any breakpoint that is to be deleted at the next stop.  */
+       breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
+
+      /* Mark the stopped threads accordingly.  In all-stop, all
+        threads of all processes are stopped when we get any event
+        reported.  In non-stop mode, only the event thread stops.  If
+        we're handling a process exit in non-stop mode, there's
+        nothing to do, as threads of the dead process are gone, and
+        threads of any other process were left running.  */
       if (!non_stop)
-       set_running (pid_to_ptid (-1), 0);
-      else
+       set_running (minus_one_ptid, 0);
+      else if (last.kind != TARGET_WAITKIND_SIGNALLED
+              && last.kind != TARGET_WAITKIND_EXITED)
        set_running (inferior_ptid, 0);
     }
 
@@ -4541,20 +4639,22 @@ Are you sure you want to change it? ", target_signal_to_name ((enum target_signa
       argv++;
     }
 
-  target_notice_signals (inferior_ptid);
+  for (signum = 0; signum < nsigs; signum++)
+    if (sigs[signum])
+      {
+       target_notice_signals (inferior_ptid);
 
-  if (from_tty)
-    {
-      /* Show the results.  */
-      sig_print_header ();
-      for (signum = 0; signum < nsigs; signum++)
-       {
-         if (sigs[signum])
-           {
-             sig_print_info (signum);
-           }
-       }
-    }
+       if (from_tty)
+         {
+           /* Show the results.  */
+           sig_print_header ();
+           for (; signum < nsigs; signum++)
+             if (sigs[signum])
+               sig_print_info (signum);
+         }
+
+       break;
+      }
 
   do_cleanups (old_chain);
 }