]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2008-11-25 Pedro Alves <pedro@codesourcery.com>
authorPedro Alves <palves@redhat.com>
Tue, 25 Nov 2008 20:45:09 +0000 (20:45 +0000)
committerPedro Alves <palves@redhat.com>
Tue, 25 Nov 2008 20:45:09 +0000 (20:45 +0000)
2008-11-25  Pedro Alves  <pedro@codesourcery.com>

* linux-fork.c (detach_fork): Delete declaration.
(_initialize_linux_fork): Move "set detach-on-fork"
command to ...
* infrun.c (_initialize_infrun): ... here.
* inferior.h (detach_fork): Declare.

2008-11-10  Pedro Alves  <pedro@codesourcery.com>

* remote.c (read_ptid): If we don't know about any inferior yet,
use the pid of magic_null_ptid.
(remote_start_remote): Don't set inferior_ptid to magic_null_ptid
here.

2008-10-14  Pedro Alves  <pedro@codesourcery.com>

* remote.c (remote_start_remote): Mask async mode while collecting
the initial event, use notice_new_inferior.

2008-10-12  Pedro Alves  <pedro@codesourcery.com>

* infcmd.c (attach_command_post_wait): Set the inferior exec here.
(attach_command): Don't set the inferior exec here.
(notice_new_inferior): New.
* inferior.h (notice_new_inferior): Declare.
* remote.c (notice_new_inferiors): Add `stopping' argument.  Add
the inferior before adding the threads.  Call notice_new_inferior.
(record_currthread): Adjust.
(remote_threads_info): Add the inferior before adding the thread.
Call notice_new_inferior.

2008-10-09  Pedro Alves  <pedro@codesourcery.com>

* remote.c (notice_new_inferiors): If there's only one exec, set
it in the new inferior.
(set_thread): If setting the thread failed, assume the thread has
terminated.

2008-09-17  Pedro Alves  <pedro@codesourcery.com>

* inferior.c (delete_inferior_1): Free the inferior after freeing
its threads.

2008-09-16  Pedro Alves  <pedro@codesourcery.com>

* inferior.h (discard_all_inferiors): Declare.
* inferior.c (delete_inferior): Rename to...
(delete_inferior_1): ...this.  Add 'silent' argument.  If this
inferior is has pid not zero, delete its threads.
(delete_inferior): New, as wrapper around delete_inferior_1.
(delete_inferior_by_pid_1): Reimplement.
(discard_all_inferiors): New.

2008-09-15  Pedro Alves  <pedro@codesourcery.com>

* remote.c (extended_remote_attach_1): Don't set target_attach_no_wait.

2008-09-15  Pedro Alves  <pedro@codesourcery.com>

* frame.c (get_current_frame, has_stack_frames): Check for
null_ptid.
* top.c (execute_command): Likewise.

2008-08-29  Pedro Alves  <pedro@codesourcery.com>

* inferior.c (have_real_inferiors): New.
* inferior.h (have_real_inferiors): Declare.
* remote.c (extended_remote_mourn_1): Use it.
* top.c (quit_target): Use it.

2008-08-28  Pedro Alves  <pedro@codesourcery.com>

* remote.c (parse_stop_reply): Handle Y;exec.

2008-08-28  Pedro Alves  <pedro@codesourcery.com>

* infcmd.c (struct exec_file_attach_wrapper_args): New.
(exec_file_attach_wrapper): New.
(attach_command_post_wait): If there's a sysroot, prepend it to
the target reported exec file path.  Continue attaching to the
inferior event if attaching to the exec file fails.

* remote.c (remote_pid_to_exec_file): Rebustify.  Expect
"QExecFile:PID;" in the reply.

2008-08-28  Pedro Alves  <pedro@codesourcery.com>

* remote.c (record_currthread): If setting the current thread to
minus_one_ptid, don't pass that to the stub.
(remote_parse_stop_reply): Handle 'Y' stop reply.
(remote_wait_as): Likewise.  If remote process exited, invalidate
the current thread.
(remote_detach_pid): New.
(remote_follow_fork): New.
(init_remote_ops): Register it.

2008-08-28  Pedro Alves  <pedro@codesourcery.com>

* remote.c (remote_pid_to_exec_file): New.
(init_remote_ops): Register it.

2008-08-28  Pedro Alves  <pedro@codesourcery.com>

* infcmd.c (kill_if_already_running): If target supports
multi-process, allow multi-runs.

2008-08-28  Pedro Alves  <pedro@codesourcery.com>

* remote.c (extended_remote_create_inferior_1): Don't clear the
thread list.

gdb/ChangeLog
gdb/exec.c
gdb/frame.c
gdb/infcmd.c
gdb/inferior.c
gdb/inferior.h
gdb/infrun.c
gdb/linux-fork.c
gdb/remote.c
gdb/stack.c
gdb/top.c

index 88de57eb120eac090465c50d513f7b3bf5f184c4..488453081cf42d170fe78df5ccad276f10348690 100644 (file)
@@ -1,3 +1,117 @@
+2008-11-25  Pedro Alves  <pedro@codesourcery.com>
+
+       2008-11-25  Pedro Alves  <pedro@codesourcery.com>
+
+       * linux-fork.c (detach_fork): Delete declaration.
+       (_initialize_linux_fork): Move "set detach-on-fork"
+       command to ...
+       * infrun.c (_initialize_infrun): ... here.
+       * inferior.h (detach_fork): Declare.
+
+       2008-11-10  Pedro Alves  <pedro@codesourcery.com>
+
+       * remote.c (read_ptid): If we don't know about any inferior yet,
+       use the pid of magic_null_ptid.
+       (remote_start_remote): Don't set inferior_ptid to magic_null_ptid
+       here.
+
+       2008-10-14  Pedro Alves  <pedro@codesourcery.com>
+
+       * remote.c (remote_start_remote): Mask async mode while collecting
+       the initial event, use notice_new_inferior.
+
+       2008-10-12  Pedro Alves  <pedro@codesourcery.com>
+
+       * infcmd.c (attach_command_post_wait): Set the inferior exec here.
+       (attach_command): Don't set the inferior exec here.
+       (notice_new_inferior): New.
+       * inferior.h (notice_new_inferior): Declare.
+       * remote.c (notice_new_inferiors): Add `stopping' argument.  Add
+       the inferior before adding the threads.  Call notice_new_inferior.
+       (record_currthread): Adjust.
+       (remote_threads_info): Add the inferior before adding the thread.
+       Call notice_new_inferior.
+
+       2008-10-09  Pedro Alves  <pedro@codesourcery.com>
+
+       * remote.c (notice_new_inferiors): If there's only one exec, set
+       it in the new inferior.
+       (set_thread): If setting the thread failed, assume the thread has
+       terminated.
+
+       2008-09-17  Pedro Alves  <pedro@codesourcery.com>
+
+       * inferior.c (delete_inferior_1): Free the inferior after freeing
+       its threads.
+
+       2008-09-16  Pedro Alves  <pedro@codesourcery.com>
+
+       * inferior.h (discard_all_inferiors): Declare.
+       * inferior.c (delete_inferior): Rename to...
+       (delete_inferior_1): ...this.  Add 'silent' argument.  If this
+       inferior is has pid not zero, delete its threads.
+       (delete_inferior): New, as wrapper around delete_inferior_1.
+       (delete_inferior_by_pid_1): Reimplement.
+       (discard_all_inferiors): New.
+
+       2008-09-15  Pedro Alves  <pedro@codesourcery.com>
+
+       * remote.c (extended_remote_attach_1): Don't set target_attach_no_wait.
+
+       2008-09-15  Pedro Alves  <pedro@codesourcery.com>
+
+       * frame.c (get_current_frame, has_stack_frames): Check for
+       null_ptid.
+       * top.c (execute_command): Likewise.
+
+       2008-08-29  Pedro Alves  <pedro@codesourcery.com>
+
+       * inferior.c (have_real_inferiors): New.
+       * inferior.h (have_real_inferiors): Declare.
+       * remote.c (extended_remote_mourn_1): Use it.
+       * top.c (quit_target): Use it.
+
+       2008-08-28  Pedro Alves  <pedro@codesourcery.com>
+
+       * remote.c (parse_stop_reply): Handle Y;exec.
+
+       2008-08-28  Pedro Alves  <pedro@codesourcery.com>
+
+       * infcmd.c (struct exec_file_attach_wrapper_args): New.
+       (exec_file_attach_wrapper): New.
+       (attach_command_post_wait): If there's a sysroot, prepend it to
+       the target reported exec file path.  Continue attaching to the
+       inferior event if attaching to the exec file fails.
+
+       * remote.c (remote_pid_to_exec_file): Rebustify.  Expect
+       "QExecFile:PID;" in the reply.
+
+       2008-08-28  Pedro Alves  <pedro@codesourcery.com>
+
+       * remote.c (record_currthread): If setting the current thread to
+       minus_one_ptid, don't pass that to the stub.
+       (remote_parse_stop_reply): Handle 'Y' stop reply.
+       (remote_wait_as): Likewise.  If remote process exited, invalidate
+       the current thread.
+       (remote_detach_pid): New.
+       (remote_follow_fork): New.
+       (init_remote_ops): Register it.
+
+       2008-08-28  Pedro Alves  <pedro@codesourcery.com>
+
+       * remote.c (remote_pid_to_exec_file): New.
+       (init_remote_ops): Register it.
+
+       2008-08-28  Pedro Alves  <pedro@codesourcery.com>
+
+       * infcmd.c (kill_if_already_running): If target supports
+       multi-process, allow multi-runs.
+
+       2008-08-28  Pedro Alves  <pedro@codesourcery.com>
+
+       * remote.c (extended_remote_create_inferior_1): Don't clear the
+       thread list.
+
 2008-11-25  Pedro Alves  <pedro@codesourcery.com>
 
        * inferior.c (itset_member): Fix typo again.
