Date: Wed, 29 Feb 2012 05:31:31 GMT From: Oleksandr Tymoshenko <gonzo@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 207068 for review Message-ID: <201202290531.q1T5VVXw084788@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@207068?ac=10 Change 207068 by gonzo@gonzo_thinkpad on 2012/02/29 05:30:44 Implement userland backtrace Affected files ... .. //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/dtrace_isa.c#4 edit .. //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/regset.h#2 edit Differences ... ==== //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/dtrace_isa.c#4 (text+ko) ==== @@ -42,12 +42,17 @@ #include <vm/pmap.h> #include <machine/db_machdep.h> +#include <machine/md_var.h> +#include <machine/mips_opcode.h> #include <ddb/db_sym.h> #include <ddb/ddb.h> #include <sys/kdb.h> #include "regset.h" +#define MAX_FUNCTION_SIZE 0x1000 +#define MAX_PROLOGUE_SIZE 0x100 + int next_frame(register_t *pc, register_t *sp, uintptr_t *args, int *valid_args); @@ -108,8 +113,151 @@ void dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) { + proc_t *p = curproc; + struct trapframe *tf; + InstFmt i; + int offset, registers_on_stack; + uint32_t opcode, mask; + register_t sp, ra, pc; + register_t function_start; + int stksize; + volatile uint16_t *flags = + (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; + + if (*flags & CPU_DTRACE_FAULT) + return; + + if (pcstack_limit <= 0) + return; + + /* + * If there's no user context we still need to zero the stack. + */ + if (p == NULL || (tf = curthread->td_frame) == NULL) + goto zero; + + *pcstack++ = (uint64_t)p->p_pid; + pcstack_limit--; + + if (pcstack_limit <= 0) + return; + + pc = (uint64_t)tf->pc; + sp = (uint64_t)tf->sp; + ra = (uint64_t)tf->ra; + *pcstack++ = (uint64_t)tf->pc; + + /* + * Unwind, and unwind, and unwind + */ + while (1) { + registers_on_stack = 0; + mask = 0; + function_start = 0; + offset = 0; + stksize = 0; + + while (offset < MAX_FUNCTION_SIZE) { + opcode = dtrace_fuword32((void *)(pc - offset)); + + /* [d]addiu sp, sp, -X*/ + if (((opcode & 0xffff8000) == 0x27bd8000) + || ((opcode & 0xffff8000) == 0x67bd8000)) { + function_start = pc - offset; + registers_on_stack = 1; + break; + } + + /* lui gp, X */ + if ((opcode & 0xffff8000) == 0x3c1c0000) { + /* + * Function might start with this instruction + * Keep an eye on "jr ra" and sp correction + * with positive value further on + */ + function_start = pc - offset; + } + + if (function_start) { + /* + * Stop looking further. Possible end of + * function instruction: it means there is no + * stack modifications, sp is unchanged + */ + + /* [d]addiu sp,sp,X */ + if (((opcode & 0xffff8000) == 0x27bd0000) + || ((opcode & 0xffff8000) == 0x67bd0000)) + break; + + if (opcode == 0x03e00008) + break; + } + + offset += sizeof(int); + } + + if (!function_start) + break; + + if (registers_on_stack) { + offset = 0; + while ((offset < MAX_PROLOGUE_SIZE) + && ((function_start + offset) < pc)) { + i.word = + dtrace_fuword32((void *)(function_start + offset)); + switch (i.JType.op) { + 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); + if (i.IType.rt == 31) + ra = dtrace_fuword32((void *)(sp + (short)i.IType.imm)); + break; - printf("IMPLEMENT ME: %s\n", __func__); + 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); + /* ra */ + if (i.IType.rt == 31) + ra = dtrace_fuword64((void *)(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); + } + + offset += sizeof(int); + } + } + + pc = ra; + sp += stksize; + + *pcstack++ = pc; + pcstack_limit--; + if (pcstack_limit <= 0) + goto zero; + } + +zero: + while (pcstack_limit-- > 0) + *pcstack++ = 0; } int ==== //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/regset.h#2 (text+ko) ====
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202290531.q1T5VVXw084788>