This is the mail archive of the gdb-patches@sources.redhat.com 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]

[commit] Use LWP IDs for thread IDs in gdbserver


Almost a shame to do this after all the time fixing support for
pointer-sized thread IDs, by both Jim and I, in gdb and gdbserver.  But
there's something we didn't think about.

I tried to debug a powerpc64-linux threaded program from a 32-bit host
yesterday.  gdbserver reports thread IDs as unsigned longs, which are 64-bit. 
The client gdb uses strtoul to parse them, and ptid_t uses longs to store
them.  All this seemed consistent - until I realized that long was 64-bit
for gdbserver and 32-bit for gdb.  GDB truncated most thread IDs to -1.

At any given time a GNU/Linux system will only have one thread with a given
PID. So this patch makes gdbserver use the PID to communicate with GDB. 
Actually it adds support for an arbitrary thread ID -> gdb ID mapping, but
PID is all we need to use on GNU/Linux.

Tested on powerpc64-linux and i386-linux targets and committed.

-- 
Daniel Jacobowitz
CodeSourcery, LLC

2005-07-13  Daniel Jacobowitz  <dan@codesourcery.com>

	* inferiors.c (struct thread_info): Add gdb_id.
	(add_thread): Add gdb_id argument.
	(thread_id_to_gdb_id, thread_to_gdb_id, gdb_id_to_thread_id): New.
	* linux-low.c (linux_create_inferior, linux_attach_lwp): Update
	calls to add_thread.
	* remote-utils.c (prepare_resume_reply: Use thread_to_gdb_id.
	* server.c (handle_query): Use thread_to_gdb_id.
	(handle_v_cont, main): Use gdb_id_to_thread_id.
	* server.h (add_thread): Update prototype.
	(thread_id_to_gdb_id, thread_to_gdb_id, gdb_id_to_thread_id): New
	prototypes.

Index: inferiors.c
===================================================================
RCS file: /home/gcc/repos/src/src/gdb/gdbserver/inferiors.c,v
retrieving revision 1.5
diff -u -p -r1.5 inferiors.c
--- inferiors.c	3 Mar 2005 16:56:53 -0000	1.5
+++ inferiors.c	13 Jul 2005 13:36:06 -0000
@@ -30,6 +30,7 @@ struct thread_info
   struct inferior_list_entry entry;
   void *target_data;
   void *regcache_data;
+  unsigned int gdb_id;
 };
 
 struct inferior_list all_threads;
@@ -102,7 +103,7 @@ remove_inferior (struct inferior_list *l
 }
 
 void
-add_thread (unsigned long thread_id, void *target_data)
+add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
 {
   struct thread_info *new_thread
     = (struct thread_info *) malloc (sizeof (*new_thread));
@@ -118,6 +119,45 @@ add_thread (unsigned long thread_id, voi
 
   new_thread->target_data = target_data;
   set_inferior_regcache_data (new_thread, new_register_cache ());
+  new_thread->gdb_id = gdb_id;
+}
+
+unsigned int
+thread_id_to_gdb_id (unsigned long thread_id)
+{
+  struct inferior_list_entry *inf = all_threads.head;
+
+  while (inf != NULL)
+    {
+      struct thread_info *thread = get_thread (inf);
+      if (inf->id == thread_id)
+	return thread->gdb_id;
+      inf = inf->next;
+    }
+
+  return 0;
+}
+
+unsigned int
+thread_to_gdb_id (struct thread_info *thread)
+{
+  return thread->gdb_id;
+}
+
+unsigned long
+gdb_id_to_thread_id (unsigned int gdb_id)
+{
+  struct inferior_list_entry *inf = all_threads.head;
+
+  while (inf != NULL)
+    {
+      struct thread_info *thread = get_thread (inf);
+      if (thread->gdb_id == gdb_id)
+	return inf->id;
+      inf = inf->next;
+    }
+
+  return 0;
 }
 
 static void
Index: linux-low.c
===================================================================
RCS file: /home/gcc/repos/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.38
diff -u -p -r1.38 linux-low.c
--- linux-low.c	17 Jun 2005 04:01:05 -0000	1.38
+++ linux-low.c	13 Jul 2005 13:35:17 -0000
@@ -160,7 +160,7 @@ linux_create_inferior (char *program, ch
     }
 
   new_process = add_process (pid);
-  add_thread (pid, new_process);
+  add_thread (pid, new_process, pid);
 
   return pid;
 }
@@ -185,7 +185,7 @@ linux_attach_lwp (unsigned long pid, uns
     }
 
   new_process = (struct process_info *) add_process (pid);
-  add_thread (tid, new_process);
+  add_thread (tid, new_process, pid);
 
   /* The next time we wait for this LWP we'll see a SIGSTOP as PTRACE_ATTACH
      brings it to a halt.  We should ignore that SIGSTOP and resume the process
Index: remote-utils.c
===================================================================
RCS file: /home/gcc/repos/src/src/gdb/gdbserver/remote-utils.c,v
retrieving revision 1.25
diff -u -p -r1.25 remote-utils.c
--- remote-utils.c	13 Jun 2005 01:59:22 -0000	1.25
+++ remote-utils.c	13 Jul 2005 01:11:47 -0000
@@ -683,6 +683,8 @@ prepare_resume_reply (char *buf, char st
 	{
 	  /* FIXME right place to set this? */
 	  thread_from_wait = ((struct inferior_list_entry *)current_inferior)->id;
