WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] PDB: process targets

# HG changeset patch
# User ach61@xxxxxxxxxxxxxxxxxxxxxx
# Node ID 577d1c7b47a9359d22110add59196ff2bf87d77c
# Parent  501a70f3ae968e46e27b9003febf05253f4cf949
PDB: process targets

diff -r 501a70f3ae96 -r 577d1c7b47a9 
linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Thu Jul 28 12:34:45 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Thu Jul 28 21:28:23 2005
@@ -90,7 +90,9 @@
 
 static int kstack_depth_to_print = 24;
 struct notifier_block *i386die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+DEFINE_SPINLOCK(die_notifier_lock);
+EXPORT_SYMBOL(die_notifier_lock);
+EXPORT_SYMBOL(i386die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
 {
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/libxendebug/xendebug.c
--- a/tools/debugger/libxendebug/xendebug.c     Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/libxendebug/xendebug.c     Thu Jul 28 21:28:23 2005
@@ -42,7 +42,6 @@
     struct list_head list;
     memory_t address;
     u32 domain;
-    u16 vcpu;
     u8 old_value;                             /* old value for software bkpt */
 } bwcpoint_t, *bwcpoint_p;
 
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/pdb/PDB.ml
--- a/tools/debugger/pdb/PDB.ml Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/PDB.ml Thu Jul 28 21:28:23 2005
@@ -138,9 +138,13 @@
 
 let detach_debugger ctx =
   match ctx with
-  | Domain d  -> Domain.detach_debugger (Domain.get_domain d) 
-                                       (Domain.get_vcpu d)
-  | Process p  -> Process.detach_debugger p
+  | Domain d  -> 
+      Domain.detach_debugger (Domain.get_domain d) 
+                            (Domain.get_vcpu d);
+      "OK"
+  | Process p  ->
+      Process.detach_debugger p;
+      raise No_reply
   | _ -> raise (Unimplemented "detach debugger")
 
 
@@ -240,13 +244,21 @@
 let read_memory ctx addr len =
   match ctx with
   | Domain d  -> Domain.read_memory d addr len
-  | Process p -> Process.read_memory p addr len
+  | Process p ->
+      begin
+       Process.read_memory p addr len;
+       raise No_reply
+      end
   | _ -> raise (Unimplemented "read memory")
 
 let write_memory ctx addr values =
   match ctx with
   | Domain d  -> Domain.write_memory d addr values
-  | Process p -> Process.write_memory p addr values
+  | Process p ->
+      begin
+       Process.write_memory p addr values;
+       raise No_reply
+      end
   | _ -> raise (Unimplemented "write memory")
 
 
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/pdb/Process.ml
--- a/tools/debugger/pdb/Process.ml     Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/Process.ml     Thu Jul 28 21:28:23 2005
@@ -57,7 +57,7 @@
 external read_registers : context_t -> unit = "proc_read_registers"
 external write_register : context_t -> register -> int32 -> unit =
   "proc_write_register"
-external read_memory : context_t -> int32 -> int -> int list = 
+external read_memory : context_t -> int32 -> int -> unit = 
   "proc_read_memory"
 external write_memory : context_t -> int32 -> int list -> unit = 
   "proc_write_memory"
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/pdb/Process.mli
--- a/tools/debugger/pdb/Process.mli    Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/Process.mli    Thu Jul 28 21:28:23 2005
@@ -29,7 +29,7 @@
 
 val read_registers : context_t -> unit
 val write_register : context_t -> register -> int32 -> unit
-val read_memory : context_t -> int32 -> int -> int list
+val read_memory : context_t -> int32 -> int -> unit
 val write_memory : context_t -> int32 -> int list -> unit
        
 val continue : context_t -> unit
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/pdb/debugger.ml
--- a/tools/debugger/pdb/debugger.ml    Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/debugger.ml    Thu Jul 28 21:28:23 2005
@@ -25,8 +25,7 @@
    hash.  It will be cleaned up with the socket is closed.
  *)
 let gdb_detach ctx =
