[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.