From b307ed446ce8893052cd4774fcb2298cf4d7a4db Mon Sep 17 00:00:00 2001 From: Michael Starzinger Date: Mon, 23 Mar 2009 13:43:51 +0100 Subject: [PATCH] * src/vm/jit/i386/linux/md-os.c: Simplified signal handlers. * src/vm/jit/i386/md-trap.h (MD_TRAP_COMPILER_FIXUP): Implemented. * src/vm/jit/i386/md.c (md_trap_decode): Implemented. * src/vm/jit/trap.cpp (trap_handle) [__I386__]: Fixed minor conflict. --HG-- branch : new-trap-decoding --- src/vm/jit/i386/linux/md-os.c | 192 +++++----------------------------- src/vm/jit/i386/md-trap.h | 19 ++++ src/vm/jit/i386/md.c | 66 ++++++++++++ src/vm/jit/trap.cpp | 2 +- 4 files changed, 112 insertions(+), 167 deletions(-) diff --git a/src/vm/jit/i386/linux/md-os.c b/src/vm/jit/i386/linux/md-os.c index 1f72d58d2..1417ec01a 100644 --- a/src/vm/jit/i386/linux/md-os.c +++ b/src/vm/jit/i386/linux/md-os.c @@ -2,6 +2,7 @@ Copyright (C) 1996-2005, 2006, 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -37,196 +38,55 @@ #include "threads/thread.hpp" -#include "vm/jit/builtin.hpp" #include "vm/signallocal.hpp" -#include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" -#include "vm/jit/stacktrace.hpp" #include "vm/jit/trap.hpp" -/* md_signal_handler_sigsegv *************************************************** - - Signal handler for hardware exceptions. - -*******************************************************************************/ - +/** + * Signal handler for hardware exceptions. + */ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) { - ucontext_t *_uc; - mcontext_t *_mc; - u1 *pv; - u1 *sp; - u1 *ra; - u1 *xpc; - u1 opc; - u1 mod; - u1 rm; - s4 d; - s4 disp; - ptrint val; - s4 type; - void *p; - - _uc = (ucontext_t *) _p; - _mc = &_uc->uc_mcontext; - - pv = NULL; /* is resolved during stackframeinfo creation */ - sp = (u1 *) _mc->gregs[REG_ESP]; - xpc = (u1 *) _mc->gregs[REG_EIP]; - ra = xpc; /* return address is equal to XPC */ - - /* get exception-throwing instruction */ - - opc = M_ALD_MEM_GET_OPC(xpc); - mod = M_ALD_MEM_GET_MOD(xpc); - rm = M_ALD_MEM_GET_RM(xpc); - - /* for values see emit_mov_mem_reg and emit_mem */ - - if ((opc == 0x8b) && (mod == 0) && (rm == 5)) { - /* this was a hardware-exception */ - - d = M_ALD_MEM_GET_REG(xpc); - disp = M_ALD_MEM_GET_DISP(xpc); - - /* we use the exception type as load displacement */ - - type = disp; - - /* ATTENTION: The _mc->gregs layout is completely crazy! The - registers are reversed starting with number 4 for REG_EDI - (see /usr/include/sys/ucontext.h). We have to convert that - here. */ - - val = _mc->gregs[REG_EAX - d]; - - if (type == TRAP_COMPILER) { - /* The PV from the compiler stub is equal to the XPC. */ - - pv = xpc; - - /* We use a framesize of zero here because the call pushed - the return addres onto the stack. */ - - ra = md_stacktrace_get_returnaddress(sp, 0); - - /* Skip the RA on the stack. */ - - sp = sp + 1 * SIZEOF_VOID_P; - - /* The XPC is the RA minus 2, because the RA points to the - instruction after the call. */ - - xpc = ra - 2; - } - } - else { - /* this was a normal NPE */ + ucontext_t* _uc = (ucontext_t *) _p; + mcontext_t* _mc = &_uc->uc_mcontext; - type = TRAP_NullPointerException; - val = 0; - } + void* xpc = (void*) _mc->gregs[REG_EIP]; - /* Handle the trap. */ - - p = trap_handle(type, val, pv, sp, ra, xpc, _p); - - /* Set registers. */ - - if (type == TRAP_COMPILER) { - if (p == NULL) { - _mc->gregs[REG_ESP] = (uintptr_t) sp; /* Remove RA from stack. */ - } - } + // Handle the trap. + trap_handle(TRAP_SIGSEGV, xpc, _p); } -/* md_signal_handler_sigfpe **************************************************** - - ArithmeticException signal handler for hardware divide by zero - check. - -*******************************************************************************/ - +/** + * Signal handler for hardware divide by zero (ArithmeticException) + * check. + */ void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p) { - ucontext_t *_uc; - mcontext_t *_mc; - u1 *pv; - u1 *sp; - u1 *ra; - u1 *xpc; - s4 type; - ptrint val; - - _uc = (ucontext_t *) _p; - _mc = &_uc->uc_mcontext; - - pv = NULL; /* is resolved during stackframeinfo creation */ - sp = (u1 *) _mc->gregs[REG_ESP]; - xpc = (u1 *) _mc->gregs[REG_EIP]; - ra = xpc; /* return address is equal to xpc */ - - /* This is an ArithmeticException. */ + ucontext_t* _uc = (ucontext_t *) _p; + mcontext_t* _mc = &_uc->uc_mcontext; - type = TRAP_ArithmeticException; - val = 0; + void* xpc = (void*) _mc->gregs[REG_EIP]; - /* Handle the trap. */ - - trap_handle(type, val, pv, sp, ra, xpc, _p); + // Handle the trap. + trap_handle(TRAP_SIGFPE, xpc, _p); } -/* md_signal_handler_sigill **************************************************** - - Signal handler for hardware patcher traps (ud2). - -*******************************************************************************/ - +/** + * Signal handler for hardware patcher traps (ud2). + */ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p) { - ucontext_t *_uc; - mcontext_t *_mc; - u1 *pv; - u1 *sp; - u1 *ra; - u1 *xpc; - s4 type; - ptrint val; - - _uc = (ucontext_t *) _p; - _mc = &_uc->uc_mcontext; - - pv = NULL; /* is resolved during stackframeinfo creation */ - sp = (u1 *) _mc->gregs[REG_ESP]; - xpc = (u1 *) _mc->gregs[REG_EIP]; - ra = xpc; /* return address is equal to xpc */ - - // Check if the trap instruction is valid. - // TODO Move this into patcher_handler. - if (patcher_is_valid_trap_instruction_at(xpc) == false) { - // Check if the PC has been patched during our way to this - // signal handler (see PR85). - if (patcher_is_patched_at(xpc) == true) - return; - - // We have a problem... - log_println("md_signal_handler_sigill: Unknown illegal instruction at 0x%lx", xpc); -#if defined(ENABLE_DISASSEMBLER) - (void) disassinstr(xpc); -#endif - vm_abort("Aborting..."); - } - - type = TRAP_PATCHER; - val = 0; + ucontext_t* _uc = (ucontext_t *) _p; + mcontext_t* _mc = &_uc->uc_mcontext; - /* Handle the trap. */ + void* xpc = (void*) _mc->gregs[REG_EIP]; - trap_handle(type, val, pv, sp, ra, xpc, _p); + // Handle the trap. + trap_handle(TRAP_SIGILL, xpc, _p); } diff --git a/src/vm/jit/i386/md-trap.h b/src/vm/jit/i386/md-trap.h index 52e6a0067..6cf2bbf20 100644 --- a/src/vm/jit/i386/md-trap.h +++ b/src/vm/jit/i386/md-trap.h @@ -62,6 +62,25 @@ enum { TRAP_END }; + +/** +* Macro to fixup a compiler stub. +* PV : The PV from the compiler stub is equal to the XPC. +* RA : We use a framesize of zero here because the call pushed +* the return addres onto the stack. +* SP : Skip the RA on the stack. +* XPC: The XPC is the RA minus 2, because the RA points to the +* instruction after the call. +*/ +#define MD_TRAP_COMPILER_FIXUP(xpc, ra, sp, pv) \ + do { \ + (pv) = (xpc); \ + (ra) = md_stacktrace_get_returnaddress((sp), 0); \ + (sp) = (void*) (((uintptr_t) (sp)) + 1 * SIZEOF_VOID_P); \ + (xpc) = (void*) (((uintptr_t) (ra)) - 2); \ + } while(0) + + #endif /* _MD_TRAP_H */ diff --git a/src/vm/jit/i386/md.c b/src/vm/jit/i386/md.c index 191cddabd..4b9a02a43 100644 --- a/src/vm/jit/i386/md.c +++ b/src/vm/jit/i386/md.c @@ -2,6 +2,7 @@ Copyright (C) 1996-2005, 2006, 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -30,11 +31,14 @@ #include "vm/types.h" +#include "vm/jit/i386/codegen.h" + #include "vm/global.h" #include "vm/vm.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/jit.hpp" +#include "vm/jit/trap.hpp" /* md_init ********************************************************************* @@ -129,6 +133,68 @@ 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) +{ + uint8_t* xpc = (uint8_t*) _xpc; + + switch (sig) { + case TRAP_SIGFPE: + // This is an ArithmeticException. + trp->type = TRAP_ArithmeticException; + trp->value = 0; + return true; + + case TRAP_SIGILL: + // Check for valid trap instruction. + if (patcher_is_valid_trap_instruction_at(xpc)) { + trp->type = TRAP_PATCHER; + trp->value = 0; + return true; + } + return false; + + case TRAP_SIGSEGV: + { + // Get exception-throwing instruction. + uint8_t opc = M_ALD_MEM_GET_OPC(xpc); + uint8_t mod = M_ALD_MEM_GET_MOD(xpc); + uint8_t rm = M_ALD_MEM_GET_RM(xpc); + + // Check for hardware exception, for values + // see emit_mov_mem_reg and emit_mem. + if ((opc == 0x8b) && (mod == 0) && (rm == 5)) { + int32_t d = M_ALD_MEM_GET_REG(xpc); + int32_t disp = M_ALD_MEM_GET_DISP(xpc); + + // We use the exception type as load displacement. + trp->type = disp; + trp->value = es->intregs[d]; + return true; + } + + // Default case is a normal NullPointerException. + else { + trp->type = TRAP_NullPointerException; + trp->value = 0; + return true; + } + } + + default: + return false; + } +} + + /* md_patch_replacement_point ************************************************** Patch the given replacement point. diff --git a/src/vm/jit/trap.cpp b/src/vm/jit/trap.cpp index 3f77c9746..3f95aaa90 100644 --- a/src/vm/jit/trap.cpp +++ b/src/vm/jit/trap.cpp @@ -271,7 +271,7 @@ void trap_handle(int sig, void *xpc, void *context) #if defined(ENABLE_REPLACEMENT) case TRAP_COUNTDOWN: # if defined(__I386__) - replace_me_wrapper((char*)xpc - 13, context); + replace_me_wrapper((uint8_t*) xpc - 13, context); # endif p = NULL; break; -- 2.25.1