-  PDB.detach_debugger ctx;
-  raise No_reply
+  PDB.detach_debugger ctx
 
 (**
    Kill Command
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/pdb/linux-2.6-module/debug.c
--- a/tools/debugger/pdb/linux-2.6-module/debug.c       Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/linux-2.6-module/debug.c       Thu Jul 28 21:28:23 2005
@@ -3,49 +3,54 @@
  * pdb debug functionality for processes.
  */
 
-
 #include <linux/module.h>
+#include <linux/mm.h>
 #include <linux/sched.h>
+#include <asm-i386/kdebug.h>
+#include <asm-xen/asm-i386/processor.h>
 #include <asm-xen/asm-i386/ptrace.h>
 #include <asm-xen/xen-public/xen.h>
-
 #include "pdb_module.h"
-
-EXPORT_SYMBOL(pdb_attach);
-EXPORT_SYMBOL(pdb_detach);
-
-int
-pdb_attach (int pid)
-{
-    struct task_struct *target;
+#include "pdb_debug.h"
+
+#define BWC_DEBUG 1
+#define BWC_INT3  3
+typedef struct bwcpoint                           /* break/watch/catch point */
+{
+    struct list_head list;
+    memory_t address;
+    u32 domain;
+    u32 process;
+    u8  old_value;                            /* old value for software bkpt */
+    u8  type;                                                     /* BWC_??? */
+} bwcpoint_t, *bwcpoint_p;
+
+static bwcpoint_t bwcpoint_list;
+
+void
+pdb_initialize_bwcpoint (void)
+{
+    memset((void *) &bwcpoint_list, 0, sizeof(bwcpoint_t));
+    INIT_LIST_HEAD(&bwcpoint_list.list);
+
+    return;
+}
+
+
+int
+pdb_suspend (struct task_struct *target)
+{
     u32 rc = 0;
 
-    printk ("pdb attach: 0x%x\n", pid);
-
-    read_lock(&tasklist_lock);
-    target = find_task_by_pid(pid);
-    if (target)
-        get_task_struct(target);
-    read_unlock(&tasklist_lock);
-
     force_sig(SIGSTOP, target);                    /* force_sig_specific ??? */
 
     return rc;
 }
 
 int
-pdb_detach (int pid)
-{
-    int rc = 0;
-    struct task_struct *target;
-
-    printk ("pdb detach: 0x%x\n", pid);
-
-    read_lock(&tasklist_lock);
-    target = find_task_by_pid(pid);
-    if (target)
-        get_task_struct(target);
-    read_unlock(&tasklist_lock);
+pdb_resume (struct task_struct *target)
+{
+    int rc = 0;
 
     wake_up_process(target);
 
@@ -55,7 +60,6 @@
 /*
  * from linux-2.6.11/arch/i386/kernel/ptrace.c::getreg()
  */
-
 static unsigned long
 _pdb_get_register (struct task_struct *target, int reg)
 {
@@ -65,20 +69,20 @@
 
     switch (reg)
     {
-    case FS:
+    case LINUX_FS:
         result = target->thread.fs;
         break;
-    case GS:
+    case LINUX_GS:
         result = target->thread.gs;
         break;
-    case DS:
-    case ES:
-    case SS:
-    case CS:
+    case LINUX_DS:
+    case LINUX_ES:
+    case LINUX_SS:
+    case LINUX_CS:
         result = 0xffff;
         /* fall through */
     default:
-        if (reg > GS)
+        if (reg > LINUX_GS)
             reg -= 2;
 
         offset = reg * sizeof(long);
@@ -91,17 +95,51 @@
     return result;
 }
 
-int
-pdb_read_register (int pid, pdb_op_rd_regs_p op)
-{
-    int rc = 0;
-    struct task_struct *target;
-
-    read_lock(&tasklist_lock);
-    target = find_task_by_pid(pid);
-    if (target)
-        get_task_struct(target);
-    read_unlock(&tasklist_lock);
+/*
+ * from linux-2.6.11/arch/i386/kernel/ptrace.c::putreg()
+ */
+static void
+_pdb_set_register (struct task_struct *target, int reg, unsigned long val)
+{
+    unsigned long offset;
+    unsigned char *stack;
+    unsigned long value = val;
+
+    switch (reg)
+    {
+    case LINUX_FS:
+        target->thread.fs = value;
+        return;
+    case LINUX_GS:
+        target->thread.gs = value;
+        return;
+    case LINUX_DS:
+    case LINUX_ES:
+        value &= 0xffff;
+        break;
+    case LINUX_SS:
+    case LINUX_CS:
+        value &= 0xffff;
+        break;
+    case LINUX_EFL:
+        break;
+    }
+
+    if (reg > LINUX_GS)
+        reg -= 2;
+    offset = reg * sizeof(long);
+    offset -= sizeof(struct pt_regs);
+    stack = (unsigned char *)target->thread.esp0;
+    stack += offset;
+    *(unsigned long *) stack = value;
+
+    return;
+}
+
+int
+pdb_read_registers (struct task_struct *target, pdb_op_rd_regs_p op)
+{
+    int rc = 0;
 
     op->reg[ 0] = _pdb_get_register(target, LINUX_EAX);
     op->reg[ 1] = _pdb_get_register(target, LINUX_ECX);
@@ -124,57 +162,248 @@
     return rc;
 }
 
-/*
- * from linux-2.6.11/arch/i386/kernel/ptrace.c::putreg()
- */
-int
-pdb_write_register (int pid, pdb_op_wr_reg_p op)
-{
-    int rc = 0;
-    struct task_struct *target;
-    unsigned long offset;
-    unsigned char *stack;
-    unsigned long value = op->value;
-
-    /*
-    printk ("pdb write register: 0x%x %2d 0x%lx\n", pid, op->reg, value);
-    */
-
-    read_lock(&tasklist_lock);
-    target = find_task_by_pid(pid);
-    if (target)
-        get_task_struct(target);
-    read_unlock(&tasklist_lock);
-
-    switch (op->reg)
-    {
-    case FS:
-        target->thread.fs = value;
-        return rc;
-    case GS:
-        target->thread.gs = value;
-        return rc;
-    case DS:
-    case ES:
-        value &= 0xffff;
-        break;
-    case SS:
-    case CS:
-        value &= 0xffff;
-        break;
-    case EFL:
-        break;
-    }
-
-    if (op->reg > GS)
-        op->reg -= 2;
-    offset = op->reg * sizeof(long);
-    offset -= sizeof(struct pt_regs);
-    stack = (unsigned char *)target->thread.esp0;
-    stack += offset;
-    *(unsigned long *) stack = op->value;
-
-    return rc;
+int
+pdb_write_register (struct task_struct *target, pdb_op_wr_reg_p op)
+{
+    int rc = 0;
+
+    _pdb_set_register(target, op->reg, op->value);
+
+    return rc;
+}
+
+int
+pdb_access_memory (struct task_struct *target, unsigned long address, 
+                   void *buffer, int length, int write)
+{
+    int rc = 0;
+
+    access_process_vm(target, address, buffer, length, write);
+
+    return rc;
+}
+
+int
+pdb_continue (struct task_struct *target)
+{
+    int rc = 0;
+    unsigned long eflags;
+
+    eflags = _pdb_get_register(target, LINUX_EFL);
+    eflags &= ~X86_EFLAGS_TF;
+    _pdb_set_register(target, LINUX_EFL, eflags);
+
+    wake_up_process(target);
+
+    return rc;
+}
+
+int
+pdb_step (struct task_struct *target)
+{
+    int rc = 0;
+    unsigned long eflags;
+    bwcpoint_p bkpt;
+    
+    eflags = _pdb_get_register(target, LINUX_EFL);
+    eflags |= X86_EFLAGS_TF;
+    _pdb_set_register(target, LINUX_EFL, eflags);
+
+    bkpt = kmalloc(sizeof(bwcpoint_t), GFP_KERNEL);
+    if ( bkpt == NULL )
+    {
+        printk("error: unable to allocation memory\n");
+        return -1;
+    }
+
+    bkpt->process = target->pid;
+    bkpt->address = 0;
+    bkpt->type    = BWC_DEBUG;
+    
+    list_add(&bkpt->list, &bwcpoint_list.list);
+
+    wake_up_process(target);
+
+    return rc;
+}
+
+int
+pdb_insert_memory_breakpoint (struct task_struct *target, 
+                              memory_t address, u32 length)
+{
+    int rc = 0;
+    bwcpoint_p bkpt;
+    u8 breakpoint_opcode = 0xcc;
+
+    printk("insert breakpoint %d:%lx len: %d\n", target->pid, address, length);
+
+    bkpt = kmalloc(sizeof(bwcpoint_t), GFP_KERNEL);
+    if ( bkpt == NULL )
+    {
+        printk("error: unable to allocation memory\n");
+        return -1;
+    }
+
+    if ( length != 1 )
+    {
+        printk("error: breakpoint length should be 1\n");
+        kfree(bkpt);
+        return -1;
+    }
+
+    bkpt->process = target->pid;
+    bkpt->address = address;
+    bkpt->type    = BWC_INT3;
+
+    pdb_access_memory(target, address, &bkpt->old_value, 1, 0);
+    pdb_access_memory(target, address, &breakpoint_opcode, 1, 1);
+    
+    list_add(&bkpt->list, &bwcpoint_list.list);
+
+    printk("breakpoint_set %d:%lx  OLD: 0x%x\n",
+           target->pid, address, bkpt->old_value);
+
+    return rc;
+}
+
+int
+pdb_remove_memory_breakpoint (struct task_struct *target,
+                              memory_t address, u32 length)
+{
+    int rc = 0;
+    bwcpoint_p bkpt = NULL;
+
+    printk ("remove breakpoint %d:%lx\n", target->pid, address);
+
+    struct list_head *entry;
+    list_for_each(entry, &bwcpoint_list.list)
+    {
+        bkpt = list_entry(entry, bwcpoint_t, list);
+        if ( target->pid == bkpt->process && 
+             address == bkpt->address     &&
+             bkpt->type == BWC_INT3 )
+            break;
+    }
+    
+    if (bkpt == &bwcpoint_list || bkpt == NULL)
+    {
+        printk ("error: no breakpoint found\n");
+        return -1;
+    }
+
+    list_del(&bkpt->list);
+
+    pdb_access_memory(target, address, &bkpt->old_value, 1, 1);
+
+    kfree(bkpt);
+
+    return rc;
+}
+
+
+/***************************************************************/
+
+int
+pdb_exceptions_notify (struct notifier_block *self, unsigned long val,
+                       void *data)
+{
+    struct die_args *args = (struct die_args *)data;
+
+       switch (val) 
+    {
+       case DIE_DEBUG:
+               if (pdb_debug_fn(args->regs, args->trapnr, args->err))
+                       return NOTIFY_STOP;
+               break;
+    case DIE_TRAP:
+               if (args->trapnr == 3 && pdb_int3_fn(args->regs, args->err))
+                       return NOTIFY_STOP;
+        break;
+       case DIE_INT3:          /* without kprobes, we should never see 
DIE_INT3 */
+       case DIE_GPF:
+       case DIE_PAGE_FAULT:
+       default:
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+
+int
+pdb_debug_fn (struct pt_regs *regs, long error_code, 
+                   unsigned int condition)
+{
+    pdb_response_t resp;
+    bwcpoint_p bkpt = NULL;
+
+    struct list_head *entry;
+    list_for_each(entry, &bwcpoint_list.list)
+    {
+        bkpt = list_entry(entry, bwcpoint_t, list);
+        if ( current->pid == bkpt->process && 
+             bkpt->type == BWC_DEBUG )
+            break;
+    }
+    
+    if (bkpt == &bwcpoint_list || bkpt == NULL)
+    {
+        printk("not my debug  0x%x 0x%lx\n", current->pid, regs->eip);
+        return 0;
+    }
+
+    list_del(&bkpt->list);
+
+    pdb_suspend(current);
+
+    printk("(pdb) debug  pid: %d, eip: 0x%08lx\n", current->pid, regs->eip);
+
+    regs->eflags &= ~X86_EFLAGS_TF;
+       set_tsk_thread_flag(current, TIF_SINGLESTEP);
+
+    resp.operation = PDB_OPCODE_STEP;
+    resp.process   = current->pid;
+    resp.status    = PDB_RESPONSE_OKAY;
+
+    pdb_send_response(&resp);
+
+    return 1;
+}
+
+
+int
+pdb_int3_fn (struct pt_regs *regs, long error_code)
+{
+    pdb_response_t resp;
+    bwcpoint_p bkpt = NULL;
+
+    struct list_head *entry;
+    list_for_each(entry, &bwcpoint_list.list)
+    {
+        bkpt = list_entry(entry, bwcpoint_t, list);
+        if ( current->pid == bkpt->process && 
+             regs->eip == bkpt->address    &&
+             bkpt->type == BWC_INT3 )
+            break;
+    }
+    
+    if (bkpt == &bwcpoint_list || bkpt == NULL)
+    {
+        printk("not my int3 bkpt  0x%x 0x%lx\n", current->pid, regs->eip);
+        return 0;
+    }
+
+    printk("(pdb) int3  pid: %d, eip: 0x%08lx\n", current->pid, regs->eip);
+
+    pdb_suspend(current);
+
+    resp.operation = PDB_OPCODE_CONTINUE;
+    resp.process   = current->pid;
+    resp.status    = PDB_RESPONSE_OKAY;
+
+    pdb_send_response(&resp);
+
+    return 1;
 }
 
 /*
diff -r 501a70f3ae96 -r 577d1c7b47a9 
tools/debugger/pdb/linux-2.6-module/module.c
--- a/tools/debugger/pdb/linux-2.6-module/module.c      Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/linux-2.6-module/module.c      Thu Jul 28 21:28:23 2005
@@ -11,6 +11,8 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 
+#include <asm-i386/kdebug.h>
+
 #include <asm-xen/evtchn.h>
 #include <asm-xen/ctrl_if.h>
 #include <asm-xen/hypervisor.h>
@@ -20,17 +22,23 @@
 #include <asm-xen/xen-public/io/ring.h>
 
 #include "pdb_module.h"
+#include "pdb_debug.h"
 
 #define PDB_RING_SIZE __RING_SIZE((pdb_sring_t *)0, PAGE_SIZE)
 
 static pdb_back_ring_t pdb_ring;
 static unsigned int    pdb_evtchn;
 static unsigned int    pdb_irq;
+static unsigned int    pdb_domain;
+
+/* work queue */
+static void pdb_work_handler(void *unused);
+static DECLARE_WORK(pdb_deferred_work, pdb_work_handler, NULL);
 
 /*
  * send response to a pdb request
  */
-static void
+void
 pdb_send_response (pdb_response_t *response)
 {
     pdb_response_t *resp;
@@ -38,6 +46,7 @@
     resp = RING_GET_RESPONSE(&pdb_ring, pdb_ring.rsp_prod_pvt);
 
     memcpy(resp, response, sizeof(pdb_response_t));
+    resp->domain = pdb_domain;
     
     wmb();                 /* Ensure other side can see the response fields. */
     pdb_ring.rsp_prod_pvt++;
@@ -53,43 +62,98 @@
 pdb_process_request (pdb_request_t *request)
 {
     pdb_response_t resp;
+    struct task_struct *target;
+
+    read_lock(&tasklist_lock);
+    target = find_task_by_pid(request->process);
+    if (target)
+        get_task_struct(target);
+    read_unlock(&tasklist_lock);
 
     resp.operation = request->operation;
-    resp.domain    = request->domain;
     resp.process   = request->process;
 
+    if (!target)
+    {
+        printk ("(linux) target not found 0x%x\n", request->process);
+        resp.status = PDB_RESPONSE_ERROR;
+        goto response;
+    }
+
     switch (request->operation)
     {
+    case PDB_OPCODE_PAUSE :
+        pdb_suspend(target);
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
     case PDB_OPCODE_ATTACH :
-        pdb_attach(request->process);
+        pdb_suspend(target);
+        pdb_domain = request->u.attach.domain;
+        printk("(linux) attach  dom:0x%x pid:0x%x\n",
+               pdb_domain, request->process);
         resp.status = PDB_RESPONSE_OKAY;
         break;
     case PDB_OPCODE_DETACH :
-        pdb_detach(request->process);
+        pdb_resume(target);
+        printk("(linux) detach 0x%x\n", request->process);
         resp.status = PDB_RESPONSE_OKAY;
         break;
     case PDB_OPCODE_RD_REGS :
-        pdb_read_register(request->process, &resp.u.rd_regs);
+        pdb_read_registers(target, &resp.u.rd_regs);
         resp.status = PDB_RESPONSE_OKAY;
         break;
     case PDB_OPCODE_WR_REG :
-        pdb_write_register(request->process, &request->u.wr_reg);
+        pdb_write_register(target, &request->u.wr_reg);
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
+    case PDB_OPCODE_RD_MEM :
+        pdb_access_memory(target, request->u.rd_mem.address,
+                          &resp.u.rd_mem.data, request->u.rd_mem.length, 0);
+        resp.u.rd_mem.address = request->u.rd_mem.address;
+        resp.u.rd_mem.length  = request->u.rd_mem.length;
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
+    case PDB_OPCODE_WR_MEM :
+        pdb_access_memory(target, request->u.wr_mem.address,
+                         &request->u.wr_mem.data, request->u.wr_mem.length, 1);
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
+    case PDB_OPCODE_CONTINUE :
+        pdb_continue(target);
+        goto no_response;
+        break;
+    case PDB_OPCODE_STEP :
+        pdb_step(target);
+        resp.status = PDB_RESPONSE_OKAY;
+        goto no_response;
+        break;
+    case PDB_OPCODE_SET_BKPT :
+        pdb_insert_memory_breakpoint(target, request->u.bkpt.address,
+                                     request->u.bkpt.length);
+        resp.status = PDB_RESPONSE_OKAY;
+        break;
+    case PDB_OPCODE_CLR_BKPT :
+        pdb_remove_memory_breakpoint(target, request->u.bkpt.address,
+                                     request->u.bkpt.length);
         resp.status = PDB_RESPONSE_OKAY;
         break;
     default:
         printk("(pdb) unknown request operation %d\n", request->operation);
         resp.status = PDB_RESPONSE_ERROR;
     }
-        
+
+ response:        
     pdb_send_response (&resp);
+
+ no_response:
     return;
 }
 
 /*
- * receive a pdb request
- */
-static irqreturn_t
-pdb_interrupt (int irq, void *dev_id, struct pt_regs *ptregs)
+ * work queue
+ */
+static void
+pdb_work_handler (void *unused)
 {
     pdb_request_t *req;
     RING_IDX i, rp;
@@ -106,10 +170,18 @@
 
     }
     pdb_ring.req_cons = i;
+}
+
+/*
+ * receive a pdb request
+ */
+static irqreturn_t
+pdb_interrupt (int irq, void *dev_id, struct pt_regs *ptregs)
+{
+    schedule_work(&pdb_deferred_work);
 
     return IRQ_HANDLED;
 }
-
 
 static void
 pdb_send_connection_status(int status, memory_t ring)
@@ -136,8 +208,6 @@
 static void
 pdb_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
 {
-printk ("pdb ctrlif rx\n");
-
     switch (msg->subtype)
     {
     case CMSG_DEBUG_CONNECTION_STATUS:
@@ -161,17 +231,34 @@
     return;
 }
 
+
+/********************************************************************/
+
+static struct notifier_block pdb_exceptions_nb =
+{
+    .notifier_call = pdb_exceptions_notify,
+    .priority = 0x1                                          /* low priority */
+};
+
+
 static int __init 
-pdb_initialize(void)
-{
+pdb_initialize (void)
+{
+    int err;
     pdb_sring_t *sring;
 
     printk("----\npdb initialize   %s %s\n", __DATE__, __TIME__);
+
+    pdb_initialize_bwcpoint();
 
     /*
     if ( xen_start_info.flags & SIF_INITDOMAIN )
         return 1;
     */
+
+    pdb_evtchn = 0;
+    pdb_irq    = 0;
+    pdb_domain = 0;
 
     (void)ctrl_if_register_receiver(CMSG_DEBUG, pdb_ctrlif_rx,
                                     CALLBACK_IN_BLOCKING_CONTEXT);
@@ -185,12 +272,21 @@
     pdb_send_connection_status(PDB_CONNECTION_STATUS_UP, 
                                virt_to_machine(pdb_ring.sring) >> PAGE_SHIFT);
 
-    return 0;
-}
+    /* handler for int1 & int3 */
+    err = register_die_notifier(&pdb_exceptions_nb);
+
+    return err;
+}
+
+extern struct notifier_block *i386die_chain;
+extern spinlock_t die_notifier_lock;
 
 static void __exit
 pdb_terminate(void)
 {
+    int err = 0;
+    unsigned long flags;
+
     printk("pdb cleanup\n");
 
     (void)ctrl_if_unregister_receiver(CMSG_DEBUG, pdb_ctrlif_rx);
@@ -208,6 +304,12 @@
     }
 
     pdb_send_connection_status(PDB_CONNECTION_STATUS_DOWN, 0);
+
+       spin_lock_irqsave(&die_notifier_lock, flags);
+    err = notifier_chain_unregister(&i386die_chain, &pdb_exceptions_nb);
+       spin_unlock_irqrestore(&die_notifier_lock, flags);
+
+       return;
 }
 
 
diff -r 501a70f3ae96 -r 577d1c7b47a9 
tools/debugger/pdb/linux-2.6-module/pdb_module.h
--- a/tools/debugger/pdb/linux-2.6-module/pdb_module.h  Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/linux-2.6-module/pdb_module.h  Thu Jul 28 21:28:23 2005
@@ -1,35 +1,80 @@
 
-#ifndef __XEN_PDB_H_
-#define __XEN_PDB_H_
+#ifndef __PDB_MODULE_H_
+#define __PDB_MODULE_H_
 
 #include "../pdb_caml_xen.h"
 
-#define PDB_OPCODE_ATTACH 1
-#define PDB_OPCODE_DETACH 2
+#define PDB_OPCODE_PAUSE  1
 
-#define PDB_OPCODE_RD_REGS 3
+#define PDB_OPCODE_ATTACH 2
+typedef struct pdb_op_attach
+{
+    u32  domain;
+} pdb_op_attach_t, *pdb_op_attach_p;
+
+#define PDB_OPCODE_DETACH 3
+
+#define PDB_OPCODE_RD_REGS 4
 typedef struct pdb_op_rd_regs
 {
     u32 reg[GDB_REGISTER_FRAME_SIZE];
 } pdb_op_rd_regs_t, *pdb_op_rd_regs_p;
 
-#define PDB_OPCODE_WR_REG 4
+#define PDB_OPCODE_WR_REG 5
 typedef struct pdb_op_wr_reg
 {
     u32 reg;
     u32 value;
 } pdb_op_wr_reg_t, *pdb_op_wr_reg_p;
 
+#define PDB_OPCODE_RD_MEM 6
+typedef struct pdb_op_rd_mem_req
+{
+    u32 address;
+    u32 length;
+} pdb_op_rd_mem_req_t, *pdb_op_rd_mem_req_p;
+
+typedef struct pdb_op_rd_mem_resp
+{
+    u32 address;
+    u32 length;
+    u8  data[1024];
+} pdb_op_rd_mem_resp_t, *pdb_op_rd_mem_resp_p;
+
+#define PDB_OPCODE_WR_MEM 7
+typedef struct pdb_op_wr_mem
+{
+    u32 address;
+    u32 length;
+    u8  data[1024];                                             /* arbitrary */
+} pdb_op_wr_mem_t, *pdb_op_wr_mem_p;
+
+#define PDB_OPCODE_CONTINUE 8
+#define PDB_OPCODE_STEP     9
+
+#define PDB_OPCODE_SET_BKPT 10
+#define PDB_OPCODE_CLR_BKPT 11
+typedef struct pdb_op_bkpt
+{
+    u32 address;
+    u32 length;
+} pdb_op_bkpt_t, *pdb_op_bkpt_p;
+
+
 typedef struct 
 {
     u8   operation;       /* PDB_OPCODE_???      */
-    u32  domain;
     u32  process;
     union
     {
-        pdb_op_wr_reg_t  wr_reg;
+        pdb_op_attach_t     attach;
+        pdb_op_wr_reg_t     wr_reg;
+        pdb_op_rd_mem_req_t rd_mem;
+        pdb_op_wr_mem_t     wr_mem;
+        pdb_op_bkpt_t       bkpt;
     } u;
 } pdb_request_t, *pdb_request_p;
+
  
 
 #define PDB_RESPONSE_OKAY   0
@@ -42,19 +87,13 @@
     s16  status;          /* PDB_RESPONSE_???    */
     union
     {
-        pdb_op_rd_regs_t rd_regs;
+        pdb_op_rd_regs_t     rd_regs;
+        pdb_op_rd_mem_resp_t rd_mem;
     } u;
 } pdb_response_t, *pdb_response_p;
 
 
 DEFINE_RING_TYPES(pdb, pdb_request_t, pdb_response_t);
-
-
-int pdb_attach (int pid);
-int pdb_detach (int pid);
-int pdb_read_register (int pid, pdb_op_rd_regs_p op);
-int pdb_write_register (int pid, pdb_op_wr_reg_p op);
-
 
 #endif
 
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/pdb/pdb_caml_process.c
--- a/tools/debugger/pdb/pdb_caml_process.c     Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/pdb_caml_process.c     Thu Jul 28 21:28:23 2005
@@ -96,17 +96,19 @@
     memset(msg, 0, sizeof(msg));
 
     rp = my_ring->sring->rsp_prod;
-    rmb(); /* Ensure we see queued responses up to 'rp'. */
-
+    rmb();                     /* Ensure we see queued responses up to 'rp'. */
+
+    /* default response is OK unless the command has something 
+       more interesting to say */
     sprintf(msg, "OK");
 
-    /* for ( loop = my_ring->rsp_cons; loop != rp; loop++ ) */
     if (my_ring->rsp_cons != rp)
     {
         resp = RING_GET_RESPONSE(my_ring, my_ring->rsp_cons);
 
         switch (resp->operation)
         {
+        case PDB_OPCODE_PAUSE :
         case PDB_OPCODE_ATTACH :
         case PDB_OPCODE_DETACH :
             break;
@@ -123,21 +125,57 @@
                 
             break;
         }
-
         case PDB_OPCODE_WR_REG :
         {
-            printf("(linux) wr regs\n");
             /* should check the return status */
             break;
         }
+
+        case PDB_OPCODE_RD_MEM :
+        {
+            int loop;
+            pdb_op_rd_mem_resp_p mem = &resp->u.rd_mem;
+
+            for (loop = 0; loop < mem->length; loop ++)
+            {
+                sprintf(&msg[loop * 2], "%02x", mem->data[loop]);
+            }
+            break;
+        }
+        case PDB_OPCODE_WR_MEM :
+        {
+            /* should check the return status */
+            break;
+        }
+
+        /* this is equivalent to process_xen_virq */
+        case PDB_OPCODE_CONTINUE :
+        {
+            sprintf(msg, "S05");
+            break;
+        }
+        case PDB_OPCODE_STEP :
+        {
+            sprintf(msg, "S05");
+            break;
+        }
+
+        case PDB_OPCODE_SET_BKPT :
+        {
+            break;
+        }
+        case PDB_OPCODE_CLR_BKPT :
+        {
+            break;
+        }
+
         default :
-            printf("(process) UNKNOWN MESSAGE TYPE IN RESPONSE\n");
+            printf("(linux) UNKNOWN MESSAGE TYPE IN RESPONSE\n");
             break;
         }
 
         my_ring->rsp_cons++;
     }
-    /* my_ring->rsp_cons = loop; */
 
     msglen = strlen(msg);
     result = caml_alloc(3,0);
@@ -164,7 +202,7 @@
     decode_context(&ctx, context);
 
     req.operation = PDB_OPCODE_ATTACH;
-    req.domain  = ctx.domain;
+    req.u.attach.domain  = ctx.domain;
     req.process = ctx.process;
 
     send_request (ctx.ring, ctx.evtchn, &req);
@@ -190,7 +228,6 @@
     fflush(stdout);
 
     req.operation = PDB_OPCODE_DETACH;
-    req.domain  = ctx.domain;
     req.process = ctx.process;
 
     send_request (ctx.ring, ctx.evtchn, &req);
@@ -207,12 +244,18 @@
 {
     CAMLparam1(context);
     context_t ctx;
+    pdb_request_t req;
 
     decode_context(&ctx, context);
 
     printf("(pdb) pause target %d %d\n", ctx.domain, ctx.process);
     fflush(stdout);
 
+    req.operation = PDB_OPCODE_PAUSE;
+    req.process = ctx.process;
+
+    send_request (ctx.ring, ctx.evtchn, &req);
+
     CAMLreturn(Val_unit);
 }
 
@@ -231,7 +274,6 @@
     decode_context(&ctx, context);
 
     req.operation = PDB_OPCODE_RD_REGS;
-    req.domain  = ctx.domain;
     req.process = ctx.process;
 
     send_request (ctx.ring, ctx.evtchn, &req);
@@ -257,7 +299,6 @@
     decode_context(&ctx, context);
 
     req.operation = PDB_OPCODE_WR_REG;
-    req.domain = ctx.domain;
     req.process = ctx.process;
     req.u.wr_reg.value = my_newval;
 
@@ -291,64 +332,28 @@
 
 
 /*
- * proc_read_memory : context_t -> int32 -> int -> int
+ * proc_read_memory : context_t -> int32 -> int -> unit
  */
 value
 proc_read_memory (value context, value address, value length)
 {
     CAMLparam3(context, address, length);
-    CAMLlocal2(result, temp);
-
-    context_t ctx;
-    int loop;
-    char *buffer;
-    /*    memory_t my_address = Int32_val(address); */
-    u32 my_length = Int_val(length);
-
-    printf ("(pdb) read memory\n");
-
-    decode_context(&ctx, context);
-
-    buffer = malloc(my_length);
-    if ( buffer == NULL )
-    {
-        printf("(pdb) read memory: malloc failed.\n");  fflush(stdout);
-        failwith("read memory error");
-    }
-
-    /*
-    if ( xendebug_read_memory(xc_handle, ctx.domain, ctx.vcpu, 
-                              my_address, my_length, buffer) )
-    {
-        printf("(pdb) read memory error!\n");  fflush(stdout);
-        failwith("read memory error");
-    }
-    */
-
-    memset(buffer, 0xff, my_length);
-
-    result = caml_alloc(2,0);
-    if ( my_length > 0 )                                              /* car */
-    {
-        Store_field(result, 0, Val_int(buffer[my_length - 1] & 0xff));
-    }
-    else
-
-    {
-        Store_field(result, 0, Val_int(0));                    
-    }
-    Store_field(result, 1, Val_int(0));                               /* cdr */
-
-    for (loop = 1; loop < my_length; loop++)
-    {
-        temp = result;
-        result = caml_alloc(2,0);
-        Store_field(result, 0, Val_int(buffer[my_length - loop - 1] & 0xff));
-        Store_field(result, 1, temp);
-    }
-
-    CAMLreturn(result);
-}
+
+    context_t ctx;
+    pdb_request_t req;
+
+    decode_context(&ctx, context);
+
+    req.operation = PDB_OPCODE_RD_MEM;
+    req.process = ctx.process;
+    req.u.rd_mem.address = Int32_val(address);
+    req.u.rd_mem.length  = Int_val(length);
+
+    send_request(ctx.ring, ctx.evtchn, &req);
+    
+    CAMLreturn(Val_unit);
+}
+
 
 /*
  * proc_write_memory : context_t -> int32 -> int list -> unit
@@ -360,50 +365,37 @@
     CAMLlocal1(node);
 
     context_t ctx;
-
-    char buffer[4096];  /* a big buffer */
-    memory_t  my_address;
+    pdb_request_t req;
     u32 length = 0;
 
-    printf ("(pdb) write memory\n");
-
-    decode_context(&ctx, context);
+    decode_context(&ctx, context);
+
+    req.operation = PDB_OPCODE_WR_MEM;
+    req.process = ctx.process;
 
     node = val_list;
     if ( Int_val(node) == 0 )       /* gdb functionalty test uses empty list */
     {
-        CAMLreturn(Val_unit);
+        req.u.wr_mem.address = Int32_val(address);
+        req.u.wr_mem.length  = 0;
     }
-
-    while ( Int_val(Field(node,1)) != 0 )
+    else
     {
-        buffer[length++] = Int_val(Field(node, 0));
-        node = Field(node,1);
+        while ( Int_val(Field(node,1)) != 0 )
+        {
+            req.u.wr_mem.data[length++] = Int_val(Field(node, 0));
+            node = Field(node,1);
+        }
+        req.u.wr_mem.data[length++] = Int_val(Field(node, 0));
+        
+        req.u.wr_mem.address = Int32_val(address);
+        req.u.wr_mem.length  = length;
     }
-    buffer[length++] = Int_val(Field(node, 0));
-
-    my_address = (memory_t) Int32_val(address);
-
-    /*
-    if ( xendebug_write_memory(xc_handle, ctx.domain, ctx.vcpu,
-                               my_address, length, buffer) )
-    {
-        printf("(pdb) write memory error!\n");  fflush(stdout);
-        failwith("write memory error");
-    }
-    */
-    {
-        int loop;
-        for (loop = 0; loop < length; loop++)
-        {
-            printf (" %02x", buffer[loop]);
-        }
-        printf ("\n");
-    }
-
-    CAMLreturn(Val_unit);
-}
-
+ 
+    send_request(ctx.ring, ctx.evtchn, &req);
+   
+    CAMLreturn(Val_unit);
+}
 
 
 /*
@@ -415,17 +407,14 @@
     CAMLparam1(context);
 
     context_t ctx;
-
-    decode_context(&ctx, context);
-
-    /*
-    if ( xendebug_continue(xc_handle, ctx.domain, ctx.vcpu) )
-    {
-        printf("(pdb) continue\n");  fflush(stdout);
-        failwith("continue");
-    }
-    */
-    printf ("CONTINUE\n");
+    pdb_request_t req;
+
+    decode_context(&ctx, context);
+
+    req.operation = PDB_OPCODE_CONTINUE;
+    req.process = ctx.process;
+ 
+    send_request(ctx.ring, ctx.evtchn, &req);
 
     CAMLreturn(Val_unit);
 }
@@ -439,17 +428,14 @@
     CAMLparam1(context);
 
     context_t ctx;
-
-    decode_context(&ctx, context);
-
-    /*
-    if ( xendebug_step(xc_handle, ctx.domain, ctx.vcpu) )
-    {
-        printf("(pdb) step\n");  fflush(stdout);
-        failwith("step");
-    }
-    */
-    printf ("STEP\n");
+    pdb_request_t req;
+
+    decode_context(&ctx, context);
+
+    req.operation = PDB_OPCODE_STEP;
+    req.process = ctx.process;
+ 
+    send_request(ctx.ring, ctx.evtchn, &req);
 
     CAMLreturn(Val_unit);
 }
@@ -465,22 +451,16 @@
     CAMLparam3(context, address, length);
 
     context_t ctx;
-    memory_t my_address = (memory_t) Int32_val(address);
-    int my_length = Int_val(length);
-
-    decode_context(&ctx, context);
-
-    printf ("(pdb) insert memory breakpoint 0x%lx %d\n",
-            my_address, my_length);
-
-    /*
-    if ( xendebug_insert_memory_breakpoint(xc_handle, ctx.domain, ctx.vcpu,
-                                           my_address, my_length) )
-    {
-        printf("(pdb) error: insert memory breakpoint\n");  fflush(stdout);
-        failwith("insert memory breakpoint");
-    }
-    */
+    pdb_request_t req;
+
+    decode_context(&ctx, context);
+
+    req.operation = PDB_OPCODE_SET_BKPT;
+    req.process = ctx.process;
+    req.u.bkpt.address = (memory_t) Int32_val(address);
+    req.u.bkpt.length  =  Int_val(length);
+
+    send_request(ctx.ring, ctx.evtchn, &req);
 
     CAMLreturn(Val_unit);
 }
@@ -494,24 +474,16 @@
     CAMLparam3(context, address, length);
 
     context_t ctx;
-
-    memory_t my_address = (memory_t) Int32_val(address);
-    int my_length = Int_val(length);
-
-    printf ("(pdb) remove memory breakpoint 0x%lx %d\n",
-            my_address, my_length);
-
-    decode_context(&ctx, context);
-
-    /*
-    if ( xendebug_remove_memory_breakpoint(xc_handle, 
-                                           ctx.domain, ctx.vcpu,
-                                           my_address, my_length) )
-    {
-        printf("(pdb) error: remove memory breakpoint\n");  fflush(stdout);
-        failwith("remove memory breakpoint");
-    }
-    */
+    pdb_request_t req;
+
+    decode_context(&ctx, context);
+
+    req.operation = PDB_OPCODE_CLR_BKPT;
+    req.process = ctx.process;
+    req.u.bkpt.address = (memory_t) Int32_val(address);
+    req.u.bkpt.length  =  Int_val(length);
+
+    send_request(ctx.ring, ctx.evtchn, &req);
 
     CAMLreturn(Val_unit);
 }
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/pdb/pdb_caml_xcs.c
--- a/tools/debugger/pdb/pdb_caml_xcs.c Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/pdb_caml_xcs.c Thu Jul 28 21:28:23 2005
@@ -201,7 +201,7 @@
     ret = connect(control_fd, (struct sockaddr *)&addr, len);
     if (ret < 0) 
     {
-        printf("error connecting to xcs(ctrl)! (%d)\n", errno);
+        printf("error connecting to xcs (ctrl)! (%d)\n", errno);
         goto ctrl_fd_fail;
     }
             
