remote non-stop, fetch the shared library list and insert breakpoints on connection

Pedro Alves pedro@codesourcery.com
Wed Mar 4 22:59:00 GMT 2009


Currently, connecting to a remote target in non-stop mode, to a target
that *doesn't* have shared code across inferiors (e.g., linux gdbserver
non-stop), GDB isn't querying the shared library list, or inserting
breakpoints.  This patch teaches GDB to do so.

When we open a remote target and find out an inferior on the other end, most
of what GDB needs to do in non-stop mode, is the same as what GDB does
right after attaching to an inferior, except, we don't do the
attach request bit.  All that code is already abstracted out in
attach_command_post_wait, so we can reuse it.

Tested against pristine head x86_64 gdbserver and checked in.

-- 
Pedro Alves

2009-03-04  Pedro Alves  <pedro@codesourcery.com>

	* inferior.h (notice_new_inferior): Declare.
	* infcmd.c (notice_new_inferior): New.
	* remote.c (remote_add_inferior, remote_add_thread): New.
	(notice_new_inferiors): Rename to...
	(remote_notice_new_inferior): ... this.  Add RUNNING argument.
	Use remote_add_thread instead of add_thread, passing it the
	RUNNING argument.  Add an inferior with remote_add_inferior.  If
	we just learned about an inferior, call notice_new_inferior.
	(record_currthread): Adjust.
	(remote_threads_info): Adjust to use remote_notice_new_inferior.
	(remote_start_remote, extended_remote_attach_1): Use
	remote_add_inferior.
	(process_stop_reply): Adjust.  Call remote_notice_new_inferior
	after handling expedited registers and watchpoint state.
	(extended_remote_create_inferior_1): Use remote_add_inferior.

---
 gdb/infcmd.c   |   66 +++++++++++++++++++++++++++++++++++++
 gdb/inferior.h |    2 +
 gdb/remote.c   |  100 ++++++++++++++++++++++++++++++++++++++-------------------
 3 files changed, 135 insertions(+), 33 deletions(-)

Index: src/gdb/inferior.h
===================================================================
--- src.orig/gdb/inferior.h	2009-02-21 20:06:33.000000000 +0000
+++ src/gdb/inferior.h	2009-03-04 22:27:35.000000000 +0000
@@ -281,6 +281,8 @@ extern void interrupt_target_1 (int all_
 
 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;
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c	2009-03-04 22:26:57.000000000 +0000
+++ src/gdb/infcmd.c	2009-03-04 22:27:35.000000000 +0000
@@ -2313,6 +2313,72 @@ attach_command (char *args, int from_tty
   discard_cleanups (back_to);
 }
 
+/* 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 likely to be stopped right now, but not necessarily so.
+   The new inferior is assumed to be already added to the inferior
+   list at this point.  If LEAVE_RUNNING, then leave the threads of
+   this inferior running, except those we've explicitly seen reported
+   as stopped.  */
+
+void
+notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
+{
+  struct cleanup* old_chain;
+  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, the
+     target reports a signal != TARGET_SIGNAL_0.  We don't try to
+     resume threads with such a stop signal.  */
+  async_exec = non_stop;
+
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    make_cleanup_restore_current_thread ();
+
+  switch_to_thread (ptid);
+
+  /* When we "notice" a new inferior we need to do all the things we
+     would normally do if we had just attached to it.  */
+
+  if (is_executing (inferior_ptid))
+    {
+      struct inferior *inferior = current_inferior ();
+
+      /* We're going to install breakpoints, and poke at memory,
+	 ensure that the inferior is stopped for a moment while we do
+	 that.  */
+      target_stop (inferior_ptid);
+
+      inferior->stop_soon = STOP_QUIETLY_REMOTE;
+
+      /* Wait for stop before proceeding.  */
+      if (target_can_async_p ())
+	{
+	  struct attach_command_continuation_args *a;
+
+	  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);
+    }
+
+  async_exec = leave_running;
+  attach_command_post_wait ("" /* args */, from_tty, async_exec);
+
+  do_cleanups (old_chain);
+}
+
 /*
  * detach_command --
  * takes a program previously attached to and detaches it.
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2009-02-26 19:37:21.000000000 +0000
+++ src/gdb/remote.c	2009-03-04 22:47:24.000000000 +0000
@@ -1118,9 +1118,53 @@ static ptid_t any_thread_ptid;
 static ptid_t general_thread;
 static ptid_t continue_thread;
 
+/* Add PID to GDB's inferior table.  Since we can be connected to a
+   remote system before before knowing about any inferior, mark the
+   target with execution when we find the first inferior.  */
+
+static struct inferior *
+remote_add_inferior (int pid)
+{
+  struct remote_state *rs = get_remote_state ();
+  struct inferior *inf;
+
+  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);
+    }
+
+  return inf;
+}
+
+/* Add thread PTID to GDB's thread list.  Tag it as executing/running
+   according to RUNNING.  */
+
 static void