index cf4e844f16f52564efb92731d80fe8b5058925d4..ffa283e48bd9b34c49fbea3d54023f865870266d 100644 (file)
@@ -151,7 +151,7 @@ exec_close (int quitting)
        {
          /* We don't free objfiles because other code does it.  */
          if (ex->inferior)
-           delete_inferior (ex->inferior->pid);
+           delete_inferior_id (ex->inferior->num);
        }
 #if 0
       VEC_block_remove (exec_p, execs, 0, VEC_length (exec_p, execs));
index dfd6b2b35f94e8cbfacc9c91a9e7266d5214dfb9..52f738ad056ad2c22fae050ba66778ead2691f24 100644 (file)
@@ -982,6 +982,8 @@ get_current_frame (void)
     error (_("No stack."));
   if (!target_has_memory)
     error (_("No memory."));
+  if (ptid_equal (inferior_ptid, null_ptid))
+    error (_("No current inferior."));
   if (is_executing (inferior_ptid))
     error (_("Target is executing."));
 
@@ -1011,6 +1013,9 @@ has_stack_frames (void)
   if (!target_has_registers || !target_has_stack || !target_has_memory)
     return 0;
 
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
   /* If the current thread is executing, don't try to read from
      it.  */
   if (is_executing (inferior_ptid))
index a9bfd3e6cb0f1178793bfd362ccbfcf0d357f249..5d490165bd13f4dd2d2d678034972ca7e11d98ca 100644 (file)
@@ -553,11 +553,14 @@ kill_if_already_running (int from_tty)
         restart it.  */
       target_require_runnable ();
 
-      if (from_tty
-         && !query ("The program being debugged has been started already.\n\
+      if (!target_supports_multi_process ())
+       {
+         if (from_tty
+             && !query ("The program being debugged has been started already.\n\
 Start it from the beginning? "))
-       error (_("Program not restarted."));
-      target_kill ();
+           error (_("Program not restarted."));
+         target_kill ();
+       }
     }
 }
 
@@ -574,6 +577,7 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
 
   kill_if_already_running (from_tty);
 
+  /* This is bad.  */
   init_wait_for_inferior ();
   clear_breakpoint_hit_counts ();
 
@@ -2206,6 +2210,23 @@ proceed_after_attach (int pid)
   do_cleanups (old_chain);
 }
 
