1 /* $NetBSD: db_interface.c,v 1.9 2006/08/26 06:27:40 skrll Exp $ */ 2 3 /* $OpenBSD: db_interface.c,v 1.16 2001/03/22 23:31:45 mickey Exp $ */ 4 5 /* 6 * Copyright (c) 1999-2000 Michael Shalayeff 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Michael Shalayeff. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.9 2006/08/26 06:27:40 skrll Exp $"); 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 41 #include <machine/db_machdep.h> 42 #include <machine/frame.h> 43 #include <machine/cpufunc.h> 44 45 #include <ddb/db_access.h> 46 #include <ddb/db_command.h> 47 #include <ddb/db_output.h> 48 #include <ddb/db_run.h> 49 #include <ddb/db_sym.h> 50 #include <ddb/db_variables.h> 51 #include <ddb/db_extern.h> 52 #include <ddb/db_interface.h> 53 #include <ddb/ddbvar.h> 54 55 #include <dev/cons.h> 56 57 void kdbprinttrap(int, int); 58 59 extern label_t *db_recover; 60 extern int db_active; 61 extern char *trap_type[]; 62 extern int trap_types; 63 64 db_regs_t ddb_regs; 65 const struct db_variable db_regs[] = { 66 { "flags", (long *)&ddb_regs.tf_flags, FCN_NULL }, 67 { "r1", (long *)&ddb_regs.tf_r1, FCN_NULL }, 68 { "rp", (long *)&ddb_regs.tf_rp, FCN_NULL }, 69 { "r3", (long *)&ddb_regs.tf_r3, FCN_NULL }, 70 { "r4", (long *)&ddb_regs.tf_r4, FCN_NULL }, 71 { "r5", (long *)&ddb_regs.tf_r5, FCN_NULL }, 72 { "r6", (long *)&ddb_regs.tf_r6, FCN_NULL }, 73 { "r7", (long *)&ddb_regs.tf_r7, FCN_NULL }, 74 { "r8", (long *)&ddb_regs.tf_r8, FCN_NULL }, 75 { "r9", (long *)&ddb_regs.tf_r9, FCN_NULL }, 76 { "r10", (long *)&ddb_regs.tf_r10, FCN_NULL }, 77 { "r11", (long *)&ddb_regs.tf_r11, FCN_NULL }, 78 { "r12", (long *)&ddb_regs.tf_r12, FCN_NULL }, 79 { "r13", (long *)&ddb_regs.tf_r13, FCN_NULL }, 80 { "r14", (long *)&ddb_regs.tf_r14, FCN_NULL }, 81 { "r15", (long *)&ddb_regs.tf_r15, FCN_NULL }, 82 { "r16", (long *)&ddb_regs.tf_r16, FCN_NULL }, 83 { "r17", (long *)&ddb_regs.tf_r17, FCN_NULL }, 84 { "r18", (long *)&ddb_regs.tf_r18, FCN_NULL }, 85 { "t4", (long *)&ddb_regs.tf_t4, FCN_NULL }, 86 { "t3", (long *)&ddb_regs.tf_t3, FCN_NULL }, 87 { "t2", (long *)&ddb_regs.tf_t2, FCN_NULL }, 88 { "t1", (long *)&ddb_regs.tf_t1, FCN_NULL }, 89 { "arg3", (long *)&ddb_regs.tf_arg3, FCN_NULL }, 90 { "arg2", (long *)&ddb_regs.tf_arg2, FCN_NULL }, 91 { "arg1", (long *)&ddb_regs.tf_arg1, FCN_NULL }, 92 { "arg0", (long *)&ddb_regs.tf_arg0, FCN_NULL }, 93 { "dp", (long *)&ddb_regs.tf_dp, FCN_NULL }, 94 { "ret0", (long *)&ddb_regs.tf_ret0, FCN_NULL }, 95 { "ret1", (long *)&ddb_regs.tf_ret1, FCN_NULL }, 96 { "sp", (long *)&ddb_regs.tf_sp, FCN_NULL }, 97 { "r31", (long *)&ddb_regs.tf_r31, FCN_NULL }, 98 { "sar", (long *)&ddb_regs.tf_sar, FCN_NULL }, 99 100 { "eirr", (long *)&ddb_regs.tf_eirr, FCN_NULL }, 101 { "eiem", (long *)&ddb_regs.tf_eiem, FCN_NULL }, 102 { "iir", (long *)&ddb_regs.tf_iir, FCN_NULL }, 103 { "isr", (long *)&ddb_regs.tf_isr, FCN_NULL }, 104 { "ior", (long *)&ddb_regs.tf_ior, FCN_NULL }, 105 { "ipsw", (long *)&ddb_regs.tf_ipsw, FCN_NULL }, 106 { "iisqh", (long *)&ddb_regs.tf_iisq_head, FCN_NULL }, 107 { "iioqh", (long *)&ddb_regs.tf_iioq_head, FCN_NULL }, 108 { "iisqt", (long *)&ddb_regs.tf_iisq_tail, FCN_NULL }, 109 { "iioqt", (long *)&ddb_regs.tf_iioq_tail, FCN_NULL }, 110 111 { "sr0", (long *)&ddb_regs.tf_sr0, FCN_NULL }, 112 { "sr1", (long *)&ddb_regs.tf_sr1, FCN_NULL }, 113 { "sr2", (long *)&ddb_regs.tf_sr2, FCN_NULL }, 114 { "sr3", (long *)&ddb_regs.tf_sr3, FCN_NULL }, 115 { "sr4", (long *)&ddb_regs.tf_sr4, FCN_NULL }, 116 { "sr5", (long *)&ddb_regs.tf_sr5, FCN_NULL }, 117 { "sr6", (long *)&ddb_regs.tf_sr6, FCN_NULL }, 118 { "sr7", (long *)&ddb_regs.tf_sr7, FCN_NULL }, 119 120 { "pidr1", (long *)&ddb_regs.tf_pidr1, FCN_NULL }, 121 { "pidr2", (long *)&ddb_regs.tf_pidr2, FCN_NULL }, 122 #ifdef pbably_not_worth_it 123 { "pidr3", (long *)&ddb_regs.tf_pidr3, FCN_NULL }, 124 { "pidr4", (long *)&ddb_regs.tf_pidr4, FCN_NULL }, 125 #endif 126 127 { "hptm", (long *)&ddb_regs.tf_hptm, FCN_NULL }, 128 { "vtop", (long *)&ddb_regs.tf_vtop, FCN_NULL }, 129 { "cr28", (long *)&ddb_regs.tf_cr28, FCN_NULL }, 130 { "cr30", (long *)&ddb_regs.tf_cr30, FCN_NULL }, 131 }; 132 const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 133 int db_active = 0; 134 135 void 136 Debugger(void) 137 { 138 __asm volatile ("break %0, %1" 139 :: "i" (HPPA_BREAK_KERNEL), "i" (HPPA_BREAK_KGDB)); 140 } 141 142 /* 143 * Print trap reason. 144 */ 145 void 146 kdbprinttrap(int type, int code) 147 { 148 db_printf("kernel: "); 149 if (type >= trap_types || type < 0) 150 db_printf("type %d", type); 151 else 152 db_printf("%s", trap_type[type]); 153 db_printf(" trap, code=%x\n", code); 154 } 155 156 /* 157 * kdb_trap - field a BPT trap 158 */ 159 int 160 kdb_trap(int type, int code, db_regs_t *regs) 161 { 162 int s; 163 164 switch (type) { 165 case T_RECOVERY: 166 case T_IBREAK: 167 case T_DBREAK: 168 case -1: 169 break; 170 default: 171 if (!db_onpanic && db_recover == 0) 172 return 0; 173 174 kdbprinttrap(type, code); 175 if (db_recover != 0) { 176 db_error("Caught exception in DDB; continuing...\n"); 177 /* NOT REACHED */ 178 } 179 } 180 181 /* XXX Should switch to kdb`s own stack here. */ 182 183 ddb_regs = *regs; 184 185 s = splhigh(); 186 db_active++; 187 cnpollc(TRUE); 188 db_trap(type, code); 189 cnpollc(FALSE); 190 db_active--; 191 splx(s); 192 193 *regs = ddb_regs; 194 return (1); 195 } 196 197 /* 198 * Validate an address for use as a breakpoint. 199 * Any address is allowed for now. 200 */ 201 int 202 db_valid_breakpoint(db_addr_t addr) 203 { 204 return (1); 205 } 206 207 void 208 db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, 209 const char *modif, void (*pr)(const char *, ...)) 210 { 211 register_t *fp, pc, rp, nargs, *argp; 212 db_sym_t sym; 213 db_expr_t off; 214 const char *name; 215 char **argnp, *argnames[HPPA_FRAME_NARGS]; 216 217 if (count < 0) 218 count = 65536; 219 220 if (!have_addr) { 221 fp = (register_t *)ddb_regs.tf_r3; 222 pc = ddb_regs.tf_iioq_head; 223 rp = ddb_regs.tf_rp; 224 } else { 225 fp = (register_t *)addr; 226 pc = 0; 227 rp = ((register_t *)fp)[-5]; 228 } 229 230 #ifdef DDB_DEBUG 231 pr(">> %x, %x, %x\t", fp, pc, rp); 232 #endif 233 while (fp && count--) { 234 235 if (USERMODE(pc)) 236 return; 237 238 sym = db_search_symbol(pc, DB_STGY_ANY, &off); 239 db_symbol_values (sym, &name, NULL); 240 241 pr("%s(", name); 242 243 /* args */ 244 nargs = HPPA_FRAME_NARGS; 245 argnp = NULL; 246 if (db_sym_numargs(sym, &nargs, argnames)) 247 argnp = argnames; 248 else 249 nargs = 4; 250 /* 251 * XXX first four args are passed on registers, and may not 252 * be stored on stack, dunno how to recover their values yet 253 */ 254 for (argp = &fp[-9]; nargs--; argp--) { 255 if (argnp) 256 pr("%s=", *argnp++); 257 pr("%lx%s", db_get_value((int)argp, 4, FALSE), 258 nargs? ",":""); 259 } 260 pr(") at "); 261 db_printsym(pc, DB_STGY_PROC, pr); 262 pr("\n"); 263 264 /* TODO: print locals */ 265 266 /* next frame */ 267 pc = rp; 268 rp = fp[-5]; 269 270 /* if a terminal frame and not a start of a page 271 * then skip the trapframe and the terminal frame */ 272 if (!fp[0]) { 273 struct trapframe *tf; 274 275 tf = (struct trapframe *)((char *)fp - sizeof(*tf)); 276 277 if (tf->tf_flags & TFF_SYS) 278 pr("-- syscall #%d(%x, %x, %x, %x, ...)\n", 279 tf->tf_t1, tf->tf_arg0, tf->tf_arg1, 280 tf->tf_arg2, tf->tf_arg3); 281 else 282 pr("-- trap #%d%s\n", tf->tf_flags & 0x3f, 283 (tf->tf_flags & T_USER)? " from user" : ""); 284 285 if (!(tf->tf_flags & TFF_LAST)) { 286 fp = (register_t *)tf->tf_r3; 287 pc = tf->tf_iioq_head; 288 rp = tf->tf_rp; 289 } else 290 fp = 0; 291 } else 292 fp = (register_t *)fp[0]; 293 #ifdef DDB_DEBUG 294 pr(">> %x, %x, %x\t", fp, pc, rp); 295 #endif 296 } 297 298 if (count && pc) { 299 db_printsym(pc, DB_STGY_XTRN, pr); 300 pr(":\n"); 301 } 302 } 303