static void db_show_callout_bucket(struct callout_cpu *cc, struct callout_circq *bucket) { callout_impl_t *c; db_expr_t offset; const char *name; static char question[] = "?"; int b; if (CIRCQ_EMPTY(bucket)) return; for (c = CIRCQ_FIRST(bucket); /*nothing*/; c = CIRCQ_NEXT(&c->c_list)) { db_find_sym_and_offset((db_addr_t)(intptr_t)c->c_func, &name, &offset); name = name ? name : question; b = (bucket - cc->cc_wheel); if (b < 0) b = -WHEELSIZE; db_printf("%9d %2d/%-4d %16lx %s\n", c->c_time - cc->cc_ticks, b / WHEELSIZE, b, (u_long)c->c_arg, name); if (CIRCQ_LAST(&c->c_list, bucket)) break; } }
void db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif, void (*pr)(const char *, ...)) { struct frame *frame, *prevframe; db_addr_t pc; bool kernel_only = true; bool trace_thread = false; bool lwpaddr = false; const char *cp = modif; char c; if (ddb_cpuinfo == NULL) ddb_cpuinfo = curcpu(); 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) { frame = (struct frame *)DDB_TF->tf_out[6]; pc = DDB_TF->tf_pc; } 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) == 0) { (*pr)("swapped out\n"); return; } u = l->l_addr; frame = (struct frame *)u->u_pcb.pcb_sp; pc = u->u_pcb.pcb_pc; (*pr)("at %p\n", frame); } else { frame = (struct frame *)addr; pc = 0; } } while (count--) { int i; db_expr_t offset; const char *name; db_addr_t prevpc; #define FR(framep,field) (INKERNEL(framep) \ ? (u_int)(framep)->field \ : fuword(&(framep)->field)) /* Fetch return address and arguments frame */ prevpc = (db_addr_t)FR(frame, fr_pc); prevframe = (struct frame *)FR(frame, fr_fp); /* * Switch to frame that contains arguments */ if (prevframe == NULL || (!INKERNEL(prevframe) && kernel_only)) return; if ((ONINTSTACK(frame) && !ONINTSTACK(prevframe)) || (INKERNEL(frame) && !INKERNEL(prevframe))) { /* We're crossing a trap frame; pc = %l1 */ prevpc = (db_addr_t)FR(frame, fr_local[1]); } name = NULL; if (INKERNEL(pc)) db_find_sym_and_offset(pc, &name, &offset); if (name == NULL) (*pr)("0x%lx(", pc); else (*pr)("%s(", name); /* * Print %i0..%i5, hope these still reflect the * actual arguments somewhat... */ for (i = 0; i < 6; i++) (*pr)("0x%x%s", FR(frame, fr_arg[i]), (i < 5) ? ", " : ") at "); if (INKERNEL(prevpc)) db_printsym(prevpc, DB_STGY_PROC, pr); else (*pr)("0x%lx", prevpc); (*pr)("\n"); pc = prevpc; frame = prevframe; } }
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 }