⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 segvhandler_arch.c

📁 This is a resource based on j2me embedded,if you dont understand,you can connection with me .
💻 C
字号:
/* * @(#)segvhandler_arch.c	1.10 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program is distributed in the hope that it will be useful, but   * WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * General Public License version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */#if defined(CVM_JIT) || defined(CVM_USE_MEM_MGR)#include "javavm/include/defs.h"#include "javavm/include/globals.h"#ifdef CVM_JIT#include "javavm/include/porting/jit/jit.h"#include "javavm/include/jit/jitcodebuffer.h"#endif#include "javavm/include/porting/memory.h"#ifdef CVM_USE_MEM_MGR#include "javavm/include/mem_mgr.h"#endif#include "portlibs/jit/risc/include/porting/ccmrisc.h"#include <signal.h>#include <dlfcn.h>#include <stddef.h>/* avoid conflicting ucontext definitions */#define ucontext asm_ucontext#include <asm/ucontext.h>#include <unistd.h>#define MAXSIGNUM 32#define MASK(sig) ((CVMUint32)1 << sig)static struct sigaction sact[MAXSIGNUM];static unsigned int cvmSignals = 0; /* signals used by cvm */static CVMBool cvmSignalInstalling = CVM_FALSE;/*  * Call pthread's __sigaction  */typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);static char* sysSigactionName[] = {"sigaction", "__sigaction"};static sigaction_t sysSigaction[2] = {0, 0};intcallSysSigaction(int sig, const struct sigaction *act,                 struct sigaction *oact, int idx){    if (sysSigaction[idx] == NULL) {#ifdef LINUX_DLSYM_BUG        void * handle = dlopen("libpthread.so.0", RTLD_LAZY);        if (handle != NULL) {	    sysSigaction[idx] = (sigaction_t)dlsym(handle, sysSigactionName[idx]);	    dlclose(handle);        }#else        sysSigaction[idx] = (sigaction_t)dlsym(RTLD_NEXT, sysSigactionName[idx]);#endif        if (sysSigaction[idx] == NULL) {	    CVMdebugPrintf(("WARNING: lookup of __sigaction failed."));            return -1;        }    }    return (*sysSigaction[idx])(sig, act, oact);}/*  * Override sigaction to chain signal handler.  */int CVMsigaction(int sig, const struct sigaction *act,              struct sigaction *oact, int idx){    struct sigaction oldAct;    if (cvmSignalInstalling) {        int result = 0;        if (act != NULL) {	    /* CVM is installing handler for this signal. Install the new               handler and save the old one. */            result = callSysSigaction(sig, act, &oldAct, idx);            if (result != -1) {                sact[sig] = oldAct;                if (oact != NULL) {                    *oact = oldAct;                }                cvmSignals |= MASK(sig); /* Mark the signal as used by CVM */            }        }        return result;    } else {        if ((MASK(sig) & cvmSignals) != 0) {	    /* CVM has installed its signal handler for this signal. Chain the               new handler. */	    if (oact != NULL) {                *oact = sact[sig];	    }            if (act != NULL) {                sact[sig] = *act;            }            return 0;        } else {	    /* The signal is not used by CVM. Install the new handler.*/            return callSysSigaction(sig, act, oact, idx);        }    }}intsigaction(int sig, const struct sigaction *act, struct sigaction *oact){    return CVMsigaction(sig, act, oact, 0);}int __sigaction(int sig, const struct sigaction *act, struct sigaction *oact){    return CVMsigaction(sig, act, oact, 1);}#ifdef CVM_USE_MEM_MGRstatic CVMUint32 getRegContent(int regNo, struct ucontext* ucp){    switch (regNo) {    case 0: return (CVMUint32)ucp->uc_mcontext.arm_r0;    case 1: return (CVMUint32)ucp->uc_mcontext.arm_r1;    case 2: return (CVMUint32)ucp->uc_mcontext.arm_r2;    case 3: return (CVMUint32)ucp->uc_mcontext.arm_r3;    case 4: return (CVMUint32)ucp->uc_mcontext.arm_r4;    case 5: return (CVMUint32)ucp->uc_mcontext.arm_r5;    case 6: return (CVMUint32)ucp->uc_mcontext.arm_r6;    case 7: return (CVMUint32)ucp->uc_mcontext.arm_r7;    case 8: return (CVMUint32)ucp->uc_mcontext.arm_r8;    case 9: return (CVMUint32)ucp->uc_mcontext.arm_r9;    case 10: return (CVMUint32)ucp->uc_mcontext.arm_r10;    case 11: return (CVMUint32)ucp->uc_mcontext.arm_fp;    case 12: return (CVMUint32)ucp->uc_mcontext.arm_ip;    case 13: return (CVMUint32)ucp->uc_mcontext.arm_sp;    case 14: return (CVMUint32)ucp->uc_mcontext.arm_lr;    case 15: return (CVMUint32)ucp->uc_mcontext.arm_pc;    default: CVMassert(CVM_FALSE); return 0;    }}#define STR_OPCODE  0x04000000#define STRB_OPCODE 0x04400000#define STRH_OPCODE 0x004000b0static void decodeAtPCAndWrite(struct ucontext* ucp){    CVMUint32 pagesize = sysconf(_SC_PAGESIZE);    CVMUint32* pc = (CVMUint32*)(ucp->uc_mcontext.arm_pc);    CVMUint32* faultAddr = (CVMUint32 *)ucp->uc_mcontext.fault_address;    CVMUint32* startAddr = (CVMUint32*)((CVMUint32)faultAddr &                                                   ~(pagesize-1));    CVMUint32 pc_instr = *pc;        if ((pc_instr & STRB_OPCODE) == STRB_OPCODE ||        (pc_instr & STRH_OPCODE) == STRH_OPCODE ||        (pc_instr & STR_OPCODE) == STR_OPCODE) {        int srcRegNo = (pc_instr & 0xF000) >> 12;        CVMUint32 srcReg = getRegContent(srcRegNo, ucp);                /* Unprotect the page that contains xthe faulting address */        CVMmprotect(startAddr, (void*)((CVMUint32)startAddr + pagesize),                    CVM_FALSE);        /* Emulate the write. */        if ((pc_instr & STRB_OPCODE) == STRB_OPCODE) {            *(CVMUint8*)faultAddr= (CVMUint8)srcReg;        } else if ((pc_instr & STRH_OPCODE) == STRH_OPCODE) {            *(CVMUint16*)faultAddr= (CVMUint16)srcReg;        } else {            *faultAddr = srcReg;        }        /* Re-protect the page */        /* Always re-protect a page after a write, because it hard to         * tell if part of a CVM_MEM_MON_FIRST_WRITE page also belongs         * a CVM_MEM_MON_ALL_WRITES. We use the dirty page map to control         * the notify instead.         */        CVMmprotect(startAddr,                     (void*)((CVMUint32)startAddr + pagesize),                    CVM_TRUE);      } else {        CVMassert(CVM_FALSE);    }}#endif /* CVM_USE_MEM_MGR *//* * SEGV handler */#ifndef LINUX_ARM_SIGINFO_BUGstatic void handleSegv(int sig, siginfo_t* info, void* ucpPtr)#else /* LINUX_ARM_SIGINFO_BUG */static void handleSegv(int sig, int a2, int a3, int a4,		       siginfo_t* info, struct ucontext* ucp)#endif /* LINUX_ARM_SIGINFO_BUG */{#ifndef LINUX_ARM_SIGINFO_BUG    struct ucontext* ucp = (struct ucontext *)ucpPtr;#endif /* LINUX_ARM_SIGINFO_BUG */    int pid = getpid();    CVMUint32* pc = (CVMUint32 *)ucp->uc_mcontext.arm_pc;#ifdef CVM_USE_MEM_MGR    CVMUint32* faultAddr = (CVMUint32 *)ucp->uc_mcontext.fault_address;    CVMBool isValidAddr;    isValidAddr = CVMMemWriteNotify(pid, faultAddr, pc);    /* If it's gcTrapInstr or NullPointerException, the faultAddr usually     * is an invalid address.     */    if (isValidAddr) {        /* Emulate the write */        decodeAtPCAndWrite(ucp);        /* skip the write instruction */        ucp->uc_mcontext.arm_pc += 4;        return;    }#endif#ifdef CVM_JIT    if (CVMJITcodeCacheInCompiledMethod((CVMUint8*)pc)) {	/* Coming from compiled code. */#ifdef CVMJIT_TRAP_BASED_GC_CHECKS#define ARM_LOADSTORE_ADDOFFSET	0x00800000	/* U bit */	{	    CVMCPUInstruction gcTrapInstr = *(CVMCPUInstruction*)pc;	    /* ldr offset in lower 12 bits */	    int offset = gcTrapInstr & 0xfff;	    if ((gcTrapInstr & ARM_LOADSTORE_ADDOFFSET) == 0) {		offset = -offset; /* make negative */	    }	    gcTrapInstr = gcTrapInstr & CVMCPU_GCTRAP_INSTRUCTION_MASK;	    if (gcTrapInstr == CVMCPU_GCTRAP_INSTRUCTION) {		if (offset >= 0) {		    /* set link register to return to just before the trap		     * instruction where incoming locals are reloaded. */		    ucp->uc_mcontext.arm_lr = ucp->uc_mcontext.arm_pc - offset;		    /* Branch to do a gc rendezvous */		    ucp->uc_mcontext.arm_pc =			(unsigned long)CVMCCMruntimeGCRendezvousGlue;		} else {		    /* phi handling: branch to generated code that will		     * spill phis, call CVMCCMruntimeGCRendezvousGlue, and		     * then reload phis.		     */		    ucp->uc_mcontext.arm_pc += offset;		}#if 0		fprintf(stderr, "redirecting to rendezvous code 0x%x 0x%x\n",			(int)ucp->uc_mcontext.arm_pc,			(int)ucp->uc_mcontext.arm_lr);#endif		return;	    }	}#endif#ifdef CVMJIT_TRAP_BASED_NULL_CHECKS	/* Branch and link to throw null pointer exception glue */	ucp->uc_mcontext.arm_lr = ucp->uc_mcontext.arm_pc + 4;	ucp->uc_mcontext.arm_pc =	    (unsigned long)CVMCCMruntimeThrowNullPointerExceptionGlue;	return;#endif    } else if (CVMJITcodeCacheInCCM((CVMUint8*)pc)) {#ifdef CVMJIT_TRAP_BASED_NULL_CHECKS	/* Coming from CCM code. */	/* Branch to throw null pointer exception glue */	ucp->uc_mcontext.arm_pc =	    (unsigned long)CVMCCMruntimeThrowNullPointerExceptionGlue;	return;#endif /* CVMJIT_TRAP_BASED_NULL_CHECKS */    }#endif /* CVM_JIT */#ifdef CVM_DEBUG    {	fprintf(stderr, "Process #%d received signal %d\n", pid, sig);	/* A real one. Suspend thread */	fprintf(stderr, "Process #%d being suspended\n", pid);		kill(pid, SIGSTOP);    }#else    /* Call chained handler */    {        struct sigaction sa = sact[sig];        if ((sa.sa_flags & SA_SIGINFO) != 0) {            (*(sa.sa_sigaction))(sig, info, ucp);        } else {            if (sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL) {                fprintf(stderr, "Process #%d received signal %d\n", pid, sig);                fprintf(stderr, "Process #%d being suspended\n", pid);                kill(pid, SIGSTOP);            } else {                (*(sa.sa_handler))(sig);            }        }    }#endif}/* * Install specific handlers for JIT exception handling */CVMBoollinuxSegvHandlerInit(void){    int signals[] = {SIGSEGV};    int i;    int result = 0;        /* The AAPCS check has nothing to do with signals, this is merely       the only existing arm-specific code where we can check that the       setting of -DAAPCS at build matches the calling and alignment       convention.  Even so, the check will be done only if this code       is actually compiled, e.g., CVM_JIT=true.  If AAPCS is in use,       doubles are 8-byte aligned, otherwise they are 4-byte       aligned. */    if (offsetof(struct { int i; double d; }, d) == 8) {#if !defined(AAPCS)	CVMpanic("AAPCS calling convention used;"		 " compilation must use -DAAPCS.\n");#endif    } else {#if defined(AAPCS)	CVMpanic("AAPCS calling convention not used;"		 " compilation must not use -DAAPCS.\n");#endif    }    cvmSignalInstalling = CVM_TRUE;    for (i = 0; result != -1 && i < (sizeof signals / sizeof signals[0]); ++i){        struct sigaction sa;#ifndef LINUX_ARM_SIGINFO_BUG        sa.sa_sigaction = handleSegv;#else /* LINUX_ARM_SIGINFO_BUG */        sa.sa_sigaction = (void(*)(int,siginfo_t*,void*))handleSegv;#endif /* LINUX_ARM_SIGINFO_BUG */        sa.sa_flags = SA_RESTART | SA_SIGINFO;        sigemptyset(&sa.sa_mask);#ifndef LINUX_ARM_SIGINFO_BUG        result = sigaction(signals[i], &sa, NULL);#else /* LINUX_ARM_SIGINFO_BUG */        result = __sigaction(signals[i], &sa, NULL);#endif /* LINUX_ARM_SIGINFO_BUG */    }    cvmSignalInstalling = CVM_FALSE;    return (result != -1);}#endif /* defined(CVM_JIT) || defined(CVM_USE_MEM_MGR) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -