Date: Mon, 17 Jul 2006 13:39:20 GMT From: Oleksandr Tymoshenko <gonzo@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 101763 for review Message-ID: <200607171339.k6HDdKdf095836@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=101763 Change 101763 by gonzo@gonzo_hq on 2006/07/17 13:39:18 o Stack unwinding routine for MIPS added. o "unimplemented" stubs added. Affected files ... .. //depot/projects/mips2/src/sys/mips/mips/db_trace.c#4 edit Differences ... ==== //depot/projects/mips2/src/sys/mips/mips/db_trace.c#4 (text+ko) ==== @@ -29,6 +29,7 @@ #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> +#include <sys/kdb.h> #include <sys/proc.h> #include <sys/user.h> @@ -41,8 +42,7 @@ #include <ddb/db_variables.h> #include <ddb/db_sym.h> -void db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t - count, char *modif); +void db_stack_trace_cmd(db_expr_t pc_addr, db_expr_t sp, db_expr_t count); void db_print_backtrace(void); struct db_variable db_regs[] = { @@ -89,44 +89,61 @@ extern char btext[]; static u_register_t -db_stack_register_fetch(u_register_t sp, u_register_t stacksize, u_register_t r) +db_stack_register_fetch(u_register_t sp, u_register_t stack_pos, u_register_t r) { - if (sp == ddb_regs.f_regs[SP]) { - return (ddb_regs.f_regs[r]); + u_register_t * stack = (u_register_t *) sp; + /* + * XXX: This is true only if we're in KSEG0, otherwise we need map + * virtual address to physical + */ + if(r == RA) { + return *(stack+stack_pos/sizeof(u_register_t)); } else { - db_printf("\n*** don't know how to read registers from stack ***\n"); + db_printf("\n*** Not RA register type ***\n"); return (0); } } +/* + * Unwind stack for given PC and SP values. Unlike other architectures + * MIPS stack unwinding requires program counter value along with SP. + * Stack unwinding is based on some heuristics. We assume that SP operations + * marks the very beginning of function entry. It is not 100% correct, though + * this implementation is good enough for practical use. + */ void -db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, - char *modif) +db_stack_trace_cmd(db_expr_t pc_addr, db_expr_t sp_addr, db_expr_t count) { - u_register_t sp, ra, pc, i, stacksize, func; + u_register_t sp, ra = 0, pc, i, stacksize, func; + short ra_stack_pos = 0; InstFmt insn; + c_db_sym_t sym; + const char *name; + db_expr_t offset, value; - sp = ddb_regs.f_regs[SP]; - ra = ddb_regs.f_regs[RA]; - pc = ddb_regs.f_regs[PC]; + sp = sp_addr; + pc = pc_addr; for (;;) { func = 0; stacksize = 0; if (pc <= (u_register_t)btext) break; - db_printf("%p", (void *)pc); for (i = pc; i >= (u_register_t)btext; i -= sizeof (insn)) { bcopy((void *)i, &insn, sizeof insn); switch (insn.IType.op) { case OP_ADDI: case OP_ADDIU: - case OP_DADDI: - case OP_DADDIU: if (insn.IType.rs != SP || insn.IType.rt != SP) break; stacksize = -(short)insn.IType.imm; break; + + case OP_SW: + if (insn.IType.rs != SP || insn.IType.rt != RA) + break; + ra_stack_pos = (short)insn.IType.imm; + break; default: break; } @@ -136,20 +153,37 @@ } } - db_printf(" in %p\n", (void *)func); + sym = db_search_symbol(func, DB_STGY_ANY, &offset); + if (sym == C_DB_SYM_NULL) { + value = 0; + name = "(null)"; + } else + db_symbol_values(sym, &name, &value); + + db_printf("0x%08x", pc); + if(name != NULL) + db_printf(" in %s(stacksize=%d, ra saved at %d)\n", + name, stacksize, ra_stack_pos); + else + db_printf(" in %p(stacksize=%d, ra saved at %d)\n", + (void *)func, stacksize, ra_stack_pos); - sp += stacksize; for (i = pc; !ra; i += sizeof (insn)) { bcopy((void *)i, &insn, sizeof insn); + switch (insn.IType.op) { - case OP_JR: - case OP_JALR: - if (ra >= (u_register_t)btext) - break; - ra = db_stack_register_fetch(sp, stacksize, insn.RType.rs); - if (!ra) - goto done; + case OP_SPECIAL: + if((insn.RType.func == OP_JR)) + { + if (ra >= (u_register_t)btext) + break; + ra = db_stack_register_fetch(sp, + ra_stack_pos, insn.RType.rs); + if (!ra) + goto done; + ra -= 8; + } break; default: break; @@ -163,6 +197,7 @@ db_printf("--- loop? ----\n"); break; } + sp += stacksize; pc = ra; ra = 0; } @@ -172,38 +207,46 @@ void db_print_backtrace(void) { - u_long *sp; - - sp = __builtin_frame_address(1); - db_stack_trace_cmd((db_expr_t)sp, TRUE, -1, "a"); + printf("%s unimplemented\n", __func__); } int db_md_set_watchpoint(db_expr_t dummy1, db_expr_t dummy2) { + printf("%s unimplemented\n", __func__); return (0); } int db_md_clr_watchpoint(db_expr_t dummy1, db_expr_t dummy2) { + printf("%s unimplemented\n", __func__); return (0); } void db_md_list_watchpoints(void) { - + printf("%s unimplemented\n", __func__); } int db_trace_thread(struct thread *thr, int count) { + u_register_t pc; + u_register_t sp; + struct pcb *ctx; + + ctx = kdb_thr_ctx(thr); + pc = ctx->pcb_regs[PCB_REG_PC]; + sp = ctx->pcb_regs[PCB_REG_SP]; + + db_stack_trace_cmd(pc, sp, -1); return (0); } void db_trace_self(void) { - + printf("%s unimplemented\n", __func__); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607171339.k6HDdKdf095836>