+struct exec_file_attach_wrapper_args
+{
+  char *path;
+  int from_tty;
+};
+
+static int
+exec_file_attach_wrapper (struct ui_out *ui_out, void *args)
+{
+  struct exec_file_attach_wrapper_args *a = args;
+
+  exec_file_attach (a->path, a->from_tty);
+  symbol_file_add_main (a->path, a->from_tty);
+
+  return 0;
+}
+
 /*
  * TODO:
  * Should save/restore the tty state since it might be that the
@@ -2241,19 +2262,47 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
       exec_file = target_pid_to_exec_file (PIDGET (inferior_ptid));
       if (exec_file)
        {
-         /* It's possible we don't have a full path, but rather just a
-            filename.  Some targets, such as HP-UX, don't provide the
-            full path, sigh.
-
-            Attempt to qualify the filename against the source path.
-            (If that fails, we'll just fall back on the original
-            filename.  Not much more we can do...)
-          */
-         if (!source_full_path_of (exec_file, &full_exec_path))
-           full_exec_path = savestring (exec_file, strlen (exec_file));
-
-         exec_file_attach (full_exec_path, from_tty);
-         symbol_file_add_main (full_exec_path, from_tty);
+         struct exec_file_attach_wrapper_args args;
+
+         if (gdb_sysroot && *gdb_sysroot)
+           {
+             char *name = xmalloc (strlen (gdb_sysroot)
+                                  + strlen (exec_file)
+                                  + 1);
+             strcpy (name, gdb_sysroot);
+             strcat (name, exec_file);
+             full_exec_path = name;
+           }
+         else
+           {
+             /* It's possible we don't have a full path, but rather just a
+                filename.  Some targets, such as HP-UX, don't provide the
+                full path, sigh.
+
+                Attempt to qualify the filename against the source path.
+                (If that fails, we'll just fall back on the original
+                filename.  Not much more we can do...)
+             */
+             if (!source_full_path_of (exec_file, &full_exec_path))
+               full_exec_path = savestring (exec_file, strlen (exec_file));
+           }
+
+         args.path = full_exec_path;
+         args.from_tty = from_tty;
+
+         /* Don't let failing to find symbols prevent trying to
+            finish the attach.  */
+         catch_exceptions (uiout, exec_file_attach_wrapper, &args,
+                           RETURN_MASK_ERROR);
+
+         /* Try to use the exec we (hopefully) just pulled in as the
+            inferior's exec.  */
+         if (!inferior->exec)
+           {
+             exec = find_exec_by_name (full_exec_path);
+             if (exec)
+               set_inferior_exec (inferior, exec);
+           }
        }
     }
   else
@@ -2262,6 +2311,14 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
       reread_symbols ();
     }
 
+  /* As a heuristic, if there is no exec assigned to the attached
+     inferior, but only one exec known to GDB, guess that it is the
+     exec for the the process just attached. (If GDB has guessed
+     wrong, it will be up to the user to use set-exec to fix
+     matters.)  */
+  if (!inferior->exec && number_of_execs () == 1)
+    set_inferior_exec (inferior, first_exec);
+
   /* Take any necessary post-attaching actions for this platform.  */
   target_post_attach (PIDGET (inferior_ptid));
 
@@ -2275,7 +2332,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
       /* The user requested an `attach&', so be sure to leave threads
         that didn't get a signal running.  */
 
-      /* Immediatelly resume all suspended threads of this inferior,
+      /* Immediately resume all suspended threads of this inferior,
         and this inferior only.  This should have no effect on
         already running threads.  If a thread has been stopped with a
         signal, leave it be.  */
@@ -2395,6 +2452,8 @@ attach_command (char *args, int from_tty)
 
   /* Set up execution context to know that we should return from
      wait_for_inferior as soon as the target reports a stop.  */
+
+  /* NOTE, NOTE, this is wrong in multi-process... */
   init_wait_for_inferior ();
   clear_proceed_status ();
 
@@ -2446,19 +2505,64 @@ attach_command (char *args, int from_tty)
 
   attach_command_post_wait (args, from_tty, async_exec);
 
-  /* As a heuristic, if there is no exec assigned to the attached
-     inferior, but only one exec known to GDB, guess that it is the
-     exec for the the process just attached. (If GDB has guessed
-     wrong, it will be up to the user to use set-exec to fix
-     matters.)  */
-  {
-    struct inferior *inferior = current_inferior ();
+}
+
+/* We had just found out that the target was already attached to an
+   inferior.  PTID points at a thread of this new inferior, that is
+   the most likelly to be stopped right now, but not necessarily so.
+   The new inferior has already been added to the inferior list at
+   this point.  */
+
+void
+notice_new_inferior (ptid_t ptid, int stopping, int from_tty)
+{
+  struct cleanup* old_chain;
+  struct inferior *inferior;
+  int async_exec;
+
+  old_chain = make_cleanup (null_cleanup, NULL);
+
+  /* If in non-stop, leave threads as running as they were.  If
+     they're stopped for some reason other than us telling it to, it
+     should report a signal != TARGET_SIGNAL_0.  */
+  async_exec = non_stop;
+
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    make_cleanup_restore_current_thread ();
+
+  switch_to_thread (ptid);
+
+  inferior = current_inferior ();
+
+  if (is_executing (inferior_ptid))
+    {
+      target_stop (inferior_ptid);
+
+      if (!non_stop)
+       inferior->stop_soon = STOP_QUIETLY_REMOTE;
 
-    if (!inferior->exec && number_of_execs () == 1)
-      set_inferior_exec (inferior, first_exec);
-  }
+      if (target_can_async_p ())
+       {
+         /* sync_execution mode.  Wait for stop.  */
+         struct attach_command_continuation_args *a;
 
-  discard_cleanups (back_to);
+         a = xmalloc (sizeof (*a));
+         a->args = xstrdup ("");
+         a->from_tty = from_tty;
+         a->async_exec = async_exec;
+         add_inferior_continuation (attach_command_continuation, a,
+                                    attach_command_continuation_free_args);
+
+         do_cleanups (old_chain);
+         return;
+       }
+      else
+       wait_for_inferior (0);
+    }
+
+  attach_command_post_wait ("" /* args */, from_tty, !stopping);
+
+  do_cleanups (old_chain);
 }
 
 /*
index 28da12df72b2ee7adf6626970947f0948cbd4bb3..096962d25ab206ef46f5b6c065c1bbe81c167ac7 100644 (file)
@@ -94,6 +94,8 @@ add_inferior_silent (int pid)
   memset (inf, 0, sizeof (*inf));
   inf->pid = pid;
 
+  inf->stop_soon = NO_STOP_QUIETLY;
+
   inf->num = ++highest_inferior_num;
   inf->next = inferior_list;
   inferior_list = inf;
@@ -138,16 +140,17 @@ delete_thread_of_inferior (struct thread_info *tp, void *data)
 
 /* If SILENT then be quiet -- don't announce a inferior death, or the
    exit of its threads.  */
