PERFORCE change 207113 for review

Oleksandr Tymoshenko gonzo at FreeBSD.org
Wed Feb 29 21:08:31 UTC 2012


http://p4web.freebsd.org/@@207113?ac=10

Change 207113 by gonzo at gonzo_thinkpad on 2012/02/29 21:07:32

	Move kernel backtrace code into dtrace_isa.c file

Affected files ...

.. //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/dtrace_asm.S#2 edit
.. //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/dtrace_isa.c#8 edit
.. //depot/projects/dtrace-mips/sys/conf/files.mips#3 edit
.. //depot/projects/dtrace-mips/sys/mips/mips/backtrace.c#5 delete
.. //depot/projects/dtrace-mips/sys/mips/mips/db_trace.c#3 edit

Differences ...

==== //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/dtrace_asm.S#2 (text+ko) ====

@@ -297,3 +297,4 @@
 	j	ra
 	nop
 END(dtrace_caller)
+

==== //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/dtrace_isa.c#8 (text+ko) ====

@@ -44,6 +44,7 @@
 #include <machine/db_machdep.h>
 #include <machine/md_var.h>
 #include <machine/mips_opcode.h>
+#include <machine/vmparam.h>
 #include <ddb/db_sym.h>
 #include <ddb/ddb.h>
 #include <sys/kdb.h>
@@ -57,14 +58,13 @@
 #define	MAX_FUNCTION_SIZE 0x10000
 #define	MAX_PROLOGUE_SIZE 0x100
 
-int next_frame(register_t *pc, register_t *sp,
-        uintptr_t *args, int *valid_args);
 
 uint8_t dtrace_fuword8_nocheck(void *);
 uint16_t dtrace_fuword16_nocheck(void *);
 uint32_t dtrace_fuword32_nocheck(void *);
 uint64_t dtrace_fuword64_nocheck(void *);
 
+static int dtrace_next_frame(register_t *pc, register_t *sp, uintptr_t *args, int *valid_args);
 static int dtrace_next_uframe(register_t *pc, register_t *sp, register_t *ra);
 
 void
@@ -107,7 +107,7 @@
 			pcstack[depth++] = callpc;
 		}
 
-		if (next_frame(&pc, &sp, NULL, NULL) < 0)
+		if (dtrace_next_frame(&pc, &sp, NULL, NULL) < 0)
 			break;
 	}
 
@@ -229,7 +229,7 @@
 		: "r" (ra));
 
 	for (i = 0; i <= aframes + 1; i++) {
-		if (next_frame(&pc, &sp, args, valid) < 0) {
+		if (dtrace_next_frame(&pc, &sp, args, valid) < 0) {
 			printf("%s: stack ends at frame #%d\n", __func__, i);
 			return (0);
 		}
@@ -264,7 +264,7 @@
 		: "r" (ra));
 
 	for (;;) {
-		if (next_frame(&pc, &sp, NULL, NULL) < 0)
+		if (dtrace_next_frame(&pc, &sp, NULL, NULL) < 0)
 			break;
 		depth++;
 	}
@@ -283,6 +283,203 @@
 }
 
 static int
