void db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif, void (*pr)(const char *, ...)) { #ifndef DDB_TRACE struct pcb *pcb; struct proc *p; struct lwp *l; if (!have_addr) { stacktrace_subr(ddb_regs.f_regs[_R_A0], ddb_regs.f_regs[_R_A1], ddb_regs.f_regs[_R_A2], ddb_regs.f_regs[_R_A3], ddb_regs.f_regs[_R_PC], ddb_regs.f_regs[_R_SP], /* non-virtual frame pointer */ ddb_regs.f_regs[_R_S8], ddb_regs.f_regs[_R_RA], pr); return; } /* "trace/t" */ (*pr)("pid %d ", (int)addr); p = p_find(addr, PFIND_LOCKED); if (p == NULL) { (*pr)("not found\n"); return; } l = LIST_FIRST(&p->p_lwps); /* XXX NJWLWP */ if (!(l->l_flag & LW_INMEM)) { (*pr)("swapped out\n"); return; } pcb = &(l->l_addr->u_pcb); (*pr)("at %p\n", pcb); stacktrace_subr(0,0,0,0, /* no args known */ (int)cpu_switchto, pcb->pcb_context[8], pcb->pcb_context[9], pcb->pcb_context[10], pr); #else /* * Incomplete but practically useful stack backtrace. */ #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ #define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */ #define MIPS_ERET 0x42000018 /* instruction code for eret */ unsigned va, pc, ra, sp, func; int insn; InstFmt i; int stacksize; db_addr_t offset; const char *name; extern char verylocore[]; pc = ddb_regs.f_regs[_R_PC]; sp = ddb_regs.f_regs[_R_SP]; ra = ddb_regs.f_regs[_R_RA]; do { va = pc; do { va -= sizeof(int); insn = *(int *)va; if (insn == MIPS_ERET) goto mips3_eret; } while (insn != MIPS_JR_RA && insn != MIPS_JR_K0); va += sizeof(int); mips3_eret: va += sizeof(int); while (*(int *)va == 0x00000000) va += sizeof(int); func = va; stacksize = 0; do { i.word = *(int *)va; if (i.IType.op == OP_SW && i.IType.rs == _R_SP && i.IType.rt == _R_RA) ra = *(int *)(sp + (short)i.IType.imm); if (i.IType.op == OP_ADDIU && i.IType.rs == _R_SP && i.IType.rt == _R_SP) stacksize = -(short)i.IType.imm; va += sizeof(int); } while (va < pc); db_find_sym_and_offset(func, &name, &offset); if (name == 0) name = "?"; (*pr)("%s()+0x%x, called by %p, stack size %d\n", name, pc - func, (void *)ra, stacksize); if (ra == pc) { (*pr)("-- loop? --\n"); return; } sp += stacksize; pc = ra; } while (pc > (unsigned)verylocore); if (pc < 0x80000000) (*pr)("-- user process --\n"); else (*pr)("-- kernel entry --\n"); #endif }
void db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif, void (*pr)(const char *, ...)) { #ifndef DDB_TRACE struct pcb *pcb; struct proc *p; struct lwp *l; const char *cp = modif; char c; bool lwpaddr = false; if (!have_addr) { struct reg * regs = &ddb_regs; stacktrace_subr(regs->r_regs[_R_A0], regs->r_regs[_R_A1], regs->r_regs[_R_A2], regs->r_regs[_R_A3], regs->r_regs[_R_PC], regs->r_regs[_R_SP], /* non-virtual frame pointer */ regs->r_regs[_R_S8], regs->r_regs[_R_RA], pr); return; } while ((c = *cp++) != 0) { if (c == 'a') { lwpaddr = true; } } if (lwpaddr) { l = (struct lwp *)(intptr_t)addr; (*pr)("pid %d.%d ", l->l_proc->p_pid, l->l_lid); } else { /* "trace/t" */ (*pr)("pid %d ", (int)addr); p = proc_find_raw(addr); if (p == NULL) { (*pr)("not found\n"); return; } l = LIST_FIRST(&p->p_lwps); /* XXX NJWLWP */ } pcb = lwp_getpcb(l); (*pr)("at %p\n", pcb); stacktrace_subr(0,0,0,0, /* no args known */ (vaddr_t)cpu_switchto, pcb->pcb_context.val[_L_SP], pcb->pcb_context.val[_L_S8], pcb->pcb_context.val[_L_RA], pr); #else /* * Incomplete but practically useful stack backtrace. */ #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ #define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */ #define MIPS_ERET 0x42000018 /* instruction code for eret */ register_t va, pc, ra, sp, func; int insn; InstFmt i; int stacksize; db_addr_t offset; const char *name; extern char verylocore[]; pc = ddb_regs.r_regs[_R_PC]; sp = ddb_regs.r_regs[_R_SP]; ra = ddb_regs.r_regs[_R_RA]; do { va = pc; do { va -= sizeof(int); insn = *(int *)(intptr_t)va; if (insn == MIPS_ERET) goto mips3_eret; } while (insn != MIPS_JR_RA && insn != MIPS_JR_K0); va += sizeof(int); mips3_eret: va += sizeof(int); while (*(int *)(intptr_t)va == 0x00000000) va += sizeof(int); func = va; stacksize = 0; do { i.word = *(int *)(intptr_t)va; if (((i.IType.op == OP_SW) || (i.IType.op == OP_SD)) && i.IType.rs == _R_SP && i.IType.rt == _R_RA) ra = *(int *)(intptr_t)(sp + (short)i.IType.imm); if (((i.IType.op == OP_ADDIU) || (i.IType.op == OP_DADDIU)) && i.IType.rs == _R_SP && i.IType.rt == _R_SP) stacksize = -(short)i.IType.imm; va += sizeof(int); } while (va < pc); db_find_sym_and_offset(func, &name, &offset); if (name == 0) name = "?"; (*pr)("%s()+0x%x, called by %p, stack size %d\n", name, pc - func, (void *)(intptr_t)ra, stacksize); if (ra == pc) { (*pr)("-- loop? --\n"); return; } sp += stacksize; pc = ra; } while (pc > (intptr_t)verylocore); if (pc < 0x80000000) (*pr)("-- user process --\n"); else (*pr)("-- kernel entry --\n"); #endif }