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