This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] gdbserver crash if gdb attaches too fast


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=500c1d8576ad5a5bdc791fc7f7c3518a4d3f4b39

commit 500c1d8576ad5a5bdc791fc7f7c3518a4d3f4b39
Author: Pedro Alves <palves@redhat.com>
Date:   Mon Nov 30 16:05:18 2015 +0000

    gdbserver crash if gdb attaches too fast
    
    With "maint set target-non-stop on", the attach tests occasionally
    crash gdbserver.
    
    Basically, gdb attaches with vAttach;PID, and then shortly after reads
    the xml target description for that process, to figure out the
    process' architecture.  On the gdbserver side, the target description
    is only filled in when the first process/thread in the thread group
    reports its initial PTRACE_ATTACH SIGSTOP.  So if GDB is fast enough,
    it can read the target description _before_ that initial stop, and
    then gdbserver dies dereferencing a NULL tdesc pointer.
    
    gdb/gdbserver/ChangeLog:
    2015-11-30  Pedro Alves  <palves@redhat.com>
    
    	* linux-low.c (linux_attach): In non-stop mode, wait for one stop
    	before returning.

Diff:
---
 gdb/gdbserver/ChangeLog   |  5 +++++
 gdb/gdbserver/linux-low.c | 53 ++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 22d729f..3d694ac 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,10 @@
 2015-11-30  Pedro Alves  <palves@redhat.com>
 
+	* linux-low.c (linux_attach): In non-stop mode, wait for one stop
+	before returning.
+
+2015-11-30  Pedro Alves  <palves@redhat.com>
+
 	* server.c (handle_v_requests): Handle vCtrlC.
 
 2015-11-30  Pedro Alves  <palves@redhat.com>
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index a70868c..69fda7f 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -1029,12 +1029,16 @@ attach_proc_task_lwp_callback (ptid_t ptid)
   return 0;
 }
 
+static void async_file_mark (void);
+
 /* Attach to PID.  If PID is the tgid, attach to it and all
    of its threads.  */
 
 static int
 linux_attach (unsigned long pid)
 {
+  struct process_info *proc;
+  struct thread_info *initial_thread;
   ptid_t ptid = ptid_build (pid, pid, 0);
   int err;
 
@@ -1045,17 +1049,12 @@ linux_attach (unsigned long pid)
     error ("Cannot attach to process %ld: %s",
 	   pid, linux_ptrace_attach_fail_reason_string (ptid, err));
 
-  linux_add_process (pid, 1);
-
-  if (!non_stop)
-    {
-      struct thread_info *thread;
+  proc = linux_add_process (pid, 1);
 
-     /* Don't ignore the initial SIGSTOP if we just attached to this
-	process.  It will be collected by wait shortly.  */
-      thread = find_thread_ptid (ptid_build (pid, pid, 0));
-      thread->last_resume_kind = resume_stop;
-    }
+  /* Don't ignore the initial SIGSTOP if we just attached to this
+     process.  It will be collected by wait shortly.  */
+  initial_thread = find_thread_ptid (ptid_build (pid, pid, 0));
+  initial_thread->last_resume_kind = resume_stop;
 
   /* We must attach to every LWP.  If /proc is mounted, use that to
      find them now.  On the one hand, the inferior may be using raw
@@ -1067,6 +1066,38 @@ linux_attach (unsigned long pid)
      that once thread_db is loaded, we'll still use it to list threads
      and associate pthread info with each LWP.  */
   linux_proc_attach_tgid_threads (pid, attach_proc_task_lwp_callback);
+
+  /* GDB will shortly read the xml target description for this
+     process, to figure out the process' architecture.  But the target
+     description is only filled in when the first process/thread in
+     the thread group reports its initial PTRACE_ATTACH SIGSTOP.  Do
+     that now, otherwise, if GDB is fast enough, it could read the
+     target description _before_ that initial stop.  */
+  if (non_stop)
+    {
+      struct lwp_info *lwp;
+      int wstat, lwpid;
+      ptid_t pid_ptid = pid_to_ptid (pid);
+
+      lwpid = linux_wait_for_event_filtered (pid_ptid, pid_ptid,
+					     &wstat, __WALL);
+      gdb_assert (lwpid > 0);
+
+      lwp = find_lwp_pid (pid_to_ptid (lwpid));
+
+      if (!WIFSTOPPED (wstat) || WSTOPSIG (wstat) != SIGSTOP)
+	{
+	  lwp->status_pending_p = 1;
+	  lwp->status_pending = wstat;
+	}
+
+      initial_thread->last_resume_kind = resume_continue;
+
+      async_file_mark ();
+
+      gdb_assert (proc->tdesc != NULL);
+    }
+
   return 0;
 }
 
@@ -2868,8 +2899,6 @@ linux_stabilize_threads (void)
     }
 }
 
-static void async_file_mark (void);
-
 /* Convenience function that is called when the kernel reports an
    event that is not passed out to GDB.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]