+	  unsigned int gdb_id_from_wait = thread_to_gdb_id (current_inferior);
+
 	  if (debug_threads)
 	    fprintf (stderr, "Writing resume reply for %ld\n\n", thread_from_wait);
 	  /* This if (1) ought to be unnecessary.  But remote_wait in GDB
@@ -692,7 +694,7 @@ prepare_resume_reply (char *buf, char st
 	  if (1 || old_thread_from_wait != thread_from_wait)
 	    {
 	      general_thread = thread_from_wait;
-	      sprintf (buf, "thread:%lx;", thread_from_wait);
+	      sprintf (buf, "thread:%x;", gdb_id_from_wait);
 	      buf += strlen (buf);
 	      old_thread_from_wait = thread_from_wait;
 	    }
Index: server.c
===================================================================
RCS file: /home/gcc/repos/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.27
diff -u -p -r1.27 server.c
--- server.c	17 Jun 2005 04:01:05 -0000	1.27
+++ server.c	13 Jul 2005 01:14:17 -0000
@@ -103,7 +103,7 @@ handle_query (char *own_buf)
   if (strcmp ("qfThreadInfo", own_buf) == 0)
     {
       thread_ptr = all_threads.head;
-      sprintf (own_buf, "m%lx", thread_ptr->id);
+      sprintf (own_buf, "m%x", thread_to_gdb_id ((struct thread_info *)thread_ptr));
       thread_ptr = thread_ptr->next;
       return;
     }
@@ -112,7 +112,7 @@ handle_query (char *own_buf)
     {
       if (thread_ptr != NULL)
 	{
-	  sprintf (own_buf, "m%lx", thread_ptr->id);
+	  sprintf (own_buf, "m%x", thread_to_gdb_id ((struct thread_info *)thread_ptr));
 	  thread_ptr = thread_ptr->next;
 	  return;
 	}
@@ -218,13 +218,21 @@ handle_v_cont (char *own_buf, char *stat
 	}
       else if (p[0] == ':')
 	{
-	  resume_info[i].thread = strtoul (p + 1, &q, 16);
+	  unsigned int gdb_id = strtoul (p + 1, &q, 16);
+	  unsigned long thread_id;
+
 	  if (p == q)
 	    goto err;
 	  p = q;
 	  if (p[0] != ';' && p[0] != 0)
 	    goto err;
 
+	  thread_id = gdb_id_to_thread_id (gdb_id);
+	  if (thread_id)
+	    resume_info[i].thread = thread_id;
+	  else
+	    goto err;
+
 	  i++;
 	}
     }
@@ -431,26 +439,35 @@ main (int argc, char *argv[])
 	      prepare_resume_reply (own_buf, status, signal);
 	      break;
 	    case 'H':
-	      switch (own_buf[1])
+	      if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
 		{
-		case 'g':
-		  general_thread = strtoul (&own_buf[2], NULL, 16);
-		  write_ok (own_buf);
-		  set_desired_inferior (1);
-		  break;
-		case 'c':
-		  cont_thread = strtoul (&own_buf[2], NULL, 16);
-		  write_ok (own_buf);
-		  break;
-		case 's':
-		  step_thread = strtoul (&own_buf[2], NULL, 16);
+		  unsigned long gdb_id, thread_id;
+
+		  gdb_id = strtoul (&own_buf[2], NULL, 16);
+		  thread_id = gdb_id_to_thread_id (gdb_id);
+		  if (thread_id == 0)
+		    {
+		      write_enn (own_buf);
+		      break;
+		    }
+
+		  if (own_buf[1] == 'g')
+		    {
+		      general_thread = thread_id;
+		      set_desired_inferior (1);
+		    }
+		  else if (own_buf[1] == 'c')
+		    cont_thread = thread_id;
+		  else if (own_buf[1] == 's')
+		    step_thread = thread_id;
+
 		  write_ok (own_buf);
-		  break;
-		default:
+		}
+	      else
+		{
 		  /* Silently ignore it so that gdb can extend the protocol
 		     without compatibility headaches.  */
 		  own_buf[0] = '\0';
-		  break;
 		}
 	      break;
 	    case 'g':
@@ -592,10 +609,22 @@ main (int argc, char *argv[])
 		  break;
 		}
 	    case 'T':
-	      if (mythread_alive (strtoul (&own_buf[1], NULL, 16)))
-		write_ok (own_buf);
-	      else
-		write_enn (own_buf);
+	      {
+		unsigned long gdb_id, thread_id;
+
+		gdb_id = strtoul (&own_buf[1], NULL, 16);
+		thread_id = gdb_id_to_thread_id (gdb_id);
+		if (thread_id == 0)
+		  {
+		    write_enn (own_buf);
+		    break;
+		  }
+
+		if (mythread_alive (thread_id))
+		  write_ok (own_buf);
+		else
+		  write_enn (own_buf);
+	      }
 	      break;
 	    case 'R':
 	      /* Restarting the inferior is only supported in the
Index: server.h
===================================================================
RCS file: /home/gcc/repos/src/src/gdb/gdbserver/server.h,v
retrieving revision 1.18
diff -u -p -r1.18 server.h
--- server.h	1 Jul 2005 17:18:06 -0000	1.18
+++ server.h	13 Jul 2005 13:36:43 -0000
@@ -97,7 +97,10 @@ extern struct thread_info *current_infer
 void remove_inferior (struct inferior_list *list,
 		      struct inferior_list_entry *entry);
 void remove_thread (struct thread_info *thread);
-void add_thread (unsigned long thread_id, void *target_data);
+void add_thread (unsigned long thread_id, void *target_data, unsigned int);
+unsigned int thread_id_to_gdb_id (unsigned long);
+unsigned int thread_to_gdb_id (struct thread_info *);
+unsigned long gdb_id_to_thread_id (unsigned int);
 void clear_inferiors (void);
 struct inferior_list_entry *find_inferior
      (struct inferior_list *,


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