+dtrace_next_frame(register_t *pc, register_t *sp,
+	uintptr_t *args, int *valid_args)
+{
+	InstFmt i;
+	/*
+	 * Arrays for a0..a3 registers and flags if content
+	 * of these registers is valid, e.g. obtained from the stack
+	 */
+	uintptr_t va;
+	unsigned instr, mask;
+	unsigned int frames = 0;
+	int more, stksize;
+	register_t ra = 0;
+	int arg, r;
+
+	/*
+	 * Invalidate arguments values
+	 */
+	if (valid_args) {
+		for (r = 0; r < 8; r++)
+			valid_args[r] = 0;
+	}
+
+	/* Jump here after a nonstandard (interrupt handler) frame */
+	stksize = 0;
+	if (frames++ > 100) {
+		/* return breaks stackframe-size heuristics with gcc -O2 */
+		goto error;	/* XXX */
+	}
+
+	/* check for bad SP: could foul up next frame */
+	if (!MIPS_IS_VALID_KERNELADDR(*sp)) {
+		goto error;
+	}
+
+	/* check for bad PC */
+	if (!MIPS_IS_VALID_KERNELADDR(*pc)) {
+		goto error;
+	}
+
+	/*
+	 * Find the beginning of the current subroutine by scanning
+	 * backwards from the current PC for the end of the previous
+	 * subroutine.
+	 */
+	va = *pc - sizeof(int);
+	while (1) {
+		instr = kdbpeek((int *)va);
+
+		/* [d]addiu sp,sp,-X */
+		if (((instr & 0xffff8000) == 0x27bd8000)
+		    || ((instr & 0xffff8000) == 0x67bd8000))
+			break;
+
+		/* jr	ra */
+		if (instr == 0x03e00008) {
+			/* skip over branch-delay slot instruction */
+			va += 2 * sizeof(int);
+			break;
+		}
+
+		va -= sizeof(int);
+	}
+
+	/* skip over nulls which might separate .o files */
+	while ((instr = kdbpeek((int *)va)) == 0)
+		va += sizeof(int);
+
+	/* scan forwards to find stack size and any saved registers */
+	stksize = 0;
+	more = 3;
+	mask = 0;
+	for (; more; va += sizeof(int),
+	    more = (more == 3) ? 3 : more - 1) {
+		/* stop if hit our current position */
+		if (va >= *pc)
+			break;
+		instr = kdbpeek((int *)va);
+		i.word = instr;
+		switch (i.JType.op) {
+		case OP_SPECIAL:
+			switch (i.RType.func) {
+			case OP_JR:
+			case OP_JALR:
+				more = 2;	/* stop after next instruction */
+				break;
+
+			case OP_SYSCALL:
+			case OP_BREAK:
+				more = 1;	/* stop now */
+			};
+			break;
+
+		case OP_BCOND:
+		case OP_J:
+		case OP_JAL:
+		case OP_BEQ:
+		case OP_BNE:
+		case OP_BLEZ:
+		case OP_BGTZ:
+			more = 2;	/* stop after next instruction */
+			break;
+
+		case OP_COP0:
+		case OP_COP1:
+		case OP_COP2:
+		case OP_COP3:
+			switch (i.RType.rs) {
+			case OP_BCx:
+			case OP_BCy:
+				more = 2;	/* stop after next instruction */
+			};
+			break;
+
+		case OP_SW:
+			/* look for saved registers on the stack */
+			if (i.IType.rs != 29)
+				break;
+			/* only restore the first one */
+			if (mask & (1 << i.IType.rt))
+				break;
+			mask |= (1 << i.IType.rt);
+			switch (i.IType.rt) {
+			case 4:/* a0 */
+			case 5:/* a1 */
+			case 6:/* a2 */
+			case 7:/* a3 */
+#if defined(__mips_n64) || defined(__mips_n32)
+			case 8:/* a4 */
+			case 9:/* a5 */
+			case 10:/* a6 */
+			case 11:/* a7 */
+#endif
+				arg = i.IType.rt - 4;
+				if (args)
+					args[arg] = kdbpeek((int *)(*sp + (short)i.IType.imm));
+				if (valid_args)
+					valid_args[arg] = 1;
+			case 31:	/* ra */
+				ra = kdbpeek((int *)(*sp + (short)i.IType.imm));
+			}
+			break;
+
+		case OP_SD:
+			/* look for saved registers on the stack */
+			if (i.IType.rs != 29)
+				break;
+			/* only restore the first one */
+			if (mask & (1 << i.IType.rt))
+				break;
+			mask |= (1 << i.IType.rt);
+			switch (i.IType.rt) {
+			case 4:/* a0 */
+			case 5:/* a1 */
+			case 6:/* a2 */
+			case 7:/* a3 */
+#if defined(__mips_n64) || defined(__mips_n32)
+			case 8:/* a4 */
+			case 9:/* a5 */
+			case 10:/* a6 */
+			case 11:/* a7 */
+#endif
+				arg = i.IType.rt - 4;
+				if (args)
+					args[arg] = kdbpeekd((int *)(*sp + (short)i.IType.imm));
+				if (valid_args)
+					valid_args[arg] = 1;
+				break;
+
+			case 31:	/* ra */
+				ra = kdbpeekd((int *)(*sp + (short)i.IType.imm));
+			}
+			break;
+
+		case OP_ADDI:
+		case OP_ADDIU:
+		case OP_DADDI:
+		case OP_DADDIU:
+			/* look for stack pointer adjustment */
+			if (i.IType.rs != 29 || i.IType.rt != 29)
+				break;
+			stksize = -((short)i.IType.imm);
+		}
+	}
+
+	if (!MIPS_IS_VALID_KERNELADDR(ra)) 
+		return (-1);
+
+	*pc = ra;
+	*sp += stksize;
+
+	return (0);
+error:
+	return (-1);
+}
+
+static int
 dtrace_next_uframe(register_t *pc, register_t *sp, register_t *ra)
 {
 	int offset, registers_on_stack;

==== //depot/projects/dtrace-mips/sys/conf/files.mips#3 (text+ko) ====

@@ -44,7 +44,6 @@
 mips/mips/pm_machdep.c		standard
 mips/mips/swtch.S		standard
 mips/mips/tlb.c			standard
-mips/mips/backtrace.c		standard
 
 mips/mips/bus_space_generic.c 	standard
 mips/mips/busdma_machdep.c 	standard

==== //depot/projects/dtrace-mips/sys/mips/mips/db_trace.c#3 (text+ko) ====

@@ -20,6 +20,7 @@
 #include <machine/mips_opcode.h>
 #include <machine/pcb.h>
 #include <machine/trap.h>
+#include <machine/vmparam.h>
 
 #include <ddb/ddb.h>
 #include <ddb/db_sym.h>
@@ -49,14 +50,6 @@
  */
 #define	MIPS_END_OF_FUNCTION(ins)	((ins) == 0x03e00008)
 
-#if defined(__mips_n64)
-#	define	MIPS_IS_VALID_KERNELADDR(reg)	((((reg) & 3) == 0) && \
-					((vm_offset_t)(reg) >= MIPS_XKPHYS_START))
-#else
-#	define	MIPS_IS_VALID_KERNELADDR(reg)	((((reg) & 3) == 0) && \
-					((vm_offset_t)(reg) >= MIPS_KSEG0_START))
-#endif
-
 /*
  * Functions ``special'' enough to print by name
  */


More information about the p4-projects mailing list