-static void
-delete_inferior_1 (int pid, int silent)
+
+void
+delete_inferior_struct (struct inferior *inftodel, int silent)
 {
   struct inferior *inf, *infprev;
-  struct delete_thread_of_inferior_arg arg = { pid, silent };
+  struct delete_thread_of_inferior_arg arg;
 
   infprev = NULL;
 
   for (inf = inferior_list; inf; infprev = inf, inf = inf->next)
-    if (inf->pid == pid)
+    if (inf == inftodel)
       break;
 
   if (!inf)
@@ -158,38 +161,42 @@ delete_inferior_1 (int pid, int silent)
   else
     inferior_list = inf->next;
 
-  free_inferior (inf);
-
-  arg.pid = pid;
-  arg.silent = silent;
-
-  iterate_over_threads (delete_thread_of_inferior, &arg);
+  if (inf->pid != 0)
+    {
+      arg.pid = inf->pid;
+      arg.silent = silent;
+      iterate_over_threads (delete_thread_of_inferior, &arg);
+    }
 
-  observer_notify_inferior_exit (pid);
+  observer_notify_inferior_exit (inf->pid);
+  free_inferior (inf);
 }
 
 void
-delete_inferior (int pid)
+delete_inferior_id (int num)
 {
-  delete_inferior_1 (pid, 0);
-
-  if (print_inferior_events)
-    printf_unfiltered (_("[Inferior %d exited]\n"), pid);
+  struct inferior *inf = find_inferior_id (num);
+  delete_inferior_struct (inf, 0);
 }
 
 void
-delete_inferior_silent (int pid)
+delete_inferior (int pid)
 {
-  delete_inferior_1 (pid, 1);
+  struct inferior *inf = find_inferior_pid (pid);
+  if (inf)
+    {
+      delete_inferior_struct (inf, 0);
+      if (print_inferior_events)
+       printf_unfiltered (_("[Inferior %d exited]\n"), pid);
+    }
 }
 
 void
-detach_inferior (int pid)
+delete_inferior_silent (int pid)
 {
-  delete_inferior_1 (pid, 1);
-
-  if (print_inferior_events)
-    printf_unfiltered (_("[Inferior %d detached]\n"), pid);
+  struct inferior *inf = find_inferior_pid (pid);
+  if (inf)
+    delete_inferior_struct (inf, 1);
 }
 
 void
@@ -200,7 +207,20 @@ discard_all_inferiors (void)
   for (inf = inferior_list; inf; inf = infnext)
     {
       infnext = inf->next;
-      delete_inferior_silent (inf->pid);
+      if (inf->pid != 0)
+       delete_inferior_struct (inf, 1);
+    }
+}
+
+void
+detach_inferior (int pid)
+{
+  struct inferior *inf = find_inferior_pid (pid);
+  if (inf)
+    {
+      delete_inferior_struct (inf, 1);
+      if (print_inferior_events)
+       printf_unfiltered (_("[Inferior %d detached]\n"), pid);
     }
 }
 
@@ -309,6 +329,18 @@ have_inferiors (void)
   return inferior_list != NULL;
 }
 
+/* Returns true if there are any non-proto inferiors.  */
+int
+have_real_inferiors (void)
+{
+  struct inferior *inf;
+
+  for (inf = inferior_list; inf; inf = inf->next)
+    if (inf->pid != 0)
+      return 1;
+  return 0;
+}
+
 int
 number_of_inferiors (void)
 {
@@ -383,15 +415,21 @@ print_inferior (struct ui_out *uiout, int requested_inferior)
              ui_out_field_string (uiout, "io_terminal", "term=Y");
            }
        }
+
 #if 0
-      extra_info = target_extra_inferior_info (inf);
-      if (extra_info)
+      /* Only query the target about real inferiors.  */
+      if (inf->pid != 0)
        {
-         ui_out_text (uiout, " (");
-         ui_out_field_string (uiout, "details", extra_info);
-         ui_out_text (uiout, ")");
+         extra_info = target_extra_inferior_info (inf);
+         if (extra_info)
+           {
+             ui_out_text (uiout, " (");
+             ui_out_field_string (uiout, "details", extra_info);
+             ui_out_text (uiout, ")");
+           }
        }
 #endif
+
       ui_out_text (uiout, "\n");
       do_cleanups (chain2);
     }
@@ -491,11 +529,9 @@ remove_inferior_command (char *args, int from_tty)
 
   for (ix = 0; VEC_iterate (itset_entry, itset->inferiors, ix, entry); ++ix)
     {
-#if 0
       if (entry->inferior->removable)
-       delete_inferior (entry->inferior);
+       delete_inferior_struct (entry->inferior, 0);
       /* (should remove threads?) */
-#endif
     }
 }
 
index c951026f3e261e79559066818b6a4768798175d8..ae60e2e90899d58aabf46fefaa86ebbd3b5dc3e5 100644 (file)
@@ -274,6 +274,8 @@ extern void interrupt_target_1 (int all_threads);
 
 extern void detach_command (char *, int);
 
+extern void notice_new_inferior (ptid_t, int, int);
+
 /* Address at which inferior stopped.  */
 
 extern CORE_ADDR stop_pc;
@@ -366,6 +368,8 @@ extern int suppress_stop_observer;
 /* When set, no calls to target_resumed observer will be made.  */
 extern int suppress_resume_observer;
 
+extern int detach_fork;
+
 \f
 /* Possible values for gdbarch_call_dummy_location.  */
 #define ON_STACK 1
@@ -532,6 +536,9 @@ extern void delete_inferior_silent (int pid);
 /* Delete an existing inferior list entry, due to inferior detaching.  */
 extern void detach_inferior (int pid);
 
+/* Delete inferior with GDB inferior id NUM.  */
+extern void delete_inferior_id (int num);
+
 /* Get rid of all inferiors.  */
 extern void discard_all_inferiors (void);
 
@@ -550,9 +557,12 @@ extern int in_inferior_list (int pid);
    not the system's).  */
 extern int valid_inferior_id (int num);
 
