aboutsummaryrefslogtreecommitdiffstats
path: root/tools/debugger
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-12-15 21:02:21 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-12-15 21:02:21 +0100
commit1f5fb04e430d6daf26671bbd6abcfb3ad5189255 (patch)
tree0f82b71128b28fe35ff6c2de2a6f219f6c93de61 /tools/debugger
parent62e852457fb0fe5bc2a1de5d12d4c1d46c53c6da (diff)
downloadxen-1f5fb04e430d6daf26671bbd6abcfb3ad5189255.tar.gz
xen-1f5fb04e430d6daf26671bbd6abcfb3ad5189255.tar.bz2
xen-1f5fb04e430d6daf26671bbd6abcfb3ad5189255.zip
Add MP debug support to gdbserver.
Signed-off-by: Kip Macy <kip.macy@gmail.com>
Diffstat (limited to 'tools/debugger')
-rw-r--r--tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c208
-rw-r--r--tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c10
2 files changed, 184 insertions, 34 deletions
diff --git a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
index dcc56cb3d5..02d39ed621 100644
--- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
+++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
@@ -36,23 +36,41 @@
#include <unistd.h>
#include <errno.h>
#include <xenctrl.h>
+#include <thread_db.h>
+#include <xc_ptrace.h>
+
#define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */
long (*myptrace)(int xc_handle, enum __ptrace_request, uint32_t, long, long);
int (*myxcwait)(int xc_handle, int domain, int *status, int options) ;
static int xc_handle;
+static inline int
+curvcpuid()
+{
+ struct process_info *process;
+ if (current_inferior == NULL)
+ return 0;
+ process = get_thread_process(current_inferior);
+ return (process->thread_known ? process->tid : 0);
+
+}
+
+
#define DOMFLAGS_DYING (1<<0) /* Domain is scheduled to die. */
#define DOMFLAGS_SHUTDOWN (1<<2) /* The guest OS has shut down. */
#define DOMFLAGS_PAUSED (1<<3) /* Currently paused by control software. */
#define DOMFLAGS_BLOCKED (1<<4) /* Currently blocked pending an event. */
#define DOMFLAGS_RUNNING (1<<5) /* Domain is currently running. */
+
+
struct inferior_list all_processes;
-static int current_domain;
+static int current_domid;
static int expect_signal = 0;
static int signal_to_send = 0;
static void linux_resume (struct thread_resume *resume_info);
+static void linux_set_inferior (void);
int debug_threads;
int using_threads;
@@ -96,7 +114,6 @@ static int use_regsets_p = 1;
point at the following instruction. If we continue and hit a
breakpoint instruction, our PC will point at the breakpoint
instruction. */
-#if 0
static CORE_ADDR
get_stop_pc (void)
{
@@ -107,9 +124,9 @@ get_stop_pc (void)
else
return stop_pc - the_low_target.decr_pc_after_break;
}
-#endif
+
static void *
-add_process (int pid)
+add_process (int pid, long tid)
{
struct process_info *process;
@@ -118,9 +135,8 @@ add_process (int pid)
process->head.id = pid;
- /* Default to tid == lwpid == pid. */
- process->tid = pid;
- process->lwpid = pid;
+ process->tid = tid;
+ process->lwpid = tid;
add_inferior_to_list (&all_processes, &process->head);
@@ -143,23 +159,25 @@ linux_create_inferior (char *program, char **allargs)
}
int
-linux_attach (int domain)
+linux_attach (int domid)
{
struct process_info *new_process;
- current_domain = domain;
- if (myptrace (xc_handle, PTRACE_ATTACH, domain, 0, 0) != 0) {
- fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domain,
+ current_domid = domid;
+ /* this is handled for all active vcpus in PTRACE_ATTACH via the thread_create_callback */
+ new_process = (struct process_info *) add_process (domid, curvcpuid());
+ /* Don't ignore the initial SIGSTOP if we just attached to this process. */
+ /* vcpuid == 0 */
+ add_thread (0, new_process);
+ new_process->stop_expected = 0;
+
+ if (myptrace (xc_handle, PTRACE_ATTACH, domid, 0, 0) != 0) {
+ fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domid,
strerror (errno), errno);
fflush (stderr);
- _exit (0177);
+ if (!using_threads)
+ _exit (0177);
}
-
- new_process = (struct process_info *) add_process (domain);
- add_thread (domain, new_process);
- /* Don't ignore the initial SIGSTOP if we just attached to this process. */
- new_process->stop_expected = 0;
-
return 0;
}
@@ -173,20 +191,18 @@ linux_kill_one_process (struct inferior_list_entry *entry)
myptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0);
}
+
static void
linux_kill (void)
{
for_each_inferior (&all_threads, linux_kill_one_process);
}
-
static void
linux_detach_one_process (struct inferior_list_entry *entry)
{
- struct thread_info *thread = (struct thread_info *) entry;
- struct process_info *process = get_thread_process (thread);
- myptrace (xc_handle, PTRACE_DETACH, pid_of (process), 0, 0);
+ myptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0);
}
@@ -212,7 +228,7 @@ static unsigned char
linux_wait (char *status)
{
int w;
- if (myxcwait(xc_handle, current_domain, &w, 0))
+ if (myxcwait(xc_handle, current_domid, &w, 0))
return -1;
if (w & (DOMFLAGS_SHUTDOWN|DOMFLAGS_DYING)) {
@@ -220,6 +236,7 @@ linux_wait (char *status)
return 0;
}
+ linux_set_inferior();
*status = 'T';
if (expect_signal)
@@ -236,8 +253,10 @@ linux_resume (struct thread_resume *resume_info)
TRACE_ENTER;
expect_signal = resume_info->sig;
for_each_inferior(&all_threads, regcache_invalidate_one);
-
- myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, current_domain, 0, 0);
+ if (debug_threads)
+ fprintf(stderr, "step: %d\n", step);
+ myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT,
+ resume_info->thread, 0, 0);
}
@@ -261,7 +280,9 @@ regsets_fetch_inferior_registers ()
}
buf = malloc (regset->size);
- res = myptrace (xc_handle, regset->get_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf);
+ res = myptrace (xc_handle, regset->get_request,
+ curvcpuid(),
+ 0, (PTRACE_XFER_TYPE)buf);
if (res < 0)
{
if (errno == EIO)
@@ -313,7 +334,7 @@ regsets_store_inferior_registers ()
buf = malloc (regset->size);
regset->fill_function (buf);
- res = myptrace (xc_handle, regset->set_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf);
+ res = myptrace (xc_handle, regset->set_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf);
if (res < 0)
{
if (errno == EIO)
@@ -391,7 +412,7 @@ linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
- buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
+ buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0);
if (errno)
return errno;
}
@@ -424,13 +445,13 @@ linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
/* Fill start and end extra bytes of buffer with existing memory data. */
- buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid,
+ buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
(PTRACE_ARG3_TYPE) addr, 0);
if (count > 1)
{
buffer[count - 1]
- = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid,
+ = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
(PTRACE_ARG3_TYPE) (addr + (count - 1)
* sizeof (PTRACE_XFER_TYPE)),
0);
@@ -444,7 +465,8 @@ linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
- myptrace (xc_handle, PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
+ myptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(),
+ (PTRACE_ARG3_TYPE) addr, buffer[i]);
if (errno)
return errno;
}
@@ -455,9 +477,11 @@ linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
static void
linux_look_up_symbols (void)
{
-#if 0
+ if (using_threads)
+ return;
+
using_threads = thread_db_init ();
-#endif
+
}
static void
@@ -535,6 +559,7 @@ linux_init_signals ()
void
initialize_low (void)
{
+ using_threads = 0;
xc_handle = xc_interface_open();
set_target_ops (&linux_xen_target_ops);
set_breakpoint_data (the_low_target.breakpoint,
@@ -548,5 +573,122 @@ initialize_low (void)
myptrace = xc_ptrace;
myxcwait = xc_waitdomain;
}
+ using_threads = thread_db_init ();
+
+}
+
+
+static void
+thread_create_callback(long vcpuid)
+{
+ struct thread_info *inferior;
+ struct process_info *process;
+
+ /* If we are attaching to our first thread, things are a little
+ * different.
+ */
+ if (all_threads.head == all_threads.tail)
+ {
+ inferior = (struct thread_info *) all_threads.head;
+ process = get_thread_process (inferior);
+ if (process->thread_known == 0)
+ {
+ /* Switch to indexing the threads list by TID. */
+ change_inferior_id (&all_threads, vcpuid);
+ goto found;
+ }
+ }
+ if (debug_threads)
+ fprintf (stderr, "looking up thread %ld\n",
+ vcpuid);
+ inferior = (struct thread_info *) find_inferior_id (&all_threads,
+ vcpuid);
+ /* if vcpu alread registered - do nothing */
+ if (inferior != NULL)
+ return;
+
+ if (debug_threads)
+ fprintf (stderr, "Attaching to thread %ld\n",
+ vcpuid);
+
+ process = add_process(current_domid, vcpuid);
+
+ add_thread(vcpuid, process);
+ inferior = (struct thread_info *) find_inferior_id (&all_threads,
+ vcpuid);
+ if (inferior == NULL)
+ {
+ warning ("Could not attach to thread %ld\n",
+ vcpuid);
+ return;
+ }
+
+
+found:
+ if (debug_threads)
+ fprintf (stderr, "notifying of new thread %ld\n",
+ vcpuid);
+ new_thread_notify (vcpuid);
+
+ process->tid = vcpuid;
+ process->lwpid = vcpuid;
+
+ process->thread_known = 1;
+}
+
+static void
+thread_death_callback(long vcpuid)
+{
+ if (debug_threads)
+ fprintf (stderr, "Buuurp...! CPU down event.\n");
+}
+
+int
+thread_db_init(void)
+{
+ debug_threads = 0;
+ xc_register_event_handler(thread_create_callback, TD_CREATE);
+ xc_register_event_handler(thread_death_callback, TD_DEATH);
+ return 1;
+}
+
+/* XXX GAG ME */
+static int breakpoint_found;
+static void
+set_breakpoint_inferior (struct inferior_list_entry *entry)
+{
+ struct thread_info *thread = (struct thread_info *) entry;
+ struct thread_info *saved_inferior = current_inferior;
+ CORE_ADDR eip;
+ unsigned char buf[2] = {0, 0};
+ current_inferior = thread;
+ if (!breakpoint_found) {
+ eip = get_stop_pc();
+ linux_read_memory(eip, buf, 1);
+ if (buf[0] == 0xcc) {
+ breakpoint_found = 1;
+ return;
+ }
+ } else if (breakpoint_found == 2) {
+ if (get_thread_process (current_inferior)->stepping) {
+ printf("stepping\n");
+ breakpoint_found = 1;
+ return;
+ }
+ }
+ current_inferior = saved_inferior;
+
+
+}
+static void
+linux_set_inferior (void)
+{
+ breakpoint_found = 0;
+ for_each_inferior (&all_threads, set_breakpoint_inferior);
+ if (!breakpoint_found) {
+ breakpoint_found = 2;
+ for_each_inferior (&all_threads, set_breakpoint_inferior);
+ }
}
+
diff --git a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c
index 54f508a186..c987c0eb9d 100644
--- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c
+++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c
@@ -20,7 +20,7 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
-
+#include "linux-low.h"
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
@@ -102,7 +102,15 @@ handle_query (char *own_buf)
strcpy (own_buf, "OK");
return;
}
+ if (strcmp ("qC", own_buf) == 0)
+ {
+ struct process_info *process;
+ if (current_inferior == NULL)
+ return;
+ process = get_thread_process(current_inferior);
+ sprintf(own_buf, "QC%x", process->thread_known ? process->tid : 0);
+ }
if (strcmp ("qfThreadInfo", own_buf) == 0)
{
thread_ptr = all_threads.head;