All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nathan Froyd <froydnj@codesourcery.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] fix gdbstub support for multiple threads in usermode
Date: Tue, 12 May 2009 12:35:43 -0700	[thread overview]
Message-ID: <1242156943-27850-1-git-send-email-froydnj@codesourcery.com> (raw)

When debugging multi-threaded programs, QEMU's gdb stub would report the
correct number of threads (the qfThreadInfo and qsThreadInfo packets).
However, the stub was unable to actually switch between threads (the T
packet), since it would report every thread except the first as being
dead.  Furthermore, the stub relied upon cpu_index as a reliable means
of assigning IDs to the threads.  This was a bad idea; if you have this
sequence of events:

initial thread created
new thread #1
new thread #2
thread #1 exits
new thread #3

thread #3 will have the same cpu_index as thread #1, which would confuse
GDB.

We fix this by adding a stable gdbstub_index field for each CPU; the
index is incremented for every CPU (thread) created.  We ignore
wraparound issues for now.  Once we have this field, the stub needs to
use this field instead of cpu_index for communicating with GDB.

Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
---
 cpu-defs.h |    1 +
 exec.c     |    5 +++++
 gdbstub.c  |   32 +++++++++++++++++++++++---------
 3 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/cpu-defs.h b/cpu-defs.h
index 0a82197..c923708 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -207,6 +207,7 @@ typedef struct CPUWatchpoint {
                                                                         \
     CPUState *next_cpu; /* next CPU sharing TB cache */                 \
     int cpu_index; /* CPU index (informative) */                        \
+    int gdbstub_index; /* index for gdbstub T and H packets */          \
     int numa_node; /* NUMA node this cpu is belonging to  */            \
     int running; /* Nonzero if cpu is currently running(usermode).  */  \
     /* user data */                                                     \
diff --git a/exec.c b/exec.c
index c5c9280..63e3411 100644
--- a/exec.c
+++ b/exec.c
@@ -538,6 +538,8 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
 }
 #endif
 
+static int next_gdbstub_index;
+
 void cpu_exec_init(CPUState *env)
 {
     CPUState **penv;
@@ -554,6 +556,7 @@ void cpu_exec_init(CPUState *env)
         cpu_index++;
     }
     env->cpu_index = cpu_index;
+    env->gdbstub_index = ++next_gdbstub_index;
     env->numa_node = 0;
     TAILQ_INIT(&env->breakpoints);
     TAILQ_INIT(&env->watchpoints);
@@ -1711,6 +1714,8 @@ CPUState *cpu_copy(CPUState *env)
                               wp->flags, NULL);
     }
 #endif
+    /* Need to assign a new thread ID for the gdbstub */
+    new_env->gdbstub_index = ++next_gdbstub_index;
 
     return new_env;
 }
diff --git a/gdbstub.c b/gdbstub.c
index 3c34741..61b065b 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1718,9 +1718,11 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             put_packet(s, "OK");
             break;
         }
-        for (env = first_cpu; env != NULL; env = env->next_cpu)
-            if (env->cpu_index + 1 == thread)
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            if (env->gdbstub_index == thread) {
                 break;
+            }
+        }
         if (env == NULL) {
             put_packet(s, "E22");
             break;
@@ -1741,14 +1743,25 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         break;
     case 'T':
         thread = strtoull(p, (char **)&p, 16);
-#ifndef CONFIG_USER_ONLY
-        if (thread > 0 && thread < smp_cpus + 1)
+#if defined(CONFIG_USER_ONLY)
+        {
+            for (env = first_cpu; env != NULL; env = env->next_cpu) {
+                if (env->gdbstub_index == thread) {
+                    break;
+                }
+            }
+
+            if (env != NULL)
+                put_packet(s, "OK");
+            else
+                put_packet(s, "E22");
+        }
 #else
-        if (thread == 1)
-#endif
+        if (thread > 0 && thread < smp_cpus + 1)
              put_packet(s, "OK");
         else
             put_packet(s, "E22");
+#endif
         break;
     case 'q':
     case 'Q':
@@ -1786,7 +1799,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         } else if (strcmp(p,"sThreadInfo") == 0) {
         report_cpuinfo:
             if (s->query_cpu) {
-                snprintf(buf, sizeof(buf), "m%x", s->query_cpu->cpu_index+1);
+                snprintf(buf, sizeof(buf), "m%x", s->query_cpu->gdbstub_index);
                 put_packet(s, buf);
                 s->query_cpu = s->query_cpu->next_cpu;
             } else
@@ -1794,8 +1807,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             break;
         } else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) {
             thread = strtoull(p+16, (char **)&p, 16);
-            for (env = first_cpu; env != NULL; env = env->next_cpu)
-                if (env->cpu_index + 1 == thread) {
+            for (env = first_cpu; env != NULL; env = env->next_cpu) {
+                if (env->gdbstub_index == thread) {
                     cpu_synchronize_state(env, 0);
                     len = snprintf((char *)mem_buf, sizeof(mem_buf),
                                    "CPU#%d [%s]", env->cpu_index,
@@ -1804,6 +1817,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
                     put_packet(s, buf);
                     break;
                 }
+            }
             break;
         }
 #ifdef CONFIG_USER_ONLY
-- 
1.6.0.5

             reply	other threads:[~2009-05-12 19:35 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-12 19:35 Nathan Froyd [this message]
2009-05-12 20:53 ` [Qemu-devel] Re: [PATCH] fix gdbstub support for multiple threads in usermode Jan Kiszka
2009-05-13  5:08   ` vibisreenivasan
2009-05-13 14:13   ` vibisreenivasan
2009-05-19 14:59     ` Nathan Froyd
2009-05-21  8:19       ` vibi sreenivasan
2009-05-19 15:06   ` Nathan Froyd
2009-05-19 16:53     ` Jan Kiszka
2009-05-19 18:01       ` Nathan Froyd
2009-05-20  6:39         ` Jan Kiszka
2009-05-20 15:27           ` Jamie Lokier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1242156943-27850-1-git-send-email-froydnj@codesourcery.com \
    --to=froydnj@codesourcery.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.