@@ -235,7 +235,7 @@
     ret = connect(data_fd, (struct sockaddr *)&addr, len);
     if (ret < 0) 
     {
-        printf("error connecting to xcs(data)! (%d)\n", errno);
+        printf("error connecting to xcs (data)! (%d)\n", errno);
         goto data_fd_fail;
     }
 
diff -r 501a70f3ae96 -r 577d1c7b47a9 tools/debugger/pdb/readme
--- a/tools/debugger/pdb/readme Thu Jul 28 12:34:45 2005
+++ b/tools/debugger/pdb/readme Thu Jul 28 21:28:23 2005
@@ -31,7 +31,7 @@
   Build the target domains with debugging symbols.
   make CONFIG_DEBUG_INFO=true CONFIG_FRAME_POINTER=false linux-2.6-xenU-build
 
-  You can also change linux-2.6.11-xenU/Makefile
+  You can also change linux-2.6.12-xenU/Makefile
   CONFIG_CC_OPTIMIZE_FOR_SIZE from -O2 to -O
 
 - Build PDB
@@ -46,7 +46,7 @@
   domain-0.xeno# ./pdb <port>
 
 - Run GDB
-  hostname% gdb <xeno.bk>/dist/install/boot/vmlinux-syms-2.6.11.11-xenU
+  hostname% gdb <xeno.bk>/dist/install/boot/vmlinux-syms-2.6.12-xenU
 
   (gdb) target remote domain-0.xeno:<port>
 
@@ -76,9 +76,18 @@
   continue
   print
 
+Process
+
+  PDB can also debug a process running in a Linux 2.6 domain. 
+  After running PDB in domain 0, insert the pdb module in dom u:
+  
+  % insmod linux-2.6-module/pdb.ko
+
+  Load GDB with the appropriate symbols, and attach with
+
+  (gdb) maint packet x context = process <domid> <pid>
 
 To Do
 
 - watchpoints
 - support for SMP
-- support for user applications

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] PDB: process targets, Xen patchbot -unstable <=