[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |