PERFORCE change 101763 for review
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Mon Jul 17 13:39:22 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=101763
Change 101763 by gonzo at 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__);
}
More information about the p4-projects
mailing list