db_sym_t db_frame_info(long *frame, db_addr_t callpc, const char **namep, db_expr_t *offp, int *is_trap, int *nargp) { db_expr_t offset; db_sym_t sym; int narg; const char *name; sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); if (sym == (db_sym_t)0) return (db_sym_t)0; *is_trap = NONE; narg = 0; if (INKERNEL((long)frame) && name) { /* * XXX traps should be based off of the Xtrap* * locations rather than on trap, since some traps * (e.g., npxdna) don't go through trap() */ if (!strcmp(name, "trap")) { *is_trap = TRAP; narg = 0; } else if (!strcmp(name, "syscall_plain") || !strcmp(name, "syscall_fancy")) { *is_trap = SYSCALL; narg = 0; } else if (name[0] == 'X') { if (!strncmp(name, "Xintr", 5) || !strncmp(name, "Xresume", 7) || !strncmp(name, "Xstray", 6) || !strncmp(name, "Xhold", 5) || !strncmp(name, "Xrecurse", 8) || !strcmp(name, "Xdoreti") || !strncmp(name, "Xsoft", 5)) { *is_trap = INTERRUPT; narg = 0; } } } if (offp != NULL) *offp = offset; if (nargp != NULL) *nargp = narg; if (namep != NULL) *namep = name; return sym; }
static const char * symbol_name(vm_offset_t va, db_strategy_t strategy) { const char *name; c_db_sym_t sym; db_expr_t offset; if (va == 0) return (NULL); sym = db_search_symbol(va, strategy, &offset); if (offset != 0) return (NULL); db_symbol_values(sym, &name, NULL); return (name); }
static void print_addr(db_addr_t loc) { db_expr_t diff; db_sym_t sym; const char *symname; diff = INT_MAX; symname = NULL; sym = db_search_symbol(loc, DB_STGY_ANY, &diff); db_symbol_values(sym, &symname, 0); if (symname) { if (diff == 0) db_printf("%s", symname); else db_printf("<%s+%lx>", symname, diff); db_printf("\t[addr:0x%08lx]", loc); } else { db_printf("0x%08lx", loc); } }
void db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif, void (*pr)(const char *, ...)) { register_t *fp, pc, rp; bool kernel_only = true; bool trace_thread = false; bool lwpaddr = false; db_sym_t sym; db_expr_t off; const char *name; const char *cp = modif; char c; if (count < 0) count = 65536; while ((c = *cp++) != 0) { if (c == 'a') { lwpaddr = true; trace_thread = true; } if (c == 't') trace_thread = true; if (c == 'u') kernel_only = false; } if (!have_addr) { fp = (register_t *)ddb_regs.tf_r3; pc = ddb_regs.tf_iioq_head; rp = ddb_regs.tf_rp; } else { if (trace_thread) { struct proc *p; struct user *u; struct lwp *l; if (lwpaddr) { l = (struct lwp *)addr; p = l->l_proc; (*pr)("trace: pid %d ", p->p_pid); } else { (*pr)("trace: pid %d ", (int)addr); p = p_find(addr, PFIND_LOCKED); if (p == NULL) { (*pr)("not found\n"); return; } l = LIST_FIRST(&p->p_lwps); KASSERT(l != NULL); } (*pr)("lid %d ", l->l_lid); if (!(l->l_flag & LW_INMEM)) { (*pr)("swapped out\n"); return; } u = l->l_addr; if (p == curproc && l == curlwp) { fp = (int *)ddb_regs.tf_r3; pc = ddb_regs.tf_iioq_head; rp = ddb_regs.tf_rp; } else { /* cpu_switchto fp, and return point */ fp = (int *)(u->u_pcb.pcb_ksp - (HPPA_FRAME_SIZE + 16*4)); pc = 0; rp = fp[-5]; } (*pr)("at %p\n", fp); } else { pc = 0; fp = (register_t *)addr; rp = fp[-5]; } } while (fp && count--) { #ifdef DDB_DEBUG pr(">> %08x %08x %08x\t", fp, pc, rp); #endif if (USERMODE(pc)) return; sym = db_search_symbol(pc, DB_STGY_ANY, &off); db_symbol_values (sym, &name, NULL); pr("%s() at ", name); db_printsym(pc, DB_STGY_PROC, pr); pr("\n"); /* XXX NH - unwind info here */ /* aue = ue_find(pc); */ /* * get rp? * fp -= ue_total_frame_size(aue) */ /* * if a terminal frame then report the trapframe * and continue after it (if not the last one). */ if (!fp[0]) { register_t *scargs; struct trapframe *tf; int scoff; /* Stack space for syscall args */ scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE + HPPA_FRAME_MAXARGS); scargs = (register_t *)((char *)fp - scoff); tf = (struct trapframe *)((char *)scargs - sizeof(*tf)); if (tf->tf_flags & TFF_SYS) pr("-- syscall #%d(%x, %x, %x, %x, ...)\n", tf->tf_t1, scargs[1], scargs[2], scargs[3], scargs[4]); else pr("-- trap #%d%s\n", tf->tf_flags & 0x3f, (tf->tf_flags & T_USER)? " from user" : ""); if (!(tf->tf_flags & TFF_LAST)) { fp = (register_t *)tf->tf_r3; pc = tf->tf_iioq_head; rp = tf->tf_rp; } else { pc = 0; fp = 0; } } else { /* next frame */ fp = (register_t *)fp[0]; pc = rp; rp = fp[-5]; } } if (count && pc) { db_printsym(pc, DB_STGY_XTRN, pr); pr(":\n"); } }
void db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif, int (*pr)(const char *, ...)) { struct callframe *frame, *lastframe; long *argp, *arg0; db_addr_t callpc; int is_trap = 0; boolean_t kernel_only = TRUE; boolean_t trace_proc = FALSE; { char *cp = modif; char c; while ((c = *cp++) != 0) { if (c == 'p') trace_proc = TRUE; if (c == 'u') kernel_only = FALSE; } } if (!have_addr) { frame = (struct callframe *)ddb_regs.tf_rbp; callpc = (db_addr_t)ddb_regs.tf_rip; } else { if (trace_proc) { struct proc *p = pfind((pid_t)addr); if (p == NULL) { (*pr) ("db_trace.c: process not found\n"); return; } frame = (struct callframe *)p->p_addr->u_pcb.pcb_rbp; } else { frame = (struct callframe *)addr; } callpc = (db_addr_t) db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE); frame = (struct callframe *)frame->f_frame; } lastframe = 0; while (count && frame != 0) { int narg; char * name; db_expr_t offset; db_sym_t sym; sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); if (lastframe == 0 && sym == NULL) { /* Symbol not found, peek at code */ long instr = db_get_value(callpc, 8, FALSE); offset = 1; if ((instr & 0x00ffffff) == 0x00e58955 || /* enter: pushl %ebp, movl %esp, %ebp */ (instr & 0x0000ffff) == 0x0000e589 /* enter+1: movl %esp, %ebp */) { offset = 0; } } if (INKERNEL(callpc) && name) { if (!strcmp(name, "trap")) { is_trap = TRAP; } else if (!strcmp(name, "ast")) { is_trap = AST; } else if (!strcmp(name, "syscall")) { is_trap = SYSCALL; } else if (name[0] == 'X') { if (!strncmp(name, "Xintr", 5) || !strncmp(name, "Xresume", 7) || !strncmp(name, "Xrecurse", 8) || !strcmp(name, "Xdoreti") || !strncmp(name, "Xsoft", 5)) { is_trap = INTERRUPT; } else goto normal; } else goto normal; narg = 0; } else { normal: is_trap = NONE; narg = db_numargs(frame); } (*pr)("%s(", name); if (lastframe == 0 && offset == 0 && !have_addr) { /* * We have a breakpoint before the frame is set up * Use %rsp instead */ arg0 = &((struct callframe *)(ddb_regs.tf_rsp-8))->f_arg0; } else { arg0 = &frame->f_arg0; } for (argp = arg0; narg > 0; ) { (*pr)("%lx", db_get_value((db_addr_t)argp, 8, FALSE)); argp++; if (--narg != 0) (*pr)(","); } (*pr)(") at "); db_printsym(callpc, DB_STGY_PROC, pr); (*pr)("\n"); if (lastframe == 0 && offset == 0 && !have_addr && !is_trap) { /* Frame really belongs to next callpc */ lastframe = (struct callframe *)(ddb_regs.tf_rsp-8); callpc = (db_addr_t) db_get_value((db_addr_t)&lastframe->f_retaddr, 8, FALSE); continue; } if (is_trap == INTERRUPT) { /* * Interrupt routines don't update %rbp, so it still * points to the frame that was interrupted. Pull * back to just above lastframe so we can find the * trapframe as with syscalls and traps. */ frame = (struct callframe *)&lastframe->f_retaddr; arg0 = &frame->f_arg0; } lastframe = frame; db_nextframe(&frame, &callpc, arg0, is_trap, pr); if (frame == 0) { /* end of chain */ break; } if (INKERNEL(frame)) { /* staying in kernel */ if (frame <= lastframe) { (*pr)("Bad frame pointer: %p\n", frame); break; } } else if (INKERNEL(lastframe)) { /* switch from user to kernel */ if (kernel_only) { (*pr)("end of kernel\n"); break; /* kernel stack only */ } } else { /* in user */ if (frame <= lastframe) { (*pr)("Bad user frame pointer: %p\n", frame); break; } } --count; } (*pr)("end trace frame: 0x%lx, count: %d\n", frame, count); if (count && is_trap != NONE) { db_printsym(callpc, DB_STGY_XTRN, pr); (*pr)(":\n"); } }
/* * System startup; initialize the world, create process 0, mount root * filesystem, and fork to create init and pagedaemon. Most of the * hard work is done in the lower-level initialization routines including * startup(), which does memory initialization and autoconfiguration. * * This allows simple addition of new kernel subsystems that require * boot time initialization. It also allows substitution of subsystem * (for instance, a scheduler, kernel profiler, or VM system) by object * module. Finally, it allows for optional "kernel threads". */ void mi_startup(void) { register struct sysinit **sipp; /* system initialization*/ register struct sysinit **xipp; /* interior loop of sort*/ register struct sysinit *save; /* bubble*/ #if defined(VERBOSE_SYSINIT) int last; int verbose; #endif if (sysinit == NULL) { sysinit = SET_BEGIN(sysinit_set); sysinit_end = SET_LIMIT(sysinit_set); } restart: /* * Perform a bubble sort of the system initialization objects by * their subsystem (primary key) and order (secondary key). */ for (sipp = sysinit; sipp < sysinit_end; sipp++) { for (xipp = sipp + 1; xipp < sysinit_end; xipp++) { if ((*sipp)->subsystem < (*xipp)->subsystem || ((*sipp)->subsystem == (*xipp)->subsystem && (*sipp)->order <= (*xipp)->order)) continue; /* skip*/ save = *sipp; *sipp = *xipp; *xipp = save; } } #if defined(VERBOSE_SYSINIT) last = SI_SUB_COPYRIGHT; verbose = 0; #if !defined(DDB) printf("VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n"); #endif #endif /* * Traverse the (now) ordered list of system initialization tasks. * Perform each task, and continue on to the next task. * * The last item on the list is expected to be the scheduler, * which will not return. */ for (sipp = sysinit; sipp < sysinit_end; sipp++) { if ((*sipp)->subsystem == SI_SUB_DUMMY) continue; /* skip dummy task(s)*/ if ((*sipp)->subsystem == SI_SUB_DONE) continue; #if defined(VERBOSE_SYSINIT) if ((*sipp)->subsystem > last) { verbose = 1; last = (*sipp)->subsystem; printf("subsystem %x\n", last); } if (verbose) { #if defined(DDB) const char *name; c_db_sym_t sym; db_expr_t offset; sym = db_search_symbol((vm_offset_t)(*sipp)->func, DB_STGY_PROC, &offset); db_symbol_values(sym, &name, NULL); if (name != NULL) printf(" %s(%p)... ", name, (*sipp)->udata); else #endif printf(" %p(%p)... ", (*sipp)->func, (*sipp)->udata); } #endif /* Call function */ (*((*sipp)->func))((*sipp)->udata); #if defined(VERBOSE_SYSINIT) if (verbose) printf("done.\n"); #endif /* Check off the one we're just done */ (*sipp)->subsystem = SI_SUB_DONE; /* Check if we've installed more sysinit items via KLD */ if (newsysinit != NULL) { if (sysinit != SET_BEGIN(sysinit_set)) free(sysinit, M_TEMP); sysinit = newsysinit; sysinit_end = newsysinit_end; newsysinit = NULL; newsysinit_end = NULL; goto restart; } } panic("Shouldn't get here!"); /* NOTREACHED*/ }
void db_printsym(db_expr_t off, db_strategy_t strategy, void (*pr)(const char *, ...)) { const char *name; #ifdef _KERNEL const char *mod; unsigned long uval; long val; #endif #ifdef notyet char *filename; int linenum; #endif #ifndef _KERNEL if (!use_ksyms) { db_expr_t d; char *filename; db_expr_t value; int linenum; db_sym_t cursym; cursym = db_search_symbol(off, strategy, &d); db_symbol_values(cursym, &name, &value); if (name != NULL && ((unsigned int)d < db_maxoff) && value != 0) { (*pr)("%s", name); if (d) { char tbuf[24]; db_format_radix(tbuf, 24, d, true); (*pr)("+%s", tbuf); } if (strategy == DB_STGY_PROC) { if ((*db_symformat->sym_line_at_pc) (NULL, cursym, &filename, &linenum, off)) (*pr)(" [%s:%d]", filename, linenum); } return; } (*pr)("%s", db_num_to_str(off)); return; } #endif #ifdef _KERNEL if (ksyms_getname(&mod, &name, (vaddr_t)off, strategy|KSYMS_CLOSEST) == 0) { (void)ksyms_getval_unlocked(mod, name, &uval, KSYMS_ANY); val = (long) uval; if (((off - val) < db_maxoff) && val) { (*pr)("%s:%s", mod, name); if (off - val) { char tbuf[24]; db_format_radix(tbuf, 24, off - val, true); (*pr)("+%s", tbuf); } #ifdef notyet if (strategy & KSYMS_PROC) { if (ksyms_fmaddr(off, &filename, &linenum) == 0) (*pr)(" [%s:%d]", filename, linenum); } #endif return; } } #endif (*pr)("%s", db_num_to_str(off)); return; }
void db_symstr(char *buf, size_t buflen, db_expr_t off, db_strategy_t strategy) { const char *name; #ifdef _KERNEL const char *mod; unsigned long val; #endif #ifndef _KERNEL if (!use_ksyms) { db_expr_t d; char *filename; db_expr_t value; int linenum; db_sym_t cursym; cursym = db_search_symbol(off, strategy, &d); db_symbol_values(cursym, &name, &value); if (name != NULL && ((unsigned int)d < db_maxoff) && value != 0) { strlcpy(buf, name, buflen); if (d) { strlcat(buf, "+", buflen); db_format_radix(buf + strlen(buf), 24, d, true); } if (strategy == DB_STGY_PROC) { if ((*db_symformat->sym_line_at_pc) (NULL, cursym, &filename, &linenum, off)) { size_t len = strlen(buf); snprintf(buf + len, buflen - len, " [%s:%d]", filename, linenum); } } return; } strlcpy(buf, db_num_to_str(off), buflen); return; } #endif #ifdef _KERNEL if (ksyms_getname(&mod, &name, (vaddr_t)off, strategy|KSYMS_CLOSEST) == 0) { (void)ksyms_getval_unlocked(mod, name, &val, KSYMS_ANY); if (((off - val) < db_maxoff) && val) { snprintf(buf, buflen, "%s:%s", mod, name); if (off - val) { strlcat(buf, "+", buflen); db_format_radix(buf+strlen(buf), 24, off - val, true); } #ifdef notyet if (strategy & KSYMS_PROC) { if (ksyms_fmaddr(off, &filename, &linenum) == 0) snprintf(buf + strlen(buf), buflen - strlen(buf), " [%s:%d]", filename, linenum); } #endif return; } } strlcpy(buf, db_num_to_str(off), buflen); #endif }
void db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif, int (*pr)(const char *, ...)) { struct x86_64_frame *frame, *lastframe; long *argp; db_addr_t callpc; int is_trap = 0; boolean_t kernel_only = TRUE; boolean_t trace_thread = FALSE; #if 0 if (!db_trace_symbols_found) db_find_trace_symbols(); #endif { char *cp = modif; char c; while ((c = *cp++) != 0) { if (c == 't') trace_thread = TRUE; if (c == 'u') kernel_only = FALSE; } } if (!have_addr) { frame = (struct x86_64_frame *)ddb_regs.tf_rbp; callpc = (db_addr_t)ddb_regs.tf_rip; } else { #if 0 if (trace_thread) { struct proc *p; struct user *u; struct lwp *l; (*pr)("trace: pid %d ", (int)addr); p = pfind(addr); if (p == NULL) { (*pr)("not found\n"); return; } l = proc_representative_lwp(p); if (!(l->l_flag&L_INMEM)) { (*pr)("swapped out\n"); return; } u = l->l_addr; frame = (struct x86_64_frame *) u->u_pcb.pcb_rbp; (*pr)("at %p\n", frame); } else #endif frame = (struct x86_64_frame *)addr; callpc = (db_addr_t) db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE); frame = (struct x86_64_frame *)frame->f_frame; } lastframe = 0; while (count && frame != 0) { int narg; char * name; db_expr_t offset; db_sym_t sym; #define MAXNARG 16 char *argnames[MAXNARG], **argnp = NULL; sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); if (lastframe == 0 && sym == NULL) { /* Symbol not found, peek at code */ long instr = db_get_value(callpc, 8, FALSE); offset = 1; if ((instr & 0x00ffffff) == 0x00e58955 || /* enter: pushl %ebp, movl %esp, %ebp */ (instr & 0x0000ffff) == 0x0000e589 /* enter+1: movl %esp, %ebp */) { offset = 0; } } if (INKERNEL(frame) && name) { #ifdef __ELF__ if (!strcmp(name, "trap")) { is_trap = TRAP; } else if (!strcmp(name, "syscall")) { is_trap = SYSCALL; } else if (name[0] == 'X') { if (!strncmp(name, "Xintr", 5) || !strncmp(name, "Xresume", 7) || !strncmp(name, "Xstray", 6) || !strncmp(name, "Xhold", 5) || !strncmp(name, "Xrecurse", 8) || !strcmp(name, "Xdoreti") || !strncmp(name, "Xsoft", 5)) { is_trap = INTERRUPT; } else goto normal; } else goto normal; narg = 0; #else if (!strcmp(name, "_trap")) { is_trap = TRAP; } else if (!strcmp(name, "_syscall")) { is_trap = SYSCALL; } else if (name[0] == '_' && name[1] == 'X') { if (!strncmp(name, "_Xintr", 6) || !strncmp(name, "_Xresume", 8) || !strncmp(name, "_Xstray", 7) || !strncmp(name, "_Xhold", 6) || !strncmp(name, "_Xrecurse", 9) || !strcmp(name, "_Xdoreti") || !strncmp(name, "_Xsoft", 6)) { is_trap = INTERRUPT; } else goto normal; } else goto normal; narg = 0; #endif /* __ELF__ */ } else { normal: is_trap = NONE; narg = MAXNARG; if (db_sym_numargs(sym, &narg, argnames)) argnp = argnames; else narg = db_numargs(frame); } (*pr)("%s(", name); if (lastframe == 0 && offset == 0 && !have_addr) { /* * We have a breakpoint before the frame is set up * Use %esp instead */ argp = &((struct x86_64_frame *)(ddb_regs.tf_rsp-8))->f_arg0; } else { argp = &frame->f_arg0; } while (narg) { if (argnp) (*pr)("%s=", *argnp++); (*pr)("%lx", db_get_value((db_addr_t)argp, 8, FALSE)); argp++; if (--narg != 0) (*pr)(","); } (*pr)(") at "); db_printsym(callpc, DB_STGY_PROC, pr); (*pr)("\n"); if (lastframe == 0 && offset == 0 && !have_addr) { /* Frame really belongs to next callpc */ lastframe = (struct x86_64_frame *)(ddb_regs.tf_rsp-8); callpc = (db_addr_t) db_get_value((db_addr_t)&lastframe->f_retaddr, 8, FALSE); continue; } lastframe = frame; db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap, pr); if (frame == 0) { /* end of chain */ break; } if (INKERNEL(frame)) { /* staying in kernel */ if (frame <= lastframe) { (*pr)("Bad frame pointer: %p\n", frame); break; } } else if (INKERNEL(lastframe)) { /* switch from user to kernel */ if (kernel_only) { (*pr)("end of kernel\n"); break; /* kernel stack only */ } } else { /* in user */ if (frame <= lastframe) { (*pr)("Bad user frame pointer: %p\n", frame); break; } } --count; } (*pr)("end trace frame: 0x%lx, count: %d\n", frame, count); if (count && is_trap != NONE) { db_printsym(callpc, DB_STGY_XTRN, pr); (*pr)(":\n"); } }
/* * Frame tracing. */ static int db_backtrace(struct thread *td, db_addr_t fp, int count) { db_addr_t stackframe, lr, *args; db_expr_t diff; c_db_sym_t sym; const char *symname; boolean_t kernel_only = TRUE; boolean_t full = FALSE; #if 0 { register char *cp = modif; register char c; while ((c = *cp++) != 0) { if (c == 't') trace_thread = TRUE; if (c == 'u') kernel_only = FALSE; if (c == 'f') full = TRUE; } } #endif stackframe = fp; while (!db_pager_quit) { if (stackframe < PAGE_SIZE) break; /* * Locate the next frame by grabbing the backchain ptr * from frame[0] */ stackframe = *(db_addr_t *)stackframe; next_frame: #ifdef __powerpc64__ /* The saved arg values start at frame[6] */ args = (db_addr_t *)(stackframe + 48); #else /* The saved arg values start at frame[2] */ args = (db_addr_t *)(stackframe + 8); #endif if (stackframe < PAGE_SIZE) break; if (count-- == 0) break; /* * Extract link register from frame and subtract * 4 to convert into calling address (as opposed to * return address) */ #ifdef __powerpc64__ lr = *(db_addr_t *)(stackframe + 16) - 4; #else lr = *(db_addr_t *)(stackframe + 4) - 4; #endif if ((lr & 3) || (lr < 0x100)) { db_printf("saved LR(0x%zx) is invalid.", lr); break; } #ifdef __powerpc64__ db_printf("0x%016lx: ", stackframe); #else db_printf("0x%08x: ", stackframe); #endif /* * The trap code labels the return addresses from the * call to C code as 'trapexit' and 'asttrapexit. Use this * to determine if the callframe has to traverse a saved * trap context */ if ((lr + CALLOFFSET == (db_addr_t) &trapexit) || (lr + CALLOFFSET == (db_addr_t) &asttrapexit)) { const char *trapstr; struct trapframe *tf = (struct trapframe *)(args); db_printf("%s ", tf->srr1 & PSL_PR ? "user" : "kernel"); switch (tf->exc) { case EXC_DSI: /* XXX take advantage of the union. */ db_printf("DSI %s trap @ %#zx by ", (tf->cpu.aim.dsisr & DSISR_STORE) ? "write" : "read", tf->cpu.aim.dar); goto print_trap; case EXC_ALI: /* XXX take advantage of the union. */ db_printf("ALI trap @ %#zx (xSR %#x) ", tf->cpu.aim.dar, (uint32_t)tf->cpu.aim.dsisr); goto print_trap; #ifdef __powerpc64__ case EXC_DSE: db_printf("DSE trap @ %#zx by ", tf->cpu.aim.dar); goto print_trap; case EXC_ISE: db_printf("ISE trap @ %#zx by ", tf->srr0); goto print_trap; #endif case EXC_ISI: trapstr = "ISI"; break; case EXC_PGM: trapstr = "PGM"; break; case EXC_SC: trapstr = "SC"; break; case EXC_EXI: trapstr = "EXI"; break; case EXC_MCHK: trapstr = "MCHK"; break; #if !defined(BOOKE) case EXC_VEC: trapstr = "VEC"; break; case EXC_FPA: trapstr = "FPA"; break; case EXC_BPT: trapstr = "BPT"; break; case EXC_TRC: trapstr = "TRC"; break; case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break; case EXC_SMI: trapstr = "SMI"; break; case EXC_RST: trapstr = "RST"; break; #endif case EXC_FPU: trapstr = "FPU"; break; case EXC_DECR: trapstr = "DECR"; break; case EXC_PERF: trapstr = "PERF"; break; default: trapstr = NULL; break; } if (trapstr != NULL) { db_printf("%s trap by ", trapstr); } else { db_printf("trap %#zx by ", tf->exc); } print_trap: lr = (db_addr_t) tf->srr0; diff = 0; symname = NULL; sym = db_search_symbol(lr, DB_STGY_ANY, &diff); db_symbol_values(sym, &symname, 0); if (symname == NULL || !strcmp(symname, "end")) { db_printf("%#zx: srr1=%#zx\n", lr, tf->srr1); } else { db_printf("%s+%#zx: srr1=%#zx\n", symname, diff, tf->srr1); } db_printf("%-10s r1=%#zx cr=%#x xer=%#x ctr=%#zx", "", tf->fixreg[1], (uint32_t)tf->cr, (uint32_t)tf->xer, tf->ctr); if (tf->exc == EXC_DSI) db_printf(" sr=%#x", (uint32_t)tf->cpu.aim.dsisr); db_printf("\n"); stackframe = (db_addr_t) tf->fixreg[1]; if (kernel_only && (tf->srr1 & PSL_PR)) break; goto next_frame; } diff = 0; symname = NULL; sym = db_search_symbol(lr, DB_STGY_ANY, &diff); db_symbol_values(sym, &symname, 0); if (symname == NULL || !strcmp(symname, "end")) db_printf("at %zx", lr); else db_printf("at %s+%#zx", symname, diff); if (full) /* Print all the args stored in that stackframe. */ db_printf("(%zx, %zx, %zx, %zx, %zx, %zx, %zx, %zx)", args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); db_printf("\n"); } return (0); }