Date: Wed, 29 Feb 2012 20:45:26 GMT From: Oleksandr Tymoshenko <gonzo@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 207111 for review Message-ID: <201202292045.q1TKjQ1k068829@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@207111?ac=10 Change 207111 by gonzo@gonzo_thinkpad on 2012/02/29 20:44:22 - Refactor userland backtrace in order to reuse code for dtrace_getustackdepth Affected files ... .. //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/dtrace_isa.c#7 edit Differences ... ==== //depot/projects/dtrace-mips/sys/cddl/dev/dtrace/mips/dtrace_isa.c#7 (text+ko) ==== @@ -65,6 +65,8 @@ uint32_t dtrace_fuword32_nocheck(void *); uint64_t dtrace_fuword64_nocheck(void *); +static int dtrace_next_uframe(register_t *pc, register_t *sp, register_t *ra); + void dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, uint32_t *intrpc) @@ -119,12 +121,7 @@ { 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; @@ -155,114 +152,14 @@ * 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; - - 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); - } - } - - /* - * We reached the end of backtrace - */ - if (pc == ra) + if (dtrace_next_uframe(&pc, &sp, &ra) < 0) break; - pc = ra; - sp += stksize; - *pcstack++ = pc; pcstack_limit--; + if (pcstack_limit <= 0) - goto zero; + break; } zero: @@ -274,8 +171,32 @@ dtrace_getustackdepth(void) { int n = 0; + proc_t *p = curproc; + struct trapframe *tf; + register_t sp, ra, pc; + volatile uint16_t *flags = + (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; + + if (*flags & CPU_DTRACE_FAULT) + return (0); + + if (p == NULL || (tf = curthread->td_frame) == NULL) + return (0); - printf("IMPLEMENT ME: %s\n", __func__); + pc = (uint64_t)tf->pc; + sp = (uint64_t)tf->sp; + ra = (uint64_t)tf->ra; + n++; + + /* + * Unwind, and unwind, and unwind + */ + while (1) { + if (dtrace_next_uframe(&pc, &sp, &ra) < 0) + break; + n++; + } + return (n); } @@ -362,6 +283,122 @@ } static int +dtrace_next_uframe(register_t *pc, register_t *sp, register_t *ra) +{ + int offset, registers_on_stack; + uint32_t opcode, mask; + register_t function_start; + int stksize; + InstFmt i; + + 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) + return (-1); + + 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; + + 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); + } + } + + /* + * We reached the end of backtrace + */ + if (*pc == *ra) + return (-1); + + *pc = *ra; + *sp += stksize; + + return (0); +} + +static int dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202292045.q1TKjQ1k068829>
