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