diff options
Diffstat (limited to 'tools/debugger/pdb/linux-2.6-module')
-rw-r--r-- | tools/debugger/pdb/linux-2.6-module/Makefile | 21 | ||||
-rw-r--r-- | tools/debugger/pdb/linux-2.6-module/debug.c | 851 | ||||
-rw-r--r-- | tools/debugger/pdb/linux-2.6-module/module.c | 337 | ||||
-rw-r--r-- | tools/debugger/pdb/linux-2.6-module/pdb_debug.h | 47 | ||||
-rw-r--r-- | tools/debugger/pdb/linux-2.6-module/pdb_module.h | 142 |
5 files changed, 0 insertions, 1398 deletions
diff --git a/tools/debugger/pdb/linux-2.6-module/Makefile b/tools/debugger/pdb/linux-2.6-module/Makefile deleted file mode 100644 index 9025cd85c1..0000000000 --- a/tools/debugger/pdb/linux-2.6-module/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -XEN_ROOT = ../../../.. -LINUX_DIR = linux-2.6.12-xenU -KDIR = $(XEN_ROOT)/$(LINUX_DIR) - -obj-m += pdb.o -pdb-objs += module.o -pdb-objs += debug.o - -CFLAGS += -g -CFLAGS += -Wall -CFLAGS += -Werror - -.PHONY: module -module : -# make KBUILD_VERBOSE=1 ARCH=xen -C $(KDIR) M=$(PWD) modules - make ARCH=xen -C $(KDIR) M=$(PWD) modules - -.PHONY: clean -clean : - make -C $(KDIR) M=$(PWD) clean - diff --git a/tools/debugger/pdb/linux-2.6-module/debug.c b/tools/debugger/pdb/linux-2.6-module/debug.c deleted file mode 100644 index e53dfbc1b1..0000000000 --- a/tools/debugger/pdb/linux-2.6-module/debug.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * debug.c - * pdb debug functionality for processes. - */ - -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <asm-i386/kdebug.h> -#include <asm-i386/mach-xen/asm/processor.h> -#include <asm-i386/mach-xen/asm/ptrace.h> -#include <asm-i386/mach-xen/asm/tlbflush.h> -#include <xen/interface/xen.h> -#include "pdb_module.h" -#include "pdb_debug.h" - - -static int pdb_debug_fn (struct pt_regs *regs, long error_code, - unsigned int condition); -static int pdb_int3_fn (struct pt_regs *regs, long error_code); -static int pdb_page_fault_fn (struct pt_regs *regs, long error_code, - unsigned int condition); - -/***********************************************************************/ - -typedef struct bwcpoint /* break/watch/catch point */ -{ - struct list_head list; - unsigned long address; - int length; - - uint8_t type; /* BWC_??? */ - uint8_t mode; /* for BWC_PAGE, the current protection mode */ - uint32_t process; - uint8_t error; /* error occured when enabling: don't disable. */ - - /* original values */ - uint8_t orig_bkpt; /* single byte breakpoint */ - pte_t orig_pte; - - struct list_head watchpt_read_list; /* read watchpoints on this page */ - struct list_head watchpt_write_list; /* write */ - struct list_head watchpt_access_list; /* access */ - struct list_head watchpt_disabled_list; /* disabled */ - - struct bwcpoint *parent; /* watchpoint: bwc_watch (the page) */ - struct bwcpoint *watchpoint; /* bwc_watch_step: original watchpoint */ -} bwcpoint_t, *bwcpoint_p; - -static struct list_head bwcpoint_list = LIST_HEAD_INIT(bwcpoint_list); - -#define _pdb_bwcpoint_alloc(_var) \ -{ \ - if ( (_var = kmalloc(sizeof(bwcpoint_t), GFP_KERNEL)) == NULL ) \ - printk("error: unable to allocate memory %d\n", __LINE__); \ - else { \ - memset(_var, 0, sizeof(bwcpoint_t)); \ - INIT_LIST_HEAD(&_var->watchpt_read_list); \ - INIT_LIST_HEAD(&_var->watchpt_write_list); \ - INIT_LIST_HEAD(&_var->watchpt_access_list); \ - INIT_LIST_HEAD(&_var->watchpt_disabled_list); \ - } \ -} - -/***********************************************************************/ - -static void _pdb_bwc_print_list (struct list_head *, char *, int); - -static void -_pdb_bwc_print (bwcpoint_p bwc, char *label, int level) -{ - printk("%s%03d 0x%08lx:0x%02x %c\n", label, bwc->type, - bwc->address, bwc->length, bwc->error ? 'e' : '-'); - - if ( !list_empty(&bwc->watchpt_read_list) ) - _pdb_bwc_print_list(&bwc->watchpt_read_list, "r", level); - if ( !list_empty(&bwc->watchpt_write_list) ) - _pdb_bwc_print_list(&bwc->watchpt_write_list, "w", level); - if ( !list_empty(&bwc->watchpt_access_list) ) - _pdb_bwc_print_list(&bwc->watchpt_access_list, "a", level); - if ( !list_empty(&bwc->watchpt_disabled_list) ) - _pdb_bwc_print_list(&bwc->watchpt_disabled_list, "d", level); -} - -static void -_pdb_bwc_print_list (struct list_head *bwc_list, char *label, int level) -{ - struct list_head *ptr; - int counter = 0; - - list_for_each(ptr, bwc_list) - { - bwcpoint_p bwc = list_entry(ptr, bwcpoint_t, list); - printk(" %s[%02d]%s ", level > 0 ? " " : "", counter++, - level > 0 ? "" : " "); - _pdb_bwc_print(bwc, label, level+1); - } - - if (counter == 0) - { - printk(" empty list\n"); - } -} - -void -pdb_bwc_print_list (void) -{ - _pdb_bwc_print_list(&bwcpoint_list, " ", 0); -} - -bwcpoint_p -pdb_search_watchpoint (uint32_t process, unsigned long address) -{ - bwcpoint_p bwc_watch = (bwcpoint_p) 0; - bwcpoint_p bwc_entry = (bwcpoint_p) 0; - struct list_head *ptr; - - list_for_each(ptr, &bwcpoint_list) /* find bwc page entry */ - { - bwc_watch = list_entry(ptr, bwcpoint_t, list); - if (bwc_watch->address == (address & PAGE_MASK)) break; - } - - if ( !bwc_watch ) - { - return (bwcpoint_p) 0; - } - -#define __pdb_search_watchpoint_list(__list) \ - list_for_each(ptr, (__list)) \ - { \ - bwc_entry = list_entry(ptr, bwcpoint_t, list); \ - if ( bwc_entry->process == process && \ - bwc_entry->address <= address && \ - bwc_entry->address + bwc_entry->length > address ) \ - return bwc_entry; \ - } - - __pdb_search_watchpoint_list(&bwc_watch->watchpt_read_list); - __pdb_search_watchpoint_list(&bwc_watch->watchpt_write_list); - __pdb_search_watchpoint_list(&bwc_watch->watchpt_access_list); - -#undef __pdb_search_watchpoint_list - - return (bwcpoint_p) 0; -} - -/*************************************************************/ - -int -pdb_suspend (struct task_struct *target) -{ - uint32_t rc = 0; - - force_sig(SIGSTOP, target); /* force_sig_specific ??? */ - - return rc; -} - -int -pdb_resume (struct task_struct *target) -{ - int rc = 0; - - wake_up_process(target); - - return rc; -} - -/* - * from linux-2.6.11/arch/i386/kernel/ptrace.c::getreg() - */ -static unsigned long -_pdb_get_register (struct task_struct *target, int reg) -{ - unsigned long result = ~0UL; - unsigned long offset; - unsigned char *stack = 0L; - - switch (reg) - { - case LINUX_FS: - result = target->thread.fs; - break; - case LINUX_GS: - result = target->thread.gs; - break; - case LINUX_DS: - case LINUX_ES: - case LINUX_SS: - case LINUX_CS: - result = 0xffff; - /* fall through */ - default: - if (reg > LINUX_GS) - reg -= 2; - - offset = reg * sizeof(long); - offset -= sizeof(struct pt_regs); - stack = (unsigned char *)target->thread.esp0; - stack += offset; - result &= *((int *)stack); - } - - return result; -} - -/* - * 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_register (struct task_struct *target, pdb_op_rd_reg_p op) -{ - int rc = 0; - - switch (op->reg) - { - case 0: op->value = _pdb_get_register(target, LINUX_EAX); break; - case 1: op->value = _pdb_get_register(target, LINUX_ECX); break; - case 2: op->value = _pdb_get_register(target, LINUX_EDX); break; - case 3: op->value = _pdb_get_register(target, LINUX_EBX); break; - case 4: op->value = _pdb_get_register(target, LINUX_ESP); break; - case 5: op->value = _pdb_get_register(target, LINUX_EBP); break; - case 6: op->value = _pdb_get_register(target, LINUX_ESI); break; - case 7: op->value = _pdb_get_register(target, LINUX_EDI); break; - case 8: op->value = _pdb_get_register(target, LINUX_EIP); break; - case 9: op->value = _pdb_get_register(target, LINUX_EFL); break; - - case 10: op->value = _pdb_get_register(target, LINUX_CS); break; - case 11: op->value = _pdb_get_register(target, LINUX_SS); break; - case 12: op->value = _pdb_get_register(target, LINUX_DS); break; - case 13: op->value = _pdb_get_register(target, LINUX_ES); break; - case 14: op->value = _pdb_get_register(target, LINUX_FS); break; - case 15: op->value = _pdb_get_register(target, LINUX_GS); break; - } - - return rc; -} - -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); - op->reg[ 2] = _pdb_get_register(target, LINUX_EDX); - op->reg[ 3] = _pdb_get_register(target, LINUX_EBX); - op->reg[ 4] = _pdb_get_register(target, LINUX_ESP); - op->reg[ 5] = _pdb_get_register(target, LINUX_EBP); - op->reg[ 6] = _pdb_get_register(target, LINUX_ESI); - op->reg[ 7] = _pdb_get_register(target, LINUX_EDI); - op->reg[ 8] = _pdb_get_register(target, LINUX_EIP); - op->reg[ 9] = _pdb_get_register(target, LINUX_EFL); - - op->reg[10] = _pdb_get_register(target, LINUX_CS); - op->reg[11] = _pdb_get_register(target, LINUX_SS); - op->reg[12] = _pdb_get_register(target, LINUX_DS); - op->reg[13] = _pdb_get_register(target, LINUX_ES); - op->reg[14] = _pdb_get_register(target, LINUX_FS); - op->reg[15] = _pdb_get_register(target, LINUX_GS); - - 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); - - _pdb_bwcpoint_alloc(bkpt); - if ( bkpt == NULL ) return -1; - - bkpt->process = target->pid; - bkpt->address = 0; - bkpt->type = BWC_DEBUG; - - list_add_tail(&bkpt->list, &bwcpoint_list); - - wake_up_process(target); - - return rc; -} - -int -pdb_insert_memory_breakpoint (struct task_struct *target, - unsigned long address, uint32_t length) -{ - int rc = 0; - bwcpoint_p bkpt; - uint8_t breakpoint_opcode = 0xcc; - - printk("insert breakpoint %d:%lx len: %d\n", target->pid, address, length); - - if ( length != 1 ) - { - printk("error: breakpoint length should be 1\n"); - return -1; - } - - _pdb_bwcpoint_alloc(bkpt); - if ( bkpt == NULL ) return -1; - - bkpt->process = target->pid; - bkpt->address = address; - bkpt->type = BWC_INT3; - - pdb_access_memory(target, address, &bkpt->orig_bkpt, 1, PDB_MEM_READ); - pdb_access_memory(target, address, &breakpoint_opcode, 1, PDB_MEM_WRITE); - - list_add_tail(&bkpt->list, &bwcpoint_list); - - printk("breakpoint_set %d:%lx OLD: 0x%x\n", - target->pid, address, bkpt->orig_bkpt); - pdb_bwc_print_list(); - - return rc; -} - -int -pdb_remove_memory_breakpoint (struct task_struct *target, - unsigned long address, uint32_t 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) - { - bkpt = list_entry(entry, bwcpoint_t, list); - if ( target->pid == bkpt->process && - address == bkpt->address && - bkpt->type == BWC_INT3 ) - break; - } - - if (entry == &bwcpoint_list) - { - printk ("error: no breakpoint found\n"); - return -1; - } - - pdb_access_memory(target, address, &bkpt->orig_bkpt, 1, PDB_MEM_WRITE); - - list_del(&bkpt->list); - kfree(bkpt); - - pdb_bwc_print_list(); - - return rc; -} - -#define PDB_PTE_UPDATE 1 -#define PDB_PTE_RESTORE 2 - -int -pdb_change_pte (struct task_struct *target, bwcpoint_p bwc, int mode) -{ - int rc = 0; - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *ptep; - - pgd = pgd_offset(target->mm, bwc->address); - if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) return -1; - - pud = pud_offset(pgd, bwc->address); - if (pud_none(*pud) || unlikely(pud_bad(*pud))) return -2; - - pmd = pmd_offset(pud, bwc->address); - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) return -3; - - ptep = pte_offset_map(pmd, bwc->address); - if (!ptep) return -4; - - switch ( mode ) - { - case PDB_PTE_UPDATE: /* added or removed a watchpoint. update pte. */ - { - pte_t new_pte; - - if ( pte_val(bwc->parent->orig_pte) == 0 ) /* new watchpoint page */ - { - bwc->parent->orig_pte = *ptep; - } - - new_pte = bwc->parent->orig_pte; - - if ( !list_empty(&bwc->parent->watchpt_read_list) || - !list_empty(&bwc->parent->watchpt_access_list) ) - { - new_pte = pte_rdprotect(new_pte); - } - - if ( !list_empty(&bwc->parent->watchpt_write_list) || - !list_empty(&bwc->parent->watchpt_access_list) ) - { - new_pte = pte_wrprotect(new_pte); - } - - if ( pte_val(new_pte) != pte_val(*ptep) ) - { - *ptep = new_pte; - flush_tlb_mm(target->mm); - } - break; - } - case PDB_PTE_RESTORE : /* suspend watchpoint by restoring original pte */ - { - *ptep = bwc->parent->orig_pte; - flush_tlb_mm(target->mm); - break; - } - default : - { - printk("(linux) unknown mode %d %d\n", mode, __LINE__); - break; - } - } - - pte_unmap(ptep); /* can i flush the tlb before pte_unmap? */ - - return rc; -} - -int -pdb_insert_watchpoint (struct task_struct *target, pdb_op_watchpt_p watchpt) -{ - int rc = 0; - - bwcpoint_p bwc_watch; - bwcpoint_p bwc_entry; - struct list_head *ptr; - unsigned long page = watchpt->address & PAGE_MASK; - struct list_head *watchpoint_list; - - printk("insert watchpoint: %d %x %x\n", - watchpt->type, watchpt->address, watchpt->length); - - list_for_each(ptr, &bwcpoint_list) /* find existing bwc page entry */ - { - bwc_watch = list_entry(ptr, bwcpoint_t, list); - - if (bwc_watch->address == page) goto got_bwc_watch; - } - - _pdb_bwcpoint_alloc(bwc_watch); /* create new bwc:watch */ - if ( bwc_watch == NULL ) return -1; - - bwc_watch->type = BWC_WATCH; - bwc_watch->process = target->pid; - bwc_watch->address = page; - - list_add_tail(&bwc_watch->list, &bwcpoint_list); - - got_bwc_watch: - - switch (watchpt->type) - { - case BWC_WATCH_READ: - watchpoint_list = &bwc_watch->watchpt_read_list; break; - case BWC_WATCH_WRITE: - watchpoint_list = &bwc_watch->watchpt_write_list; break; - case BWC_WATCH_ACCESS: - watchpoint_list = &bwc_watch->watchpt_access_list; break; - default: - printk("unknown type %d\n", watchpt->type); return -2; - } - - _pdb_bwcpoint_alloc(bwc_entry); /* create new bwc:entry */ - if ( bwc_entry == NULL ) return -1; - - bwc_entry->process = target->pid; - bwc_entry->address = watchpt->address; - bwc_entry->length = watchpt->length; - bwc_entry->type = watchpt->type; - bwc_entry->parent = bwc_watch; - - list_add_tail(&bwc_entry->list, watchpoint_list); - pdb_change_pte(target, bwc_entry, PDB_PTE_UPDATE); - - pdb_bwc_print_list(); - - return rc; -} - -int -pdb_remove_watchpoint (struct task_struct *target, pdb_op_watchpt_p watchpt) -{ - int rc = 0; - bwcpoint_p bwc_watch = (bwcpoint_p) NULL; - bwcpoint_p bwc_entry = (bwcpoint_p) NULL; - unsigned long page = watchpt->address & PAGE_MASK; - struct list_head *ptr; - struct list_head *watchpoint_list; - - printk("remove watchpoint: %d %x %x\n", - watchpt->type, watchpt->address, watchpt->length); - - list_for_each(ptr, &bwcpoint_list) /* find bwc page entry */ - { - bwc_watch = list_entry(ptr, bwcpoint_t, list); - if (bwc_watch->address == page) break; - } - - if ( !bwc_watch ) - { - printk("(linux) delete watchpoint: can't find bwc page 0x%08x\n", - watchpt->address); - return -1; - } - - switch (watchpt->type) - { - case BWC_WATCH_READ: - watchpoint_list = &bwc_watch->watchpt_read_list; break; - case BWC_WATCH_WRITE: - watchpoint_list = &bwc_watch->watchpt_write_list; break; - case BWC_WATCH_ACCESS: - watchpoint_list = &bwc_watch->watchpt_access_list; break; - default: - printk("unknown type %d\n", watchpt->type); return -2; - } - - list_for_each(ptr, watchpoint_list) /* find watchpoint */ - { - bwc_entry = list_entry(ptr, bwcpoint_t, list); - if ( bwc_entry->address == watchpt->address && - bwc_entry->length == watchpt->length ) break; - } - - if ( !bwc_entry ) /* or ptr == watchpoint_list */ - { - printk("(linux) delete watchpoint: can't find watchpoint 0x%08x\n", - watchpt->address); - return -1; - } - - list_del(&bwc_entry->list); - pdb_change_pte(target, bwc_entry, PDB_PTE_UPDATE); - kfree(bwc_entry); - - - if ( list_empty(&bwc_watch->watchpt_read_list) && - list_empty(&bwc_watch->watchpt_write_list) && - list_empty(&bwc_watch->watchpt_access_list) ) - { - list_del(&bwc_watch->list); - kfree(bwc_watch); - } - - pdb_bwc_print_list(); - - 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 */ - if ( pdb_int3_fn(args->regs, args->err) ) - return NOTIFY_STOP; - break; - case DIE_PAGE_FAULT: - if ( pdb_page_fault_fn(args->regs, args->trapnr, args->err) ) - return NOTIFY_STOP; - break; - case DIE_GPF: - printk("---------------GPF\n"); - break; - default: - break; - } - - return NOTIFY_DONE; -} - - -static 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; - - printk("pdb_debug_fn\n"); - - list_for_each(entry, &bwcpoint_list) - { - bkpt = list_entry(entry, bwcpoint_t, list); - if ( current->pid == bkpt->process && - (bkpt->type == BWC_DEBUG || /* single step */ - bkpt->type == BWC_WATCH_STEP)) /* single step over watchpoint */ - break; - } - - if (entry == &bwcpoint_list) - { - printk("not my debug 0x%x 0x%lx\n", current->pid, regs->eip); - return 0; - } - - pdb_suspend(current); - - printk("(pdb) %s pid: %d, eip: 0x%08lx\n", - bkpt->type == BWC_DEBUG ? "debug" : "watch-step", - current->pid, regs->eip); - - regs->eflags &= ~X86_EFLAGS_TF; - set_tsk_thread_flag(current, TIF_SINGLESTEP); - - switch (bkpt->type) - { - case BWC_DEBUG: - resp.operation = PDB_OPCODE_STEP; - break; - case BWC_WATCH_STEP: - { - struct list_head *watchpoint_list; - bwcpoint_p watch_page = bkpt->watchpoint->parent; - - switch (bkpt->watchpoint->type) - { - case BWC_WATCH_READ: - watchpoint_list = &watch_page->watchpt_read_list; break; - case BWC_WATCH_WRITE: - watchpoint_list = &watch_page->watchpt_write_list; break; - case BWC_WATCH_ACCESS: - watchpoint_list = &watch_page->watchpt_access_list; break; - default: - printk("unknown type %d\n", bkpt->watchpoint->type); return 0; - } - - resp.operation = PDB_OPCODE_WATCHPOINT; - list_del_init(&bkpt->watchpoint->list); - list_add_tail(&bkpt->watchpoint->list, watchpoint_list); - pdb_change_pte(current, bkpt->watchpoint, PDB_PTE_UPDATE); - pdb_bwc_print_list(); - break; - } - default: - printk("unknown breakpoint type %d %d\n", __LINE__, bkpt->type); - return 0; - } - - resp.process = current->pid; - resp.status = PDB_RESPONSE_OKAY; - - pdb_send_response(&resp); - - list_del(&bkpt->list); - kfree(bkpt); - - return 1; -} - - -static int -pdb_int3_fn (struct pt_regs *regs, long error_code) -{ - pdb_response_t resp; - bwcpoint_p bkpt = NULL; - unsigned long address = regs->eip - 1; - - struct list_head *entry; - list_for_each(entry, &bwcpoint_list) - { - bkpt = list_entry(entry, bwcpoint_t, list); - if ( current->pid == bkpt->process && - address == bkpt->address && - bkpt->type == BWC_INT3 ) - break; - } - - if (entry == &bwcpoint_list) - { - printk("not my int3 bkpt 0x%x 0x%lx\n", current->pid, address); - return 0; - } - - printk("(pdb) int3 pid: %d, eip: 0x%08lx\n", current->pid, address); - - pdb_suspend(current); - - resp.operation = PDB_OPCODE_CONTINUE; - resp.process = current->pid; - resp.status = PDB_RESPONSE_OKAY; - - pdb_send_response(&resp); - - return 1; -} - -static int -pdb_page_fault_fn (struct pt_regs *regs, long error_code, - unsigned int condition) -{ - unsigned long cr2; - unsigned long cr3; - bwcpoint_p bwc; - bwcpoint_p watchpt; - bwcpoint_p bkpt; - - __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : ); - __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (cr2) : ); - - bwc = pdb_search_watchpoint(current->pid, cr2); - if ( !bwc ) - { - return 0; /* not mine */ - } - - printk("page_fault cr2:%08lx err:%lx eip:%08lx\n", - cr2, error_code, regs->eip); - - /* disable the watchpoint */ - watchpt = bwc->watchpoint; - list_del_init(&bwc->list); - list_add_tail(&bwc->list, &bwc->parent->watchpt_disabled_list); - pdb_change_pte(current, bwc, PDB_PTE_RESTORE); - - /* single step the faulting instruction */ - regs->eflags |= X86_EFLAGS_TF; - - /* create a bwcpoint entry so we know what to do once we regain control */ - _pdb_bwcpoint_alloc(bkpt); - if ( bkpt == NULL ) return -1; - - bkpt->process = current->pid; - bkpt->address = 0; - bkpt->type = BWC_WATCH_STEP; - bkpt->watchpoint = bwc; - - /* add to head so we see it first the next time we break */ - list_add(&bkpt->list, &bwcpoint_list); - - pdb_bwc_print_list(); - return 1; -} - - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/tools/debugger/pdb/linux-2.6-module/module.c b/tools/debugger/pdb/linux-2.6-module/module.c deleted file mode 100644 index 5ca0e025ca..0000000000 --- a/tools/debugger/pdb/linux-2.6-module/module.c +++ /dev/null @@ -1,337 +0,0 @@ - -/* - * module.c - * - * Handles initial registration with pdb when the pdb module starts up - * and cleanup when the module goes away (sortof :) - * Also receives each request from pdb in domain 0 and dispatches to the - * appropriate debugger function. - */ - -#include <linux/module.h> -#include <linux/interrupt.h> - -#include <asm-i386/kdebug.h> - -#include <xen/evtchn.h> -#include <xen/ctrl_if.h> -#include <xen/hypervisor.h> -#include <xen/interface/io/domain_controller.h> -#include <xen/interface/xen.h> - -#include <xen/interface/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 - */ -void -pdb_send_response (pdb_response_t *response) -{ - pdb_response_t *resp; - - 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++; - RING_PUSH_RESPONSES(&pdb_ring); - notify_via_evtchn(pdb_evtchn); - return; -} - -/* - * handle a debug command from the front end - */ -static void -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.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_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_resume(target); - printk("(linux) detach 0x%x\n", request->process); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_RD_REG : - resp.u.rd_reg.reg = request->u.rd_reg.reg; - pdb_read_register(target, &resp.u.rd_reg); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_RD_REGS : - pdb_read_registers(target, &resp.u.rd_regs); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_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, - PDB_MEM_READ); - 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, - PDB_MEM_WRITE); - 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; - case PDB_OPCODE_SET_WATCHPT : - pdb_insert_watchpoint(target, &request->u.watchpt); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_CLR_WATCHPT : - pdb_remove_watchpoint(target, &request->u.watchpt); - 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; -} - -/* - * work queue - */ -static void -pdb_work_handler (void *unused) -{ - pdb_request_t *req; - RING_IDX i, rp; - - rp = pdb_ring.sring->req_prod; - rmb(); - - for ( i = pdb_ring.req_cons; - (i != rp) && !RING_REQUEST_CONS_OVERFLOW(&pdb_ring, i); - i++ ) - { - req = RING_GET_REQUEST(&pdb_ring, i); - pdb_process_request(req); - - } - 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, unsigned long ring) -{ - ctrl_msg_t cmsg = - { - .type = CMSG_DEBUG, - .subtype = CMSG_DEBUG_CONNECTION_STATUS, - .length = sizeof(pdb_connection_t), - }; - pdb_connection_t *conn = (pdb_connection_t *)cmsg.msg; - - conn->status = status; - conn->ring = ring; - conn->evtchn = 0; - - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -} - - -/* - * this is called each time a message is received on the control channel - */ -static void -pdb_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - switch (msg->subtype) - { - case CMSG_DEBUG_CONNECTION_STATUS: - /* initialize event channel created by the pdb server */ - - pdb_evtchn = ((pdb_connection_p) msg->msg)->evtchn; - pdb_irq = bind_evtchn_to_irq(pdb_evtchn); - - if ( request_irq(pdb_irq, pdb_interrupt, - SA_SAMPLE_RANDOM, "pdb", NULL) ) - { - printk("(pdb) request irq failed: %d %d\n", pdb_evtchn, pdb_irq); - } - break; - - default: - printk ("(pdb) unknown xcs control message: %d\n", msg->subtype); - break; - } - - return; -} - - -/********************************************************************/ - -static struct notifier_block pdb_exceptions_nb = -{ - .notifier_call = pdb_exceptions_notify, - .priority = 0x1 /* low priority */ -}; - - -static int __init -pdb_initialize (void) -{ - int err; - pdb_sring_t *sring; - - printk("----\npdb initialize %s %s\n", __DATE__, __TIME__); - - /* - 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); - - /* rings */ - sring = (pdb_sring_t *)__get_free_page(GFP_KERNEL); - SHARED_RING_INIT(sring); - BACK_RING_INIT(&pdb_ring, sring, PAGE_SIZE); - - /* notify pdb in dom 0 */ - pdb_send_connection_status(PDB_CONNECTION_STATUS_UP, - virt_to_machine(pdb_ring.sring) >> PAGE_SHIFT); - - /* handler for int1 & int3 */ - err = register_die_notifier(&pdb_exceptions_nb); - - return err; -} - -static void __exit -pdb_terminate(void) -{ - int err = 0; - - printk("pdb cleanup\n"); - - (void)ctrl_if_unregister_receiver(CMSG_DEBUG, pdb_ctrlif_rx); - - if (pdb_irq) - { - free_irq(pdb_irq, NULL); - pdb_irq = 0; - } - - if (pdb_evtchn) - { - unbind_evtchn_from_irq(pdb_evtchn); - pdb_evtchn = 0; - } - - pdb_send_connection_status(PDB_CONNECTION_STATUS_DOWN, 0); - - /* handler for int1 & int3 */ - err = unregister_die_notifier(&pdb_exceptions_nb); - - return; -} - - -module_init(pdb_initialize); -module_exit(pdb_terminate); - - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/tools/debugger/pdb/linux-2.6-module/pdb_debug.h b/tools/debugger/pdb/linux-2.6-module/pdb_debug.h deleted file mode 100644 index 89adbc0b0d..0000000000 --- a/tools/debugger/pdb/linux-2.6-module/pdb_debug.h +++ /dev/null @@ -1,47 +0,0 @@ - -#ifndef __PDB_DEBUG_H_ -#define __PDB_DEBUG_H_ - -/* debugger.c */ -void pdb_initialize_bwcpoint (void); -int pdb_suspend (struct task_struct *target); -int pdb_resume (struct task_struct *target); -int pdb_read_register (struct task_struct *target, pdb_op_rd_reg_p op); -int pdb_read_registers (struct task_struct *target, pdb_op_rd_regs_p op); -int pdb_write_register (struct task_struct *target, pdb_op_wr_reg_p op); -int pdb_read_memory (struct task_struct *target, pdb_op_rd_mem_req_p req, - pdb_op_rd_mem_resp_p resp); -int pdb_write_memory (struct task_struct *target, pdb_op_wr_mem_p op); -int pdb_access_memory (struct task_struct *target, unsigned long address, - void *buffer, int length, int write); -int pdb_continue (struct task_struct *target); -int pdb_step (struct task_struct *target); - -int pdb_insert_memory_breakpoint (struct task_struct *target, - unsigned long address, uint32_t length); -int pdb_remove_memory_breakpoint (struct task_struct *target, - unsigned long address, uint32_t length); -int pdb_insert_watchpoint (struct task_struct *target, - pdb_op_watchpt_p watchpt); -int pdb_remove_watchpoint (struct task_struct *target, - pdb_op_watchpt_p watchpt); - -int pdb_exceptions_notify (struct notifier_block *self, unsigned long val, - void *data); - -/* module.c */ -void pdb_send_response (pdb_response_t *response); - -#endif - - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/tools/debugger/pdb/linux-2.6-module/pdb_module.h b/tools/debugger/pdb/linux-2.6-module/pdb_module.h deleted file mode 100644 index 472403d69e..0000000000 --- a/tools/debugger/pdb/linux-2.6-module/pdb_module.h +++ /dev/null @@ -1,142 +0,0 @@ - -#ifndef __PDB_MODULE_H_ -#define __PDB_MODULE_H_ - -#include "../pdb_caml_xen.h" - -#define PDB_OPCODE_PAUSE 1 - -#define PDB_OPCODE_ATTACH 2 -typedef struct pdb_op_attach -{ - uint32_t domain; -} pdb_op_attach_t, *pdb_op_attach_p; - -#define PDB_OPCODE_DETACH 3 - -#define PDB_OPCODE_RD_REG 4 -typedef struct pdb_op_rd_reg -{ - uint32_t reg; - uint32_t value; -} pdb_op_rd_reg_t, *pdb_op_rd_reg_p; - -#define PDB_OPCODE_RD_REGS 5 -typedef struct pdb_op_rd_regs -{ - uint32_t reg[GDB_REGISTER_FRAME_SIZE]; -} pdb_op_rd_regs_t, *pdb_op_rd_regs_p; - -#define PDB_OPCODE_WR_REG 6 -typedef struct pdb_op_wr_reg -{ - uint32_t reg; - uint32_t value; -} pdb_op_wr_reg_t, *pdb_op_wr_reg_p; - -#define PDB_OPCODE_RD_MEM 7 -typedef struct pdb_op_rd_mem_req -{ - uint32_t address; - uint32_t length; -} pdb_op_rd_mem_req_t, *pdb_op_rd_mem_req_p; - -typedef struct pdb_op_rd_mem_resp -{ - uint32_t address; - uint32_t length; - uint8_t data[1024]; -} pdb_op_rd_mem_resp_t, *pdb_op_rd_mem_resp_p; - -#define PDB_OPCODE_WR_MEM 8 -typedef struct pdb_op_wr_mem -{ - uint32_t address; - uint32_t length; - uint8_t data[1024]; /* arbitrary */ -} pdb_op_wr_mem_t, *pdb_op_wr_mem_p; - -#define PDB_OPCODE_CONTINUE 9 -#define PDB_OPCODE_STEP 10 - -#define PDB_OPCODE_SET_BKPT 11 -#define PDB_OPCODE_CLR_BKPT 12 -typedef struct pdb_op_bkpt -{ - uint32_t address; - uint32_t length; -} pdb_op_bkpt_t, *pdb_op_bkpt_p; - -#define PDB_OPCODE_SET_WATCHPT 13 -#define PDB_OPCODE_CLR_WATCHPT 14 -#define PDB_OPCODE_WATCHPOINT 15 -typedef struct pdb_op_watchpt -{ -#define BWC_DEBUG 1 -#define BWC_INT3 3 -#define BWC_WATCH 100 /* pdb: watchpoint page */ -#define BWC_WATCH_STEP 101 /* pdb: watchpoint single step */ -#define BWC_WATCH_WRITE 102 -#define BWC_WATCH_READ 103 -#define BWC_WATCH_ACCESS 104 - uint32_t type; - uint32_t address; - uint32_t length; -} pdb_op_watchpt_t, *pdb_op_watchpt_p; - - -typedef struct -{ - uint8_t operation; /* PDB_OPCODE_??? */ - uint32_t process; - union - { - pdb_op_attach_t attach; - pdb_op_rd_reg_t rd_reg; - 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; - pdb_op_watchpt_t watchpt; - } u; -} pdb_request_t, *pdb_request_p; - - - -#define PDB_RESPONSE_OKAY 0 -#define PDB_RESPONSE_ERROR -1 - -typedef struct { - uint8_t operation; /* copied from request */ - uint32_t domain; - uint32_t process; - int16_t status; /* PDB_RESPONSE_??? */ - union - { - pdb_op_rd_reg_t rd_reg; - 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); - - -/* from access_process_vm */ -#define PDB_MEM_READ 0 -#define PDB_MEM_WRITE 1 - -#endif - - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - |