1 /* $NetBSD: db_interface.c,v 1.33 2003/08/25 04:51:10 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Scott K. Stevens 5 * 6 * Mach Operating System 7 * Copyright (c) 1991,1990 Carnegie Mellon University 8 * All Rights Reserved. 9 * 10 * Permission to use, copy, modify and distribute this software and its 11 * documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 * 30 * From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) 31 */ 32 33 /* 34 * Interface to new debugger. 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 #include "opt_ddb.h" 40 41 #include <sys/param.h> 42 #include <sys/proc.h> 43 #include <sys/reboot.h> 44 #include <sys/systm.h> /* just for boothowto */ 45 #include <sys/exec.h> 46 47 #include <vm/vm.h> 48 #include <vm/pmap.h> 49 #include <vm/vm_map.h> 50 #include <vm/vm_extern.h> 51 52 #include <machine/db_machdep.h> 53 #include <machine/katelib.h> 54 #include <machine/vmparam.h> 55 #include <machine/cpu.h> 56 57 #include <ddb/ddb.h> 58 #include <ddb/db_access.h> 59 #include <ddb/db_command.h> 60 #include <ddb/db_output.h> 61 #include <ddb/db_variables.h> 62 #include <ddb/db_sym.h> 63 #include <sys/cons.h> 64 65 static int nil = 0; 66 67 int db_access_und_sp (struct db_variable *, db_expr_t *, int); 68 int db_access_abt_sp (struct db_variable *, db_expr_t *, int); 69 int db_access_irq_sp (struct db_variable *, db_expr_t *, int); 70 71 #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 72 struct db_variable db_regs[] = { 73 { "spsr", DB_OFFSET(tf_spsr), FCN_NULL, }, 74 { "r0", DB_OFFSET(tf_r0), FCN_NULL, }, 75 { "r1", DB_OFFSET(tf_r1), FCN_NULL, }, 76 { "r2", DB_OFFSET(tf_r2), FCN_NULL, }, 77 { "r3", DB_OFFSET(tf_r3), FCN_NULL, }, 78 { "r4", DB_OFFSET(tf_r4), FCN_NULL, }, 79 { "r5", DB_OFFSET(tf_r5), FCN_NULL, }, 80 { "r6", DB_OFFSET(tf_r6), FCN_NULL, }, 81 { "r7", DB_OFFSET(tf_r7), FCN_NULL, }, 82 { "r8", DB_OFFSET(tf_r8), FCN_NULL, }, 83 { "r9", DB_OFFSET(tf_r9), FCN_NULL, }, 84 { "r10", DB_OFFSET(tf_r10), FCN_NULL, }, 85 { "r11", DB_OFFSET(tf_r11), FCN_NULL, }, 86 { "r12", DB_OFFSET(tf_r12), FCN_NULL, }, 87 { "usr_sp", DB_OFFSET(tf_usr_sp), FCN_NULL, }, 88 { "usr_lr", DB_OFFSET(tf_usr_lr), FCN_NULL, }, 89 { "svc_sp", DB_OFFSET(tf_svc_sp), FCN_NULL, }, 90 { "svc_lr", DB_OFFSET(tf_svc_lr), FCN_NULL, }, 91 { "pc", DB_OFFSET(tf_pc), FCN_NULL, }, 92 { "und_sp", &nil, db_access_und_sp, }, 93 { "abt_sp", &nil, db_access_abt_sp, }, 94 { "irq_sp", &nil, db_access_irq_sp, }, 95 }; 96 97 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 98 99 int 100 db_access_und_sp(struct db_variable *vp, db_expr_t *valp, int rw) 101 { 102 103 if (rw == DB_VAR_GET) 104 *valp = get_stackptr(PSR_UND32_MODE); 105 return(0); 106 } 107 108 int 109 db_access_abt_sp(struct db_variable *vp, db_expr_t *valp, int rw) 110 { 111 112 if (rw == DB_VAR_GET) 113 *valp = get_stackptr(PSR_ABT32_MODE); 114 return(0); 115 } 116 117 int 118 db_access_irq_sp(struct db_variable *vp, db_expr_t *valp, int rw) 119 { 120 121 if (rw == DB_VAR_GET) 122 *valp = get_stackptr(PSR_IRQ32_MODE); 123 return(0); 124 } 125 126 void 127 db_show_mdpcpu(struct pcpu *pc) 128 { 129 } 130 int 131 db_validate_address(vm_offset_t addr) 132 { 133 struct proc *p = curproc; 134 struct pmap *pmap; 135 136 if (!p || !p->p_vmspace || !p->p_vmspace->vm_map.pmap || 137 #ifndef ARM32_NEW_VM_LAYOUT 138 addr >= VM_MAXUSER_ADDRESS 139 #else 140 addr >= VM_MIN_KERNEL_ADDRESS 141 #endif 142 ) 143 pmap = pmap_kernel(); 144 else 145 pmap = p->p_vmspace->vm_map.pmap; 146 147 return (pmap_extract(pmap, addr) == FALSE); 148 } 149 150 /* 151 * Read bytes from kernel address space for debugger. 152 */ 153 int 154 db_read_bytes(addr, size, data) 155 vm_offset_t addr; 156 size_t size; 157 char *data; 158 { 159 char *src = (char *)addr; 160 161 if (db_validate_address((u_int)src)) { 162 db_printf("address %p is invalid\n", src); 163 return (-1); 164 } 165 166 if (size == 4 && (addr & 3) == 0 && ((uintptr_t)data & 3) == 0) { 167 *((int*)data) = *((int*)src); 168 return (0); 169 } 170 171 if (size == 2 && (addr & 1) == 0 && ((uintptr_t)data & 1) == 0) { 172 *((short*)data) = *((short*)src); 173 return (0); 174 } 175 176 while (size-- > 0) { 177 if (db_validate_address((u_int)src)) { 178 db_printf("address %p is invalid\n", src); 179 return (-1); 180 } 181 *data++ = *src++; 182 } 183 return (0); 184 } 185 186 /* 187 * Write bytes to kernel address space for debugger. 188 */ 189 int 190 db_write_bytes(vm_offset_t addr, size_t size, char *data) 191 { 192 char *dst; 193 size_t loop; 194 195 /* If any part is in kernel text, use db_write_text() */ 196 if (addr >= (vm_offset_t) btext && addr < (vm_offset_t) etext) { 197 return (-1); 198 } 199 200 dst = (char *)addr; 201 if (db_validate_address((u_int)dst)) { 202 db_printf("address %p is invalid\n", dst); 203 return (0); 204 } 205 206 if (size == 4 && (addr & 3) == 0 && ((uintptr_t)data & 3) == 0) 207 *((int*)dst) = *((int*)data); 208 else 209 if (size == 2 && (addr & 1) == 0 && ((uintptr_t)data & 1) == 0) 210 *((short*)dst) = *((short*)data); 211 else { 212 loop = size; 213 while (loop-- > 0) { 214 if (db_validate_address((u_int)dst)) { 215 db_printf("address %p is invalid\n", dst); 216 return (-1); 217 } 218 *dst++ = *data++; 219 } 220 } 221 222 /* make sure the caches and memory are in sync */ 223 cpu_icache_sync_range(addr, size); 224 225 /* In case the current page tables have been modified ... */ 226 cpu_tlb_flushID(); 227 cpu_cpwait(); 228 return (0); 229 } 230 231 232 233