This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[commit] Use LWP IDs for thread IDs in gdbserver
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Date: Wed, 13 Jul 2005 11:11:33 -0400
- Subject: [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 *,