db_trace.c revision 104435
1/* $FreeBSD: head/sys/powerpc/powerpc/db_trace.c 104435 2002-10-04 01:19:18Z grehan $ */ 2/* $NetBSD: db_trace.c,v 1.20 2002/05/13 20:30:09 matt Exp $ */ 3/* $OpenBSD: db_trace.c,v 1.3 1997/03/21 02:10:48 niklas Exp $ */ 4 5/* 6 * Mach Operating System 7 * Copyright (c) 1992 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 Mellon 28 * the rights to redistribute these changes. 29 */ 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/proc.h> 34#include <sys/user.h> 35 36#include <vm/vm.h> 37#include <vm/pmap.h> 38#include <vm/vm_extern.h> 39 40#include <machine/db_machdep.h> 41#include <machine/spr.h> 42#include <machine/trap.h> 43 44#include <ddb/ddb.h> 45#include <ddb/db_access.h> 46#include <ddb/db_sym.h> 47#include <ddb/db_variables.h> 48 49struct db_variable db_regs[] = { 50 { "r0", &ddb_regs.r[0], FCN_NULL }, 51 { "r1", &ddb_regs.r[1], FCN_NULL }, 52 { "r2", &ddb_regs.r[2], FCN_NULL }, 53 { "r3", &ddb_regs.r[3], FCN_NULL }, 54 { "r4", &ddb_regs.r[4], FCN_NULL }, 55 { "r5", &ddb_regs.r[5], FCN_NULL }, 56 { "r6", &ddb_regs.r[6], FCN_NULL }, 57 { "r7", &ddb_regs.r[7], FCN_NULL }, 58 { "r8", &ddb_regs.r[8], FCN_NULL }, 59 { "r9", &ddb_regs.r[9], FCN_NULL }, 60 { "r10", &ddb_regs.r[10], FCN_NULL }, 61 { "r11", &ddb_regs.r[11], FCN_NULL }, 62 { "r12", &ddb_regs.r[12], FCN_NULL }, 63 { "r13", &ddb_regs.r[13], FCN_NULL }, 64 { "r14", &ddb_regs.r[14], FCN_NULL }, 65 { "r15", &ddb_regs.r[15], FCN_NULL }, 66 { "r16", &ddb_regs.r[16], FCN_NULL }, 67 { "r17", &ddb_regs.r[17], FCN_NULL }, 68 { "r18", &ddb_regs.r[18], FCN_NULL }, 69 { "r19", &ddb_regs.r[19], FCN_NULL }, 70 { "r20", &ddb_regs.r[20], FCN_NULL }, 71 { "r21", &ddb_regs.r[21], FCN_NULL }, 72 { "r22", &ddb_regs.r[22], FCN_NULL }, 73 { "r23", &ddb_regs.r[23], FCN_NULL }, 74 { "r24", &ddb_regs.r[24], FCN_NULL }, 75 { "r25", &ddb_regs.r[25], FCN_NULL }, 76 { "r26", &ddb_regs.r[26], FCN_NULL }, 77 { "r27", &ddb_regs.r[27], FCN_NULL }, 78 { "r28", &ddb_regs.r[28], FCN_NULL }, 79 { "r29", &ddb_regs.r[29], FCN_NULL }, 80 { "r30", &ddb_regs.r[30], FCN_NULL }, 81 { "r31", &ddb_regs.r[31], FCN_NULL }, 82 { "iar", &ddb_regs.iar, FCN_NULL }, 83 { "msr", &ddb_regs.msr, FCN_NULL }, 84 { "lr", &ddb_regs.lr, FCN_NULL }, 85 { "ctr", &ddb_regs.ctr, FCN_NULL }, 86 { "cr", &ddb_regs.cr, FCN_NULL }, 87 { "xer", &ddb_regs.xer, FCN_NULL }, 88#ifdef PPC_IBM4XX 89 { "dear", &ddb_regs.dear, FCN_NULL }, 90 { "esr", &ddb_regs.esr, FCN_NULL }, 91 { "pid", &ddb_regs.pid, FCN_NULL }, 92#endif 93}; 94struct db_variable *db_eregs = db_regs + sizeof (db_regs)/sizeof (db_regs[0]); 95 96extern int trapexit[]; 97extern int end[]; 98 99/* 100 * Frame tracing. 101 */ 102static void 103db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, 104 char *modif, void (*pr)(const char *, ...)) 105{ 106 db_addr_t frame, lr, caller, *args; 107 db_addr_t fakeframe[2]; 108 db_expr_t diff; 109 c_db_sym_t sym; 110 const char *symname; 111 boolean_t kernel_only = TRUE; 112 boolean_t trace_thread = FALSE; 113 boolean_t full = FALSE; 114 115 { 116 register char *cp = modif; 117 register char c; 118 119 while ((c = *cp++) != 0) { 120 if (c == 't') 121 trace_thread = TRUE; 122 if (c == 'u') 123 kernel_only = FALSE; 124 if (c == 'f') 125 full = TRUE; 126 } 127 } 128 129 if (have_addr) { 130#if 0 131 if (trace_thread) { 132 struct proc *p; 133 struct user *u; 134 135 (*pr)("trace: pid %d ", (int)addr); 136 p = pfind(addr); 137 if (p == NULL) { 138 (*pr)("not found\n"); 139 return; 140 } 141 if (!(p->p_flag&P_INMEM)) { 142 (*pr)("swapped out\n"); 143 return; 144 } 145 u = p->p_addr; 146 frame = (db_addr_t)u->u_pcb.pcb_sp; 147 (*pr)("at %p\n", frame); 148 } else 149#endif 150 frame = (db_addr_t)addr; 151 } else { 152 frame = (db_addr_t)ddb_regs.r[1]; 153 } 154 for (;;) { 155 if (frame < PAGE_SIZE) 156 break; 157#ifdef PPC_MPC6XX 158 if (kernel_only && 159 ((frame > (db_addr_t) end && 160 frame < VM_MIN_KERNEL_ADDRESS) || 161 frame >= VM_MAX_KERNEL_ADDRESS)) 162 break; 163#endif 164 frame = *(db_addr_t *)frame; 165 next_frame: 166 args = (db_addr_t *)(frame + 8); 167 if (frame < PAGE_SIZE) 168 break; 169#ifdef PPC_MPC6XX 170 if (kernel_only && 171 ((frame > (db_addr_t) end && 172 frame < VM_MIN_KERNEL_ADDRESS) || 173 frame >= VM_MAX_KERNEL_ADDRESS)) 174 break; 175#endif 176 if (count-- == 0) 177 break; 178 179 lr = *(db_addr_t *)(frame + 4) - 4; 180 if ((lr & 3) || (lr < 0x100)) { 181 (*pr)("saved LR(0x%x) is invalid.", lr); 182 break; 183 } 184 if ((caller = (db_addr_t)vtophys(lr)) == 0) 185 caller = lr; 186 187 if (frame != (db_addr_t) fakeframe) { 188 (*pr)("0x%08lx: ", frame); 189 } else { 190 (*pr)(" <?> : "); 191 } 192 if (caller + 4 == (db_addr_t) &trapexit) { 193 const char *trapstr; 194 struct trapframe *tf = (struct trapframe *) (frame+8); 195 (*pr)("%s ", tf->srr1 & PSL_PR ? "user" : "kernel"); 196 switch (tf->exc) { 197 case EXC_DSI: 198#ifdef PPC_MPC6XX 199 (*pr)("DSI %s trap @ %#x by ", 200 tf->dsisr & DSISR_STORE ? "write" : "read", 201 tf->dar); 202#endif 203#ifdef PPC_IBM4XX 204 (*pr)("DSI %s trap @ %#x by ", 205 tf->esr & ESR_DST ? "write" : "read", 206 tf->dear); 207#endif 208 goto print_trap; 209 case EXC_ISI: trapstr = "ISI"; break; 210 case EXC_PGM: trapstr = "PGM"; break; 211 case EXC_SC: trapstr = "SC"; break; 212 case EXC_EXI: trapstr = "EXI"; break; 213 case EXC_MCHK: trapstr = "MCHK"; break; 214 case EXC_VEC: trapstr = "VEC"; break; 215 case EXC_FPU: trapstr = "FPU"; break; 216 case EXC_FPA: trapstr = "FPA"; break; 217 case EXC_DECR: trapstr = "DECR"; break; 218 case EXC_ALI: trapstr = "ALI"; break; 219 case EXC_BPT: trapstr = "BPT"; break; 220 case EXC_TRC: trapstr = "TRC"; break; 221 case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break; 222 case EXC_PERF: trapstr = "PERF"; break; 223 case EXC_SMI: trapstr = "SMI"; break; 224 case EXC_RST: trapstr = "RST"; break; 225 default: trapstr = NULL; break; 226 } 227 if (trapstr != NULL) { 228 (*pr)("%s trap by ", trapstr); 229 } else { 230 (*pr)("trap %#x by ", tf->exc); 231 } 232 print_trap: 233 lr = (db_addr_t) tf->srr0; 234 if ((caller = (db_addr_t)vtophys(lr)) == 0) 235 caller = lr; 236 diff = 0; 237 symname = NULL; 238 sym = db_search_symbol(caller, DB_STGY_ANY, &diff); 239 db_symbol_values(sym, &symname, 0); 240 if (symname == NULL || !strcmp(symname, "end")) { 241 (*pr)("%p: srr1=%#x\n", caller, tf->srr1); 242 } else { 243 (*pr)("%s+%x: srr1=%#x\n", symname, diff, 244 tf->srr1); 245 } 246 (*pr)("%-10s r1=%#x cr=%#x xer=%#x ctr=%#x", 247 "", tf->fixreg[1], tf->cr, tf->xer, tf->ctr); 248#ifdef PPC_MPC6XX 249 if (tf->exc == EXC_DSI) 250 (*pr)(" dsisr=%#x", tf->dsisr); 251#endif 252#ifdef PPC_IBM4XX 253 if (tf->exc == EXC_DSI) 254 (*pr)(" dear=%#x", tf->dear); 255 (*pr)(" esr=%#x pid=%#x", tf->esr, tf->pid); 256#endif 257 (*pr)("\n"); 258 fakeframe[0] = (db_addr_t) tf->fixreg[1]; 259 fakeframe[1] = (db_addr_t) tf->lr; 260 frame = (db_addr_t) fakeframe; 261 if (kernel_only && (tf->srr1 & PSL_PR)) 262 break; 263 goto next_frame; 264 } 265 266 diff = 0; 267 symname = NULL; 268 sym = db_search_symbol(caller, DB_STGY_ANY, &diff); 269 db_symbol_values(sym, &symname, 0); 270 if (symname == NULL || !strcmp(symname, "end")) 271 (*pr)("at %p", caller); 272 else 273 (*pr)("at %s+%#x", symname, diff); 274 if (full) 275 /* Print all the args stored in that stackframe. */ 276 (*pr)("(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)", 277 args[0], args[1], args[2], args[3], 278 args[4], args[5], args[6], args[7]); 279 (*pr)("\n"); 280 } 281} 282 283void 284db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, 285 char *modif) 286{ 287 288 db_stack_trace_print(addr, have_addr, count, modif, db_printf); 289} 290 291void 292db_print_backtrace(void) 293{ 294} 295