From bf37169994c298686342ad1617c28f22bbffafc9 Mon Sep 17 00:00:00 2001 From: Stefan Ring Date: Sun, 13 Sep 2009 14:23:10 +0200 Subject: [PATCH] * src/vm/jit/mips/linux/md-os.c: Simplified signal handlers. * src/vm/jit/mips/md-trap.h (MD_TRAP_COMPILER_FIXUP): Implemented. * src/vm/jit/mips/md.c (md_trap_decode): Implemented. (like 96f53095598b) --- src/vm/jit/mips/linux/md-os.c | 144 +++------------------------------- src/vm/jit/mips/md-trap.h | 12 +++ src/vm/jit/mips/md.c | 64 ++++++++++++++- 3 files changed, 84 insertions(+), 136 deletions(-) diff --git a/src/vm/jit/mips/linux/md-os.c b/src/vm/jit/mips/linux/md-os.c index 4eeb049f8..02c978b79 100644 --- a/src/vm/jit/mips/linux/md-os.c +++ b/src/vm/jit/mips/linux/md-os.c @@ -1,6 +1,6 @@ /* src/vm/jit/mips/linux/md-os.c - machine dependent MIPS Linux functions - Copyright (C) 1996-2005, 2006, 2007, 2008 + Copyright (C) 1996-2005, 2006, 2007, 2008, 2009 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -41,9 +41,7 @@ #include "mm/memory.hpp" #include "vm/signallocal.hpp" -#include "vm/os.hpp" -#include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" #include "vm/jit/trap.hpp" @@ -77,151 +75,33 @@ void md_init(void) } -/* md_signal_handler_sigsegv *************************************************** - - NullPointerException signal handler for hardware null pointer - check. - -*******************************************************************************/ - +/** + * NullPointerException signal handler for hardware null pointer check. + */ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) { - ucontext_t *_uc; - mcontext_t *_mc; - greg_t *_gregs; - u1 *pv; - u1 *sp; - u1 *ra; - u1 *xpc; - unsigned int cause; - u4 mcode; - int d; - int s1; - int16_t disp; - intptr_t val; - intptr_t addr; - int type; - - _uc = (struct ucontext *) _p; - _mc = &_uc->uc_mcontext; - -#if defined(__UCLIBC__) - _gregs = _mc->gpregs; -#else - _gregs = _mc->gregs; -#endif - - /* In glibc's ucontext.h the registers are defined as long long, - even for MIPS32, so we cast them. This is not the case for - uClibc. */ - - pv = (u1 *) (ptrint) _gregs[REG_PV]; - sp = (u1 *) (ptrint) _gregs[REG_SP]; - ra = (u1 *) (ptrint) _gregs[REG_RA]; /* this is correct for leafs */ - -#if !defined(__UCLIBC__) -# if ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 5)) - /* NOTE: We only need this for pre glibc-2.5. */ - - xpc = (u1 *) (ptrint) _mc->pc; - - /* get the cause of this exception */ - - cause = _mc->cause; - - /* check the cause to find the faulting instruction */ - - /* TODO: use defines for that stuff */ - - switch (cause & 0x0000003c) { - case 0x00000008: - /* TLBL: XPC is ok */ - break; - - case 0x00000010: - /* AdEL: XPC is of the following instruction */ - xpc = xpc - 4; - break; - } -# else - xpc = (u1 *) (ptrint) _mc->pc; -# endif -#else - xpc = (u1 *) (ptrint) _gregs[CTX_EPC]; -#endif - - /* get exception-throwing instruction */ - - mcode = *((u4 *) xpc); - - d = M_ITYPE_GET_RT(mcode); - s1 = M_ITYPE_GET_RS(mcode); - disp = M_ITYPE_GET_IMM(mcode); - - /* check for special-load */ - - if (s1 == REG_ZERO) { - /* we use the exception type as load displacement */ - - type = disp; - val = _gregs[d]; - - if (type == TRAP_COMPILER) { - /* The XPC is the RA minus 4, because the RA points to the - instruction after the call. */ - - xpc = ra - 4; - } - } - else { - /* This is a normal NPE: addr must be NULL and the NPE-type - define is 0. */ - - addr = _gregs[s1]; - type = (int) addr; - val = 0; - } + ucontext_t* _uc = (struct ucontext *) _p; + mcontext_t* _mc = &_uc->uc_mcontext; - /* Handle the trap. */ + void* xpc = (void*) _mc->pc; - trap_handle(type, val, pv, sp, ra, xpc, _p); + // Handle the trap. + trap_handle(TRAP_SIGSEGV, xpc, _p); } /** - * Signal handler for patcher calls. + * Illegal Instruction signal handler for hardware exception checks. */ void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p) { ucontext_t* _uc = (struct ucontext *) _p; mcontext_t* _mc = &_uc->uc_mcontext; - greg_t* _gregs; - -#if defined(__UCLIBC__) - _gregs = _mc->gpregs; -#else - _gregs = _mc->gregs; -#endif - - // In glibc's ucontext.h the registers are defined as long long - // int, even for MIPS32, so we cast them. This is not the case - // for uClibc. - void* pv = (void*) (uintptr_t) _gregs[REG_PV]; - void* sp = (void*) (uintptr_t) _gregs[REG_SP]; - void* ra = (void*) (uintptr_t) _gregs[REG_RA]; // The RA is correct for leaf methods. - -#if defined(__UCLIBC__) - void* xpc = (void*) (uintptr_t) _gregs[CTX_EPC]; -#else - void* xpc = (void*) (uintptr_t) _mc->pc; -#endif - // This signal is always a patcher. - int type = TRAP_PATCHER; - intptr_t val = 0; + void* xpc = (void*) _mc->pc; // Handle the trap. - trap_handle(type, val, pv, sp, ra, xpc, _p); + trap_handle(TRAP_SIGILL, xpc, _p); } diff --git a/src/vm/jit/mips/md-trap.h b/src/vm/jit/mips/md-trap.h index 9ea8bd5c6..aeec67e64 100644 --- a/src/vm/jit/mips/md-trap.h +++ b/src/vm/jit/mips/md-trap.h @@ -64,6 +64,18 @@ enum { TRAP_PATCHER = 99 // A large number. }; + +/** + * Macro to fixup a compiler stub. The XPC is the RA minus 8, + * because the RA points to two instructions after the call. + */ +#define MD_TRAP_COMPILER_FIXUP(xpc, ra, sp, pv) \ + do { \ + (xpc) = (void*) (((uintptr_t) (ra)) - 8); \ + } while(0) + + + #endif /* _MD_TRAP_H */ diff --git a/src/vm/jit/mips/md.c b/src/vm/jit/mips/md.c index 6a83c92da..639c1cfd5 100644 --- a/src/vm/jit/mips/md.c +++ b/src/vm/jit/mips/md.c @@ -1,9 +1,7 @@ /* src/vm/jit/mips/md.c - machine dependent MIPS functions - Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008, 2009 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -144,6 +142,64 @@ void *md_jit_method_patch_address(void *pv, void *ra, void *mptr) } +/** + * Decode the trap instruction at the given PC. + * + * @param trp information about trap to be filled + * @param sig signal number + * @param xpc exception PC + * @param es execution state of the machine + * @return true if trap was decoded successfully, false otherwise. + */ +bool md_trap_decode(trapinfo_t* trp, int sig, void* xpc, executionstate_t* es) +{ + // Get the exception-throwing instruction. + uint32_t mcode = *((uint32_t*) xpc); + + switch (sig) { + case TRAP_SIGILL: + // Check for valid trap instruction. + // TODO Check the whole instruction. + if (mcode == 0xec000000) { + trp->type = TRAP_PATCHER; + trp->value = 0; + return true; + } + return false; + + case TRAP_SIGSEGV: + { + // Retrieve base address of instruction. + int32_t s1 = M_ITYPE_GET_RS(mcode); + uintptr_t addr = es->intregs[s1]; + + // Check for special-load. + if (s1 == REG_ZERO) { + int32_t d = M_ITYPE_GET_RT(mcode); + int32_t disp = M_ITYPE_GET_IMM(mcode); + + // We use the exception type as load displacement. + trp->type = disp; + trp->value = es->intregs[d]; + return true; + } + + // Check for implicit NullPointerException. + if (addr == 0) { + trp->type = TRAP_NullPointerException; + trp->value = 0; + return true; + } + + return false; + } + + default: + return false; + } +} + + /* md_patch_replacement_point ************************************************** Patch the given replacement point. -- 2.25.1