db_trace.c revision 236141
1191762Simp/* $FreeBSD: head/sys/powerpc/powerpc/db_trace.c 236141 2012-05-27 10:25:20Z raj $ */ 2191762Simp/* $NetBSD: db_trace.c,v 1.20 2002/05/13 20:30:09 matt Exp $ */ 3191762Simp/* $OpenBSD: db_trace.c,v 1.3 1997/03/21 02:10:48 niklas Exp $ */ 4191762Simp 5191762Simp/*- 6191762Simp * Mach Operating System 7191762Simp * Copyright (c) 1992 Carnegie Mellon University 8191762Simp * All Rights Reserved. 9191762Simp * 10191762Simp * Permission to use, copy, modify and distribute this software and its 11191762Simp * documentation is hereby granted, provided that both the copyright 12191762Simp * notice and this permission notice appear in all copies of the 13191762Simp * software, derivative works or modified versions, and any portions 14191762Simp * thereof, and that both notices appear in supporting documentation. 15191762Simp * 16191762Simp * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17191762Simp * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 18191762Simp * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19191762Simp * 20191762Simp * Carnegie Mellon requests users of this software to return to 21191762Simp * 22191762Simp * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23191762Simp * School of Computer Science 24191762Simp * Carnegie Mellon University 25191762Simp * Pittsburgh PA 15213-3890 26191762Simp * 27191762Simp * any improvements or extensions that they make and grant Carnegie Mellon 28191762Simp * the rights to redistribute these changes. 29191762Simp */ 30191762Simp 31191762Simp#include <sys/param.h> 32191762Simp#include <sys/systm.h> 33191762Simp#include <sys/kdb.h> 34191762Simp#include <sys/proc.h> 35191762Simp#include <sys/stack.h> 36191762Simp 37191762Simp#include <vm/vm.h> 38191762Simp#include <vm/pmap.h> 39191762Simp#include <vm/vm_extern.h> 40191762Simp 41191762Simp#include <machine/db_machdep.h> 42191762Simp#include <machine/pcb.h> 43191762Simp#include <machine/spr.h> 44191762Simp#include <machine/stack.h> 45191762Simp#include <machine/trap.h> 46191762Simp 47191762Simp#include <ddb/ddb.h> 48191762Simp#include <ddb/db_access.h> 49191762Simp#include <ddb/db_sym.h> 50191762Simp#include <ddb/db_variables.h> 51191762Simp 52191762Simpstatic db_varfcn_t db_frame; 53191762Simp 54191762Simp#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 55191762Simp 56191762Simp#ifdef __powerpc64__ 57191762Simp#define CALLOFFSET 8 /* Include TOC reload slot */ 58191762Simp#else 59191762Simp#define CALLOFFSET 4 60191762Simp#endif 61191762Simp 62191762Simpstruct db_variable db_regs[] = { 63191762Simp { "r0", DB_OFFSET(fixreg[0]), db_frame }, 64191762Simp { "r1", DB_OFFSET(fixreg[1]), db_frame }, 65191762Simp { "r2", DB_OFFSET(fixreg[2]), db_frame }, 66191762Simp { "r3", DB_OFFSET(fixreg[3]), db_frame }, 67191762Simp { "r4", DB_OFFSET(fixreg[4]), db_frame }, 68191762Simp { "r5", DB_OFFSET(fixreg[5]), db_frame }, 69191762Simp { "r6", DB_OFFSET(fixreg[6]), db_frame }, 70191762Simp { "r7", DB_OFFSET(fixreg[7]), db_frame }, 71191762Simp { "r8", DB_OFFSET(fixreg[8]), db_frame }, 72191762Simp { "r9", DB_OFFSET(fixreg[9]), db_frame }, 73191762Simp { "r10", DB_OFFSET(fixreg[10]), db_frame }, 74191762Simp { "r11", DB_OFFSET(fixreg[11]), db_frame }, 75191762Simp { "r12", DB_OFFSET(fixreg[12]), db_frame }, 76191762Simp { "r13", DB_OFFSET(fixreg[13]), db_frame }, 77191762Simp { "r14", DB_OFFSET(fixreg[14]), db_frame }, 78191762Simp { "r15", DB_OFFSET(fixreg[15]), db_frame }, 79191762Simp { "r16", DB_OFFSET(fixreg[16]), db_frame }, 80191762Simp { "r17", DB_OFFSET(fixreg[17]), db_frame }, 81191762Simp { "r18", DB_OFFSET(fixreg[18]), db_frame }, 82191762Simp { "r19", DB_OFFSET(fixreg[19]), db_frame }, 83191762Simp { "r20", DB_OFFSET(fixreg[20]), db_frame }, 84191762Simp { "r21", DB_OFFSET(fixreg[21]), db_frame }, 85191762Simp { "r22", DB_OFFSET(fixreg[22]), db_frame }, 86191762Simp { "r23", DB_OFFSET(fixreg[23]), db_frame }, 87191762Simp { "r24", DB_OFFSET(fixreg[24]), db_frame }, 88191762Simp { "r25", DB_OFFSET(fixreg[25]), db_frame }, 89191762Simp { "r26", DB_OFFSET(fixreg[26]), db_frame }, 90191762Simp { "r27", DB_OFFSET(fixreg[27]), db_frame }, 91191762Simp { "r28", DB_OFFSET(fixreg[28]), db_frame }, 92191762Simp { "r29", DB_OFFSET(fixreg[29]), db_frame }, 93191762Simp { "r30", DB_OFFSET(fixreg[30]), db_frame }, 94191762Simp { "r31", DB_OFFSET(fixreg[31]), db_frame }, 95191762Simp { "srr0", DB_OFFSET(srr0), db_frame }, 96191762Simp { "srr1", DB_OFFSET(srr1), db_frame }, 97191762Simp { "lr", DB_OFFSET(lr), db_frame }, 98191762Simp { "ctr", DB_OFFSET(ctr), db_frame }, 99191762Simp { "cr", DB_OFFSET(cr), db_frame }, 100191762Simp { "xer", DB_OFFSET(xer), db_frame }, 101191762Simp#ifdef AIM 102191762Simp { "dar", DB_OFFSET(cpu.aim.dar), db_frame }, 103191762Simp { "dsisr", DB_OFFSET(cpu.aim.dsisr), db_frame }, 104191762Simp#endif 105191762Simp#if defined(BOOKE) 106191762Simp { "dear", DB_OFFSET(cpu.booke.dear), db_frame }, 107191762Simp { "esr", DB_OFFSET(cpu.booke.esr), db_frame }, 108191762Simp#endif 109191762Simp}; 110191762Simpstruct db_variable *db_eregs = db_regs + sizeof (db_regs)/sizeof (db_regs[0]); 111191762Simp 112191762Simp/* 113191762Simp * register variable handling 114191762Simp */ 115191762Simpstatic int 116191762Simpdb_frame(struct db_variable *vp, db_expr_t *valuep, int op) 117191762Simp{ 118191762Simp register_t *reg; 119191762Simp 120191762Simp if (kdb_frame == NULL) 121191762Simp return (0); 122191762Simp reg = (register_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep); 123191762Simp if (op == DB_VAR_GET) 124191762Simp *valuep = *reg; 125191762Simp else 126191762Simp *reg = *valuep; 127191762Simp return (1); 128191762Simp} 129191762Simp 130191762Simp 131191762Simp/* 132191762Simp * Frame tracing. 133191762Simp */ 134191762Simpstatic int 135191762Simpdb_backtrace(struct thread *td, db_addr_t fp, int count) 136191762Simp{ 137191762Simp db_addr_t stackframe, lr, *args; 138191762Simp db_expr_t diff; 139191762Simp c_db_sym_t sym; 140191762Simp const char *symname; 141191762Simp boolean_t kernel_only = TRUE; 142191762Simp boolean_t full = FALSE; 143191762Simp 144191762Simp#if 0 145191762Simp { 146191762Simp register char *cp = modif; 147191762Simp register char c; 148191762Simp 149191762Simp while ((c = *cp++) != 0) { 150191762Simp if (c == 't') 151191762Simp trace_thread = TRUE; 152191762Simp if (c == 'u') 153191762Simp kernel_only = FALSE; 154191762Simp if (c == 'f') 155191762Simp full = TRUE; 156191762Simp } 157191762Simp } 158191762Simp#endif 159191762Simp 160191762Simp stackframe = fp; 161191762Simp 162191762Simp while (!db_pager_quit) { 163191762Simp if (stackframe < PAGE_SIZE) 164191762Simp break; 165191762Simp 166191762Simp /* 167191762Simp * Locate the next frame by grabbing the backchain ptr 168191762Simp * from frame[0] 169191762Simp */ 170191762Simp stackframe = *(db_addr_t *)stackframe; 171191762Simp 172191762Simp next_frame: 173191762Simp #ifdef __powerpc64__ 174191762Simp /* The saved arg values start at frame[6] */ 175191762Simp args = (db_addr_t *)(stackframe + 48); 176191762Simp #else 177191762Simp /* The saved arg values start at frame[2] */ 178191762Simp args = (db_addr_t *)(stackframe + 8); 179191762Simp #endif 180191762Simp 181191762Simp if (stackframe < PAGE_SIZE) 182191762Simp break; 183191762Simp 184191762Simp if (count-- == 0) 185191762Simp break; 186191762Simp 187191762Simp /* 188191762Simp * Extract link register from frame and subtract 189191762Simp * 4 to convert into calling address (as opposed to 190191762Simp * return address) 191191762Simp */ 192191762Simp #ifdef __powerpc64__ 193191762Simp lr = *(db_addr_t *)(stackframe + 16) - 4; 194191762Simp #else 195191762Simp lr = *(db_addr_t *)(stackframe + 4) - 4; 196191762Simp #endif 197191762Simp if ((lr & 3) || (lr < 0x100)) { 198191762Simp db_printf("saved LR(0x%zx) is invalid.", lr); 199191762Simp break; 200191762Simp } 201191762Simp 202191762Simp #ifdef __powerpc64__ 203191762Simp db_printf("0x%016lx: ", stackframe); 204191762Simp #else 205191762Simp db_printf("0x%08x: ", stackframe); 206191762Simp #endif 207191762Simp 208191762Simp /* 209191762Simp * The trap code labels the return addresses from the 210191762Simp * call to C code as 'trapexit' and 'asttrapexit. Use this 211191762Simp * to determine if the callframe has to traverse a saved 212191762Simp * trap context 213191762Simp */ 214191762Simp if ((lr + CALLOFFSET == (db_addr_t) &trapexit) || 215191762Simp (lr + CALLOFFSET == (db_addr_t) &asttrapexit)) { 216191762Simp const char *trapstr; 217191762Simp struct trapframe *tf = (struct trapframe *)(args); 218191762Simp db_printf("%s ", tf->srr1 & PSL_PR ? "user" : "kernel"); 219191762Simp switch (tf->exc) { 220191762Simp case EXC_DSI: 221191762Simp /* XXX take advantage of the union. */ 222191762Simp db_printf("DSI %s trap @ %#zx by ", 223191762Simp (tf->cpu.aim.dsisr & DSISR_STORE) ? "write" 224191762Simp : "read", tf->cpu.aim.dar); 225191762Simp goto print_trap; 226191762Simp case EXC_ALI: 227191762Simp /* XXX take advantage of the union. */ 228191762Simp db_printf("ALI trap @ %#zx (xSR %#x) ", 229191762Simp tf->cpu.aim.dar, 230191762Simp (uint32_t)tf->cpu.aim.dsisr); 231191762Simp goto print_trap; 232191762Simp#ifdef __powerpc64__ 233191762Simp case EXC_DSE: 234191762Simp db_printf("DSE trap @ %#zx by ", 235191762Simp tf->cpu.aim.dar); 236191762Simp goto print_trap; 237191762Simp case EXC_ISE: 238191762Simp db_printf("ISE trap @ %#zx by ", tf->srr0); 239191762Simp goto print_trap; 240191762Simp#endif 241191762Simp case EXC_ISI: trapstr = "ISI"; break; 242191762Simp case EXC_PGM: trapstr = "PGM"; break; 243191762Simp case EXC_SC: trapstr = "SC"; break; 244191762Simp case EXC_EXI: trapstr = "EXI"; break; 245191762Simp case EXC_MCHK: trapstr = "MCHK"; break; 246191762Simp#if !defined(BOOKE) 247191762Simp case EXC_VEC: trapstr = "VEC"; break; 248191762Simp case EXC_FPA: trapstr = "FPA"; break; 249191762Simp case EXC_BPT: trapstr = "BPT"; break; 250191762Simp case EXC_TRC: trapstr = "TRC"; break; 251191762Simp case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break; 252191762Simp case EXC_SMI: trapstr = "SMI"; break; 253191762Simp case EXC_RST: trapstr = "RST"; break; 254191762Simp#endif 255191762Simp case EXC_FPU: trapstr = "FPU"; break; 256191762Simp case EXC_DECR: trapstr = "DECR"; break; 257191762Simp case EXC_PERF: trapstr = "PERF"; break; 258191762Simp default: trapstr = NULL; break; 259191762Simp } 260191762Simp if (trapstr != NULL) { 261191762Simp db_printf("%s trap by ", trapstr); 262191762Simp } else { 263191762Simp db_printf("trap %#zx by ", tf->exc); 264191762Simp } 265191762Simp 266191762Simp print_trap: 267191762Simp lr = (db_addr_t) tf->srr0; 268191762Simp diff = 0; 269191762Simp symname = NULL; 270191762Simp sym = db_search_symbol(lr, DB_STGY_ANY, &diff); 271191762Simp db_symbol_values(sym, &symname, 0); 272191762Simp if (symname == NULL || !strcmp(symname, "end")) { 273191762Simp db_printf("%#zx: srr1=%#zx\n", lr, tf->srr1); 274191762Simp } else { 275191762Simp db_printf("%s+%#zx: srr1=%#zx\n", symname, diff, 276191762Simp tf->srr1); 277191762Simp } 278191762Simp db_printf("%-10s r1=%#zx cr=%#x xer=%#x ctr=%#zx", 279191762Simp "", tf->fixreg[1], (uint32_t)tf->cr, 280191762Simp (uint32_t)tf->xer, tf->ctr); 281191762Simp if (tf->exc == EXC_DSI) 282191762Simp db_printf(" sr=%#x", 283191762Simp (uint32_t)tf->cpu.aim.dsisr); 284191762Simp db_printf("\n"); 285191762Simp stackframe = (db_addr_t) tf->fixreg[1]; 286191762Simp if (kernel_only && (tf->srr1 & PSL_PR)) 287191762Simp break; 288191762Simp goto next_frame; 289191762Simp } 290191762Simp 291191762Simp diff = 0; 292191762Simp symname = NULL; 293191762Simp sym = db_search_symbol(lr, DB_STGY_ANY, &diff); 294191762Simp db_symbol_values(sym, &symname, 0); 295191762Simp if (symname == NULL || !strcmp(symname, "end")) 296191762Simp db_printf("at %zx", lr); 297191762Simp else 298191762Simp db_printf("at %s+%#zx", symname, diff); 299191762Simp if (full) 300191762Simp /* Print all the args stored in that stackframe. */ 301191762Simp db_printf("(%zx, %zx, %zx, %zx, %zx, %zx, %zx, %zx)", 302191762Simp args[0], args[1], args[2], args[3], 303191762Simp args[4], args[5], args[6], args[7]); 304191762Simp db_printf("\n"); 305191762Simp } 306191762Simp 307191762Simp return (0); 308191762Simp} 309191762Simp 310191762Simpvoid 311191762Simpdb_trace_self(void) 312191762Simp{ 313191762Simp db_addr_t addr; 314191762Simp 315191762Simp addr = (db_addr_t)__builtin_frame_address(1); 316191762Simp db_backtrace(curthread, addr, -1); 317191762Simp} 318191762Simp 319191762Simpint 320191762Simpdb_trace_thread(struct thread *td, int count) 321191762Simp{ 322191762Simp struct pcb *ctx; 323191762Simp 324191762Simp ctx = kdb_thr_ctx(td); 325191762Simp return (db_backtrace(td, (db_addr_t)ctx->pcb_sp, count)); 326191762Simp} 327191762Simp