-/* Search function to lookup a inferior by target 'pid'.  */
+/* Search function to lookup an inferior by target 'pid'.  */
 extern struct inferior *find_inferior_pid (int pid);
 
+/* Search function to lookup an inferior by GDB 'num'.  */
+extern struct inferior *find_inferior_id (int num);
+
 /* Inferior iterator function.
 
    Calls a callback function once for each inferior, so long as the
index a459c97f6b680e5f0874cec2c3addbaa337aba32..cd809edb6612b97ecba46f99739c37efec4cbcd2 100644 (file)
@@ -5307,6 +5307,12 @@ By default, the debugger will follow the parent process."),
                        show_follow_fork_mode_string,
                        &setlist, &showlist);
 
+  add_setshow_boolean_cmd ("detach-on-fork", class_run, &detach_fork, _("\
+Set whether gdb will detach the child of a fork."), _("\
+Show whether gdb will detach the child of a fork."), _("\
+Tells gdb whether to detach the child of a fork."),
+                          NULL, NULL, &setlist, &showlist);
+
   add_setshow_enum_cmd ("scheduler-locking", class_run, 
                        scheduler_enums, &scheduler_mode, _("\
 Set mode for locking scheduler during execution."), _("\
index 498db30189bee3446dca217beb4588a8bf6bf3ed..c8aee9119d0bd7da25aec56cd1b735e15f1bcce3 100644 (file)
@@ -34,8 +34,6 @@
 #include "gdb_dirent.h"
 #include <ctype.h>
 
-extern int detach_fork;
-
 struct fork_info *fork_list;
 static int highest_fork_num;
 
@@ -670,14 +668,6 @@ _initialize_linux_fork (void)
 {
   init_fork_list ();
 
-  /* Set/show detach-on-fork: user-settable mode.  */
-
-  add_setshow_boolean_cmd ("detach-on-fork", class_obscure, &detach_fork, _("\
-Set whether gdb will detach the child of a fork."), _("\
-Show whether gdb will detach the child of a fork."), _("\
-Tells gdb whether to detach the child of a fork."), 
-                          NULL, NULL, &setlist, &showlist);
-
   /* Set/show restart-auto-finish: user-settable count.  Causes the
      first "restart" of a fork to do some number of "finish" commands
      before returning to user.
index 47eb98213abca0473e56686c6de5df05c17df6ed..0d1d79f06d3633ab4ed219a6105155934dffde61 100644 (file)
@@ -1126,53 +1126,87 @@ static ptid_t general_thread;
 static ptid_t continue_thread;
 
 static void
-notice_new_inferiors (ptid_t currthread)
+notice_new_inferiors (ptid_t currthread, int running)
 {
+  struct remote_state *rs = get_remote_state ();
+  struct inferior *inf = NULL;
+
   /* If this is a new thread, add it to GDB's thread list.
      If we leave it up to WFI to do this, bad things will happen.  */
 
   if (in_thread_list (currthread) && is_exited (currthread))
     {
+      int pid = ptid_get_pid (currthread);
+      if (!in_inferior_list (pid))
+       {
+         inf = add_inferior (pid);
+
+         /* This may be the first inferior we hear about.  */
+         if (!target_has_execution)
+           {
+             if (rs->extended)
+               target_mark_running (&extended_remote_ops);
+             else
+               target_mark_running (&remote_ops);
+           }
+       }
+
       /* We're seeing an event on a thread id we knew had exited.
         This has to be a new thread reusing the old id.  Add it.  */
       add_thread (currthread);
-      return;
-    }
 
-  if (!in_thread_list (currthread))
+      set_executing (currthread, running);
+      set_running (currthread, running);
+    }
+  else if (!in_thread_list (currthread))
     {
       if (ptid_equal (pid_to_ptid (ptid_get_pid (currthread)), inferior_ptid))
        {
          /* inferior_ptid has no thread member yet.  This can happen
             with the vAttach -> remote_wait,"TAAthread:" path if the
             stub doesn't support qC.  This is the first stop reported
-            after an attach, so this is the main thread.  Update the
-            ptid in the thread list.  */
-         thread_change_ptid (inferior_ptid, currthread);
-         return;
+            after an attach, so this is the main thread.  */
+         thread_change_ptid (inferior_ptid, currthread);
        }
-
-      if (ptid_equal (magic_null_ptid, inferior_ptid))
+      else if (ptid_equal (magic_null_ptid, inferior_ptid))
        {
          /* inferior_ptid is not set yet.  This can happen with the
             vRun -> remote_wait,"TAAthread:" path if the stub
             doesn't support qC.  This is the first stop reported
             after an attach, so this is the main thread.  Update the
             ptid in the thread list.  */
-         thread_change_ptid (inferior_ptid, currthread);
-         return;
+         thread_change_ptid (inferior_ptid, currthread);
        }
+      else
+       {
+         /* When connecting to a target remote, or to a target
+            extended-remote which already was debugging an inferior, we
+            may not know about it yet.  Add it before adding its child
+            thread, so notifications are emitted in a sensible order.  */
+         if (!in_inferior_list (ptid_get_pid (currthread)))
+           {
+             inf = add_inferior (ptid_get_pid (currthread));
 
-      /* When connecting to a target remote, or to a target
-        extended-remote which already was debugging an inferior, we
-        may not know about it yet.  Add it before adding its child
-        thread, so notifications are emitted in a sensible order.  */
-      if (!in_inferior_list (ptid_get_pid (currthread)))
-       add_inferior (ptid_get_pid (currthread));
+             /* This may be the first inferior we hear about.  */
+             if (!target_has_execution)
+               {
+                 if (rs->extended)
+               target_mark_running (&extended_remote_ops);
+                 else
+                   target_mark_running (&remote_ops);
+               }
+           }
 
-      /* This is really a new thread.  Add it.  */
-      add_thread (currthread);
+         /* This is really a new thread.  Add it.  */
+         add_thread (currthread);
+         set_executing (currthread, running);
+         set_running (currthread, running);
+       }
     }
+
+  if (inf)
+    /* Do whatever is needed to do with a new inferior.  */
+    notice_new_inferior (currthread, !running, 0);
 }
 
 /* Call this function as a result of
@@ -1190,7 +1224,7 @@ record_currthread (ptid_t currthread)
     /* We're just invalidating the local thread mirror.  */
     return;
 