-notice_new_inferiors (ptid_t currthread)
+remote_add_thread (ptid_t ptid, int running)
 {
+  add_thread (ptid);
+
+  set_executing (ptid, running);
+  set_running (ptid, running);
+}
+
+/* Come here when we learn about a thread id from the remote target.
+   It may be the first time we hear about such thread, so take the
+   opportunity to add it to GDB's thread list.  In case this is the
+   first time we're noticing its corresponding inferior, add it to
+   GDB's inferior list as well.  */
+
+static void
+remote_notice_new_inferior (ptid_t currthread, int running)
+{
+  struct remote_state *rs = get_remote_state ();
+
   /* 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.  */
 
@@ -1128,12 +1172,14 @@ notice_new_inferiors (ptid_t currthread)
     {
       /* 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);
+      remote_add_thread (currthread, running);
       return;
     }
 
   if (!in_thread_list (currthread))
     {
+      struct inferior *inf = NULL;
+
       if (ptid_equal (pid_to_ptid (ptid_get_pid (currthread)), inferior_ptid))
 	{
 	  /* inferior_ptid has no thread member yet.  This can happen
@@ -1161,10 +1207,16 @@ notice_new_inferiors (ptid_t currthread)
 	 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));
+	inf = remote_add_inferior (ptid_get_pid (currthread));
 
       /* This is really a new thread.  Add it.  */
-      add_thread (currthread);
+      remote_add_thread (currthread, running);
+
+      /* If we found a new inferior, let the common code do whatever
+	 it needs to with it (e.g., read shared libraries, insert
+	 breakpoints).  */
+      if (inf != NULL)
+	notice_new_inferior (currthread, running, 0);
     }
 }
 
@@ -1183,7 +1235,7 @@ record_currthread (ptid_t currthread)
     /* We're just invalidating the local thread mirror.  */
     return;
 
-  notice_new_inferiors (currthread);
+  remote_notice_new_inferior (currthread, 0);
 }
 
 static char *last_pass_packet;
@@ -2146,27 +2198,15 @@ remote_threads_info (struct target_ops *
 	      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;
+
+		      remote_notice_new_inferior (new_thread, running);
 		    }
 		}
 	      while (*bufp++ == ',');	/* comma-separated list */
@@ -2605,9 +2645,6 @@ remote_start_remote (struct ui_out *uiou
 	}
       else
 	{
-	  if (args->extended_p)
-	    target_mark_running (args->target);
-
 	  /* Save the reply for later.  */
 	  wait_status = alloca (strlen (rs->buf) + 1);
 	  strcpy (wait_status, rs->buf);
@@ -2628,7 +2665,7 @@ remote_start_remote (struct ui_out *uiou
       /* Now, if we have thread information, update inferior_ptid.  */
       inferior_ptid = remote_current_thread (inferior_ptid);
 
-      add_inferior (ptid_get_pid (inferior_ptid));
+      remote_add_inferior (ptid_get_pid (inferior_ptid));
 
       /* Always add the main thread.  */
       add_thread_silent (inferior_ptid);
@@ -3394,13 +3431,12 @@ extended_remote_attach_1 (struct target_
     error (_("Attaching to %s failed"),
 	   target_pid_to_str (pid_to_ptid (pid)));
 
-  target_mark_running (target);
   inferior_ptid = pid_to_ptid (pid);
 
   /* Now, if we have thread information, update inferior_ptid.  */
   inferior_ptid = remote_current_thread (inferior_ptid);
 
-  inf = add_inferior (pid);
+  inf = remote_add_inferior (pid);
   inf->attach_flag = 1;
 
   if (non_stop)
@@ -4508,8 +4544,6 @@ process_stop_reply (struct stop_reply *s
   if (status->kind != TARGET_WAITKIND_EXITED
       && status->kind != TARGET_WAITKIND_SIGNALLED)
     {
-      notice_new_inferiors (ptid);
-
       /* Expedited registers.  */
       if (stop_reply->regcache)
 	{
@@ -4526,6 +4560,8 @@ process_stop_reply (struct stop_reply *s
 
       remote_stopped_by_watchpoint_p = stop_reply->stopped_by_watchpoint_p;
       remote_watch_data_address = stop_reply->watch_data_address;
+
+      remote_notice_new_inferior (ptid, 0);
     }
 
   stop_reply_xfree (stop_reply);
@@ -6725,11 +6761,9 @@ extended_remote_create_inferior_1 (char 
   /* Now, if we have thread information, update inferior_ptid.  */
   inferior_ptid = remote_current_thread (inferior_ptid);
 
-  add_inferior (ptid_get_pid (inferior_ptid));
+  remote_add_inferior (ptid_get_pid (inferior_ptid));
   add_thread_silent (inferior_ptid);
 
-  target_mark_running (&extended_remote_ops);
-
   /* Get updated offsets, if the stub uses qOffsets.  */
   get_offsets ();
 }



More information about the Gdb-patches mailing list