From owner-p4-projects@FreeBSD.ORG Wed Feb 29 05:31:32 2012 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 60CFF1065670; Wed, 29 Feb 2012 05:31:32 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 00D66106566B for ; Wed, 29 Feb 2012 05:31:32 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id DE0898FC08 for ; Wed, 29 Feb 2012 05:31:31 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id q1T5VVUb084791 for ; Wed, 29 Feb 2012 05:31:31 GMT (envelope-from gonzo@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id q1T5VVXw084788 for perforce@freebsd.org; Wed, 29 Feb 2012 05:31:31 GMT (envelope-from gonzo@FreeBSD.org) Date: Wed, 29 Feb 2012 05:31:31 GMT Message-Id: <201202290531.q1T5VVXw084788@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to gonzo@FreeBSD.org using -f From: Oleksandr Tymoshenko To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 207068 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Feb 2012 05:31:32 -0000 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 #include +#include +#include #include #include #include #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) ====