-  notice_new_inferiors (currthread);
+  notice_new_inferiors (currthread, 0);
 }
 
 static char *last_pass_packet;
@@ -1279,6 +1313,23 @@ set_thread (struct ptid ptid, int gen)
     write_ptid (buf, endbuf, ptid);
   putpkt (rs->buf);
   getpkt (&rs->buf, &rs->buf_size, 0);
+
+  if (rs->buf[0]
+      && strcmp (rs->buf, "OK") != 0)
+    {
+      /* If we get an error setting a thread, it's because it is no
+        longer valid.  */
+      if (!ptid_equal (minus_one_ptid, ptid)
+         && !ptid_equal (null_ptid, ptid)
+         && !ptid_equal (any_thread_ptid, ptid)
+         && !ptid_is_pid (ptid))
+       {
+         int num = pid_to_thread_id (ptid);
+         delete_thread (ptid);
+         error (_("Thread ID %d has terminated."), num);
+       }
+    }
+
   if (gen)
     general_thread = ptid;
   else
@@ -1525,8 +1576,13 @@ read_ptid (char *buf, char **obuf)
   pp = unpack_varlen_hex (p, &tid);
 
   /* Since the stub is not sending a process id, then default to
-     what's in inferior_ptid.  */
-  pid = ptid_get_pid (inferior_ptid);
+     what's in inferior_ptid, unless it's null at this point.  If so,
+     then since there's no way to know the pid of the reported
+     threads, use the magic number.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    pid = ptid_get_pid (magic_null_ptid);
+  else
+    pid = ptid_get_pid (inferior_ptid);
 
   if (obuf)
     *obuf = pp;
@@ -2148,27 +2204,15 @@ remote_threads_info (void)
              do
                {
                  new_thread = read_ptid (bufp, &bufp);
-                 if (!ptid_equal (new_thread, null_ptid)
-                     && (!in_thread_list (new_thread)
-                         || is_exited (new_thread)))
+                 if (!ptid_equal (new_thread, null_ptid))
                    {
-                     /* When connected to a multi-process aware stub,
-                        "info threads" may show up threads of
-                        inferiors we didn't know about yet.  Add them
-                        now, and before adding any of its child
-                        threads, so notifications are emitted in a
-                        sensible order.  */
-                     if (!in_inferior_list (ptid_get_pid (new_thread)))
-                       add_inferior (ptid_get_pid (new_thread));
-
-                     add_thread (new_thread);
-
                      /* In non-stop mode, we assume new found threads
-                        are running until we proven otherwise with a
+                        are running until proven otherwise with a
                         stop reply.  In all-stop, we can only get
                         here if all threads are stopped.  */
-                     set_executing (new_thread, non_stop ? 1 : 0);
-                     set_running (new_thread, non_stop ? 1 : 0);
+                     int running = non_stop ? 1 : 0;
+
+                     notice_new_inferiors (new_thread, running);
                    }
                }
              while (*bufp++ == ',');   /* comma-separated list */
@@ -2576,12 +2620,6 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
         The '?' query below will then tell us about which threads are
         stopped.  */
 
-      /* If we're not using the multi-process extensions, there's no
-        way to know the pid of the reported threads; use the magic
-        number.  */
-      if (!remote_multi_process_p (rs))
-       inferior_ptid = magic_null_ptid;
-
       remote_threads_info ();
     }
   else if (rs->non_stop_aware)
@@ -2601,6 +2639,8 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
 
   if (!non_stop)
     {
+      int saved_async = 0;
+
       if (rs->buf[0] == 'W' || rs->buf[0] == 'X')
        {
          if (args->extended_p)
@@ -2638,11 +2678,12 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
       /* Now, if we have thread information, update inferior_ptid.  */
       inferior_ptid = remote_current_thread (inferior_ptid);
 
-      add_inferior (ptid_get_pid (inferior_ptid));
+      inf = add_inferior (ptid_get_pid (inferior_ptid));
 
       /* Always add the main thread.  */
       add_thread_silent (inferior_ptid);
 
+      /* TODO: This should be done in notice_new_inferiors.  */
       get_offsets ();          /* Get text, data & bss offsets.  */
 
       /* Use the previously fetched status.  */
@@ -2651,7 +2692,37 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
       rs->cached_wait_status = 1;
 
       immediate_quit--;
-      start_remote (args->from_tty); /* Initialize gdb process mechanisms.  */
+      init_wait_for_inferior ();
+
+      /* We know the inferior is stopped already, as we have a pending
+        wait status.  We need to force this event through
+        handle_inferior_event.  Pretend the inferior is running, so
+        notice_new_inferior will force a target_stop and a
+        target_wait, to collect the event.  remote_stop_as
+        (target_stop) will notice we have a cached wait status and
+        will not pass the request to the remote.  */
+      {
+       struct cleanup *old_chain;
+       old_chain = make_cleanup_restore_integer (&suppress_resume_observer);
+
+       /* Don't output '*running'.  */
+       suppress_resume_observer = 1;
+
+       set_executing (inferior_ptid, 1);
+       set_running (inferior_ptid, 1);
+
+       suppress_resume_observer = 0;
+      }
+
+      /* Collect the pending event synchronously, instead of going
+        through the event loop.  */
+      if (target_can_async_p ())
+       saved_async = target_async_mask (0);
+
+      notice_new_inferior (inferior_ptid, 1, args->from_tty);
+
+      if (saved_async)
+       target_async_mask (saved_async);
     }
   else
     {
@@ -2710,10 +2781,13 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
       if (ptid_equal (inferior_ptid, minus_one_ptid))
        error (_("remote didn't report the current thread in non-stop mode"));
 
+      /* TODO: This should be done whenever we notice a new
+        inferior.  */
       get_offsets ();          /* Get text, data & bss offsets.  */
 
       /* In non-stop mode, any cached wait status will be stored in
-        the stop reply queue.  */
+        the stop reply queue.  Also, we can only reach here if
+        threads were found.  */
       gdb_assert (wait_status == NULL);
     }
 
@@ -4384,7 +4458,65 @@ Packet: '%s'\n"),
        else
          error (_("unknown stop reply packet: %s"), buf);
        event->ptid = pid_to_ptid (pid);
+       break;
       }
