diff options
author | cognet <cognet@FreeBSD.org> | 2004-11-21 18:11:39 +0000 |
---|---|---|
committer | cognet <cognet@FreeBSD.org> | 2004-11-21 18:11:39 +0000 |
commit | 22b168ab2449334b15b55b276945245bb1660a9d (patch) | |
tree | df736a61622aa96c6e0acdf37b6a2125c736826d /sys/arm | |
parent | 774795721abcc723b01400a6ab6a346139fcd6b8 (diff) | |
download | FreeBSD-src-22b168ab2449334b15b55b276945245bb1660a9d.zip FreeBSD-src-22b168ab2449334b15b55b276945245bb1660a9d.tar.gz |
Implement breakpoints and single stepping on arm.
Obtained from: NetBSD
Diffstat (limited to 'sys/arm')
-rw-r--r-- | sys/arm/arm/db_interface.c | 97 | ||||
-rw-r--r-- | sys/arm/arm/undefined.c | 14 | ||||
-rw-r--r-- | sys/arm/include/db_machdep.h | 17 | ||||
-rw-r--r-- | sys/arm/include/kdb.h | 2 |
4 files changed, 109 insertions, 21 deletions
diff --git a/sys/arm/arm/db_interface.c b/sys/arm/arm/db_interface.c index d1c349a..8832097 100644 --- a/sys/arm/arm/db_interface.c +++ b/sys/arm/arm/db_interface.c @@ -43,6 +43,9 @@ __FBSDID("$FreeBSD$"); #include <sys/reboot.h> #include <sys/systm.h> /* just for boothowto */ #include <sys/exec.h> +#ifdef KDB +#include <sys/kdb.h> +#endif #include <vm/vm.h> #include <vm/pmap.h> @@ -192,11 +195,6 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data) char *dst; size_t loop; - /* If any part is in kernel text, use db_write_text() */ - if (addr >= (vm_offset_t) btext && addr < (vm_offset_t) etext) { - return (-1); - } - dst = (char *)addr; if (db_validate_address((u_int)dst)) { db_printf("address %p is invalid\n", dst); @@ -229,4 +227,93 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data) } +static u_int +db_fetch_reg(int reg) +{ + + switch (reg) { + case 0: + return (kdb_frame->tf_r0); + case 1: + return (kdb_frame->tf_r1); + case 2: + return (kdb_frame->tf_r2); + case 3: + return (kdb_frame->tf_r3); + case 4: + return (kdb_frame->tf_r4); + case 5: + return (kdb_frame->tf_r5); + case 6: + return (kdb_frame->tf_r6); + case 7: + return (kdb_frame->tf_r7); + case 8: + return (kdb_frame->tf_r8); + case 9: + return (kdb_frame->tf_r9); + case 10: + return (kdb_frame->tf_r10); + case 11: + return (kdb_frame->tf_r11); + case 12: + return (kdb_frame->tf_r12); + case 13: + return (kdb_frame->tf_svc_sp); + case 14: + return (kdb_frame->tf_svc_lr); + case 15: + return (kdb_frame->tf_pc); + default: + panic("db_fetch_reg: botch"); + } +} + +u_int +branch_taken(u_int insn, db_addr_t pc) +{ + u_int addr, nregs; + + switch ((insn >> 24) & 0xf) { + case 0xa: /* b ... */ + case 0xb: /* bl ... */ + addr = ((insn << 2) & 0x03ffffff); + if (addr & 0x02000000) + addr |= 0xfc000000; + return (pc + 8 + addr); + case 0x7: /* ldr pc, [pc, reg, lsl #2] */ + addr = db_fetch_reg(insn & 0xf); + addr = pc + 8 + (addr << 2); + db_read_bytes(addr, 4, (char *)&addr); + return (addr); + case 0x1: /* mov pc, reg */ + addr = db_fetch_reg(insn & 0xf); + return (addr); + case 0x8: /* ldmxx reg, {..., pc} */ + case 0x9: + addr = db_fetch_reg((insn >> 16) & 0xf); + nregs = (insn & 0x5555) + ((insn >> 1) & 0x5555); + nregs = (nregs & 0x3333) + ((nregs >> 2) & 0x3333); + nregs = (nregs + (nregs >> 4)) & 0x0f0f; + nregs = (nregs + (nregs >> 8)) & 0x001f; + switch ((insn >> 23) & 0x3) { + case 0x0: /* ldmda */ + addr = addr - 0; + break; + case 0x1: /* ldmia */ + addr = addr + 0 + ((nregs - 1) << 2); + break; + case 0x2: /* ldmdb */ + addr = addr - 4; + break; + case 0x3: /* ldmib */ + addr = addr + 4 + ((nregs - 1) << 2); + break; + } + db_read_bytes(addr, 4, (char *)&addr); + return (addr); + default: + panic("branch_taken: botch"); + } +} diff --git a/sys/arm/arm/undefined.c b/sys/arm/arm/undefined.c index 0c8ea41..8632867 100644 --- a/sys/arm/arm/undefined.c +++ b/sys/arm/arm/undefined.c @@ -45,6 +45,8 @@ */ +#include "opt_ddb.h" + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -263,21 +265,13 @@ undefinedinstruction(trapframe_t *frame) if ((fault_code & FAULT_USER) == 0) { if (fault_instruction == KERNEL_BREAKPOINT) { #ifdef KDB - kdb_trap(0, 0, frame); + kdb_trap(T_BREAKPOINT, 0, frame); #else printf("No debugger in kernel.\n"); #endif - frame->tf_pc += 4; return; - } else { -#ifdef KDB - printf("Undefined instruction in kernel.\n"); - kdb_trap(0, 0, frame); -#else + } else panic("Undefined instruction in kernel.\n"); -#endif - } - } #ifdef FAST_FPE diff --git a/sys/arm/include/db_machdep.h b/sys/arm/include/db_machdep.h index f40daa5..0682311 100644 --- a/sys/arm/include/db_machdep.h +++ b/sys/arm/include/db_machdep.h @@ -34,8 +34,6 @@ #include <machine/trap.h> #include <machine/armreg.h> -#define BYTE_MSF (1) - #define T_BREAKPOINT (1) typedef vm_offset_t db_addr_t; typedef int db_expr_t; @@ -50,8 +48,7 @@ typedef int db_expr_t; kdb_frame->tf_pc += BKPT_SIZE; \ } while (0) -#define db_clear_single_step(regs) -#define db_set_single_step(regs) +#define SOFTWARE_SSTEP 1 #define IS_BREAKPOINT_TRAP(type, code) (type == T_BREAKPOINT) #define IS_WATCHPOINT_TRAP(type, code) (0) @@ -65,7 +62,8 @@ typedef int db_expr_t; /* mov pc, reg 0000000f register */ #define inst_return(ins) (((ins) & 0x0e108000) == 0x08108000 || \ - ((ins) & 0x0ff0fff0) == 0x01a0f000) + ((ins) & 0x0ff0fff0) == 0x01a0f000 || \ + ((ins) & 0x0ffffff0) == 0x012fff10) /* bx */ /* bl ... 00ffffff offset>>2 */ #define inst_call(ins) (((ins) & 0x0f000000) == 0x0b000000) @@ -74,14 +72,21 @@ typedef int db_expr_t; /* ldr pc, [pc, reg, lsl #2] 0000000f register */ +#define inst_branch(ins) (((ins) & 0x0f000000) == 0x0a000000 || \ + ((ins) & 0x0fdffff0) == 0x079ff100) #define inst_load(ins) (0) #define inst_store(ins) (0) +#define next_instr_address(pc, bd) ((bd) ? (pc) : ((pc) + INSN_SIZE)) + #define DB_SMALL_VALUE_MAX (0x7fffffff) #define DB_SMALL_VALUE_MIN (-0x40001) -#define DB_ELFSIZE 64 +#define DB_ELFSIZE 32 int db_validate_address(vm_offset_t); + +u_int branch_taken (u_int insn, u_int pc); + #endif /* !_MACHINE_DB_MACHDEP_H_ */ diff --git a/sys/arm/include/kdb.h b/sys/arm/include/kdb.h index ba8b3b9..0adf7e1 100644 --- a/sys/arm/include/kdb.h +++ b/sys/arm/include/kdb.h @@ -31,6 +31,7 @@ #include <machine/frame.h> #include <machine/psl.h> +#include <machine/cpufunc.h> static __inline void kdb_cpu_clear_singlestep(void) @@ -45,6 +46,7 @@ kdb_cpu_set_singlestep(void) static __inline void kdb_cpu_trap(int type, int code) { + cpu_idcache_wbinv_all(); } #endif /* _MACHINE_KDB_H_ */ |