+    case 'Y':
+      {
+       char *p = buf + 1;
+       if (*p != ';')
+         error (_("unknown stop reply packet: %s"), buf);
+
+       p++;
+       if (strncmp (p, "fork;", 5) == 0)
+         {
+           p += 5;
+           event->ws.kind = TARGET_WAITKIND_FORKED;
+         }
+       else if (strncmp (p, "vfork;", 6) == 0)
+         {
+           p += 6;
+           event->ws.kind = TARGET_WAITKIND_VFORKED;
+         }
+       else if (strncmp (p, "exec;", 5) == 0)
+         {
+           p += 5;
+           event->ws.kind = TARGET_WAITKIND_EXECD;
+         }
+       else
+         error (_("unknown stop reply packet: %s"), buf);
+
+       event->ptid = read_ptid (p, &p);
+
+       if (*p != ';')
+         error (_("unknown stop reply packet: %s"), buf);
+       p++;
+
+       if (event->ws.kind == TARGET_WAITKIND_EXECD)
+         {
+           struct cleanup *old_chain;
+           int result;
+           char *buf;
+
+           buf = xmalloc (strlen (p) + 1);
+           result = hex2bin (p, (gdb_byte *) buf, strlen (p));
+           buf [result] = '\0';
+           event->ws.value.execd_pathname = buf;
+
+           /* At this point, all inserted breakpoints are gone.
+              Doing this as soon as we detect an exec prevents the
+              badness of deleting a breakpoint writing the current
+              "shadow contents" to lift the bp.  That shadow is NOT
+              valid after an exec.  */
+
+           old_chain = save_inferior_ptid ();
+           inferior_ptid = event->ptid;
+           mark_breakpoints_out ();
+           do_cleanups (old_chain);
+         }
+       else
+         event->ws.value.related_pid = read_ptid (p, &p);
+      }
+
       break;
     }
 
@@ -4504,7 +4636,7 @@ process_stop_reply (struct stop_reply *stop_reply,
       delete_inferior (pid);
     }
   else
-    notice_new_inferiors (ptid);
+    notice_new_inferiors (ptid, 0);
 
   /* Expedited registers.  */
   if (stop_reply->regcache)
@@ -4655,7 +4787,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status)
     case 'F':          /* File-I/O request.  */
       remote_fileio_request (buf);
       break;
-    case 'T': case 'S': case 'X': case 'W':
+    case 'T': case 'S': case 'X': case 'W': case 'Y':
       {
        struct stop_reply *stop_reply;
        struct cleanup *old_chain;
@@ -4681,7 +4813,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status)
             remote system doesn't support it.  */
          target_terminal_ours_for_output ();
          printf_filtered
-           ("Can't send signals to this remote system.  %s not sent.\n",
+           ("Can't send signals to this remote system.  %s not sent.\n",
             target_signal_to_name (last_sent_signal));
          last_sent_signal = TARGET_SIGNAL_0;
          target_terminal_inferior ();
@@ -6550,7 +6682,7 @@ extended_remote_mourn_1 (struct target_ops *target)
   /* Unlike "target remote", we do not want to unpush the target; then
      the next time the user says "run", we won't be connected.  */
 
-  if (have_inferiors ())
+  if (have_real_inferiors ())
     {
       extern void nullify_last_target_wait_ptid ();
       /* Multi-process case.  The current process has exited, but
@@ -6691,11 +6823,15 @@ extended_remote_create_inferior_1 (char *exec_file, char *args,
       extended_remote_restart ();
     }
 
+#if 0
+  /* FIXME: How does this look with itsets?  */
+
   /* Clean up from the last time we ran, before we mark the target
      running again.  This will mark breakpoints uninserted, and
      get_offsets may insert breakpoints.  */
   init_thread_list ();
   init_wait_for_inferior ();
+#endif
 
   /* Now mark the inferior as running before we do anything else.  */
   inferior_ptid = magic_null_ptid;
@@ -6716,7 +6852,7 @@ extended_remote_create_inferior_1 (char *exec_file, char *args,
 }
 
 static void
-extended_remote_create_inferior (struct target_ops *ops, 
+extended_remote_create_inferior (struct target_ops *ops,
                                 char *exec_file, char *args,
                                 char **env, int from_tty)
 {
@@ -7263,7 +7399,6 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
   char *p2;
   char query_type;
 
-  
   if (tmp_inf && tmp_inf->pid != ptid_get_pid (inferior_ptid))
     {
       ptid_t tmp_ptid;
@@ -8635,6 +8770,217 @@ remote_supports_multi_process (void)
   return remote_multi_process_p (rs);
 }
 
+char *
+remote_pid_to_exec_file (int pid)
+{
+  struct remote_state *rs;
+
+  rs = get_remote_state ();
+
+  sprintf (rs->buf, "qExecFile:%x", pid);
+  putpkt (rs->buf);
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  if (*rs->buf == '\0')
+    /* Not supported */ ;
+  else if (strncmp (rs->buf, "QExecFile:", 10) == 0)
+    {
+      static char *buf = NULL;
+      int n, result;
+      char *p;
+
+      p = strchr (rs->buf + 10, ';');
+
+      if (p == NULL)
+       {
+         warning (_("Invalid qExecFile reply: %s"), rs->buf);
+         return NULL;
+       }
+
+      p++;
+
+      if (buf == NULL)
+       make_final_cleanup (xfree, buf);
+      else
+       xfree (buf);
+
+      buf = xmalloc (strlen (p) + 1);
+      result = hex2bin (p, (gdb_byte *) buf, strlen (p));
+      buf [result] = '\0';
+
+      return buf;
+    }
+  else if (*rs->buf == 'E')
+    ;
+  else
+    warning (_("Invalid qExecFile reply: %s"), rs->buf);
+
+  return NULL;
+}
+
+static void
+remote_detach_pid (int pid)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  /* Tell the remote target to detach.  */
+  sprintf (rs->buf, "D;%x", pid);
+
+  putpkt (rs->buf);
+  getpkt (&rs->buf, &rs->buf_size, 0);
+
+  if (strcmp (rs->buf, "OK") == 0)
+    ;
+  else if (rs->buf[0] == '\0')
+    error (_("Remote doesn't know how to detach"));
+  else
+    error (_("Can't detach process."));
+}
+
+static int
+remote_follow_fork (struct target_ops *ops, int follow_child)
+{
+  ptid_t last_ptid;
+  struct target_waitstatus last_status;
+  int has_vforked;
+  int parent_pid, child_pid;
+
+  get_last_target_status (&last_ptid, &last_status);
+  has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
+  parent_pid = ptid_get_tid (last_ptid);
+  if (parent_pid == 0)
+    parent_pid = ptid_get_pid (last_ptid);
+  child_pid = PIDGET (last_status.value.related_pid);
+
+  if (! follow_child)
+    {
+      /* We're already attached to the parent, by default.  */
+
+      /* Before detaching from the child, remove all breakpoints from
+         it.  (This won't actually modify the breakpoint list, but
+         will physically remove the breakpoints from the child.)  */
+      /* If we vforked this will remove the breakpoints from the
+        parent also, but they'll be reinserted below.  */
+      set_general_thread (last_status.value.related_pid);
+      detach_breakpoints (child_pid);
+
+      /* Detach new forked process?  */
+      if (detach_fork)
+       {
+         if (info_verbose || remote_debug)
+           {
+             target_terminal_ours ();
+             fprintf_filtered (gdb_stdlog,
+                               "Detaching after fork from child process %d.\n",
+                               child_pid);
+           }
+
+         /* Tell the remote target to detach.  */
+         remote_detach_pid (child_pid);
+       }
+      else
+       {
+         /* Add process to GDB's tables.  */
+         add_inferior (child_pid);
+       }
+
+      set_general_thread (last_ptid);
+
+      if (has_vforked)
+       {
+         /* TODO here: Wait for linux's VFORK_DONE, or HPUX's
+            TTEVT_VFORK, or equivalent.  */
+
+         /* Since we vforked, breakpoints were removed in the parent
+            too.  Put them back.  */
+         reattach_breakpoints (parent_pid);
+       }
+    }
+  else
+    {
+      struct thread_info *last_tp = find_thread_pid (last_ptid);
+      struct thread_info *tp;
+
+      /* Copy user stepping state to the new inferior thread.  */
+      struct breakpoint *step_resume_breakpoint = last_tp->step_resume_breakpoint;
+      CORE_ADDR step_range_start = last_tp->step_range_start;
+      CORE_ADDR step_range_end = last_tp->step_range_end;
+      struct frame_id step_frame_id = last_tp->step_frame_id;
+
+      last_tp->step_range_start = 0;
+      last_tp->step_range_end = last_tp->step_range_end  = 0;
+      last_tp->step_frame_id = null_frame_id;
+
+      /* Otherwise, deleting the parent would get rid of this
+        breakpoint.  */
+      last_tp->step_resume_breakpoint = NULL;
+
+      /* Needed to keep the breakpoint lists in sync.  */
+      if (! has_vforked)
+       {
+         set_general_thread (last_status.value.related_pid);
+         detach_breakpoints (child_pid);
+       }
+
+      /* Before detaching from the parent, remove all breakpoints from it. */
+      set_general_thread (last_ptid);
+      remove_breakpoints ();
+
+      if (info_verbose || remote_debug)
+       {
+         target_terminal_ours ();
+         fprintf_filtered (gdb_stdlog,
+                           "Attaching after fork to child process %d.\n",
+                           child_pid);
+       }
+
+      /* If we're vforking, we may want to hold on to the parent until
+        the child exits or execs.  At exec time we can remove the old
+        breakpoints from the parent and detach it; at exit time we
+        could do the same (or even, sneakily, resume debugging it - the
+        child's exec has failed, or something similar).
+
+        The holding part is very easy if we have VFORKDONE events;
+        but keeping track of both processes is beyond GDB at the
+        moment.  So we don't expose the parent to the rest of GDB.
+        Instead we quietly hold onto it until such time as we can
+        safely resume it.  */
+
+      if (has_vforked)
+       {
+         /* TODO: handle this correctly.
+
+         remote_fork_parent_pid = parent_pid;
+
+         */
+         detach_inferior (parent_pid);
+       }
+      else if (detach_fork)
+       {
+         remote_detach_pid (parent_pid);
+         detach_inferior (parent_pid);
+       }
+
+      add_inferior (child_pid);
+
+      inferior_ptid = ptid_build (child_pid, 0, 0);
+      set_general_thread (inferior_ptid);
+      inferior_ptid = remote_current_thread (inferior_ptid);
+      set_general_thread (inferior_ptid);
+
+      tp = add_thread (inferior_ptid);
+
+      tp->step_resume_breakpoint = step_resume_breakpoint;
+      tp->step_range_start = step_range_start;
+      tp->step_range_end = step_range_end;
+      tp->step_frame_id = step_frame_id;
+
+      /* Reset breakpoints in the child as appropriate.  */
+      follow_inferior_reset_breakpoints ();
+    }
+
+  return 0;
+}
+
 static void
 init_remote_ops (void)
 {
@@ -8698,6 +9044,8 @@ Specify the serial device it is connected to\n\
   remote_ops.to_terminal_ours = remote_terminal_ours;
   remote_ops.to_supports_non_stop = remote_supports_non_stop;
   remote_ops.to_supports_multi_process = remote_supports_multi_process;
+  remote_ops.to_pid_to_exec_file = remote_pid_to_exec_file;
+  remote_ops.to_follow_fork = remote_follow_fork;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
index 3c1019b22c1f5d5c304d45e4679b217f6615535a..392de10fce91ba86352541c1d701ff2b0af4d181 100644 (file)
@@ -1639,6 +1639,9 @@ get_selected_block (CORE_ADDR *addr_in_block)
   if (!target_has_stack)
     return 0;
 
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
   if (is_exited (inferior_ptid))
     return 0;
 
index c77ba9761f8b26e9472d823d2b57365b0ff3cd55..e77ceb8c1b60991d20cef22901b6838d526efba8 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -481,7 +481,9 @@ Cannot execute this command without a live selected thread.  See `help thread'."
   /* FIXME:  This should be cacheing the frame and only running when
      the frame changes.  */
 
-  if (target_has_stack && is_stopped (inferior_ptid))
+  if (target_has_stack
+      && !ptid_equal (inferior_ptid, null_ptid)
+      && is_stopped (inferior_ptid))
     {
       flang = get_frame_language ();
       if (!warned