* src/vm/jit/trap.cpp (trap_handle): Further generalized trap handling and
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Thu, 12 Mar 2009 14:35:16 +0000 (15:35 +0100)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Thu, 12 Mar 2009 14:35:16 +0000 (15:35 +0100)
changed signature accordingly.
* src/vm/jit/trap.hpp (trapinfo_t): Added together with signal number defines.

* src/vm/jit/arm/linux/md-os.c: Simplified signal handlers.
* src/vm/jit/arm/md-trap.h (MD_TRAP_COMPILER_FIXUP): Implemented.
* src/vm/jit/arm/md.c (md_trap_decode): Implemented.

* src/vm/jit/x86_64/linux/md-os.c: Simplified signal handlers.
* src/vm/jit/x86_64/md-trap.h (MD_TRAP_COMPILER_FIXUP): Implemented.
* src/vm/jit/x86_64/md.c (md_trap_decode): Implemented.

--HG--
branch : new-trap-decoding

src/vm/jit/arm/linux/md-os.c
src/vm/jit/arm/md-trap.h
src/vm/jit/arm/md.c
src/vm/jit/trap.cpp
src/vm/jit/trap.hpp
src/vm/jit/x86_64/freebsd/md-os.c
src/vm/jit/x86_64/linux/md-os.c
src/vm/jit/x86_64/md-trap.h
src/vm/jit/x86_64/md.c

index 0788aa26a9ecc9341dd3625a4b8a2c56c9903216..f8d29c56757faf36fa79ee8932f71249d67c794e 100644 (file)
@@ -2,7 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-   Copyright (C) 2008 Theobroma Systems Ltd.
+   Copyright (C) 2008, 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
@@ -51,72 +51,34 @@ typedef struct ucontext {
 
 #include "threads/thread.hpp"
 
-#include "vm/os.hpp"
 #include "vm/signallocal.hpp"
-#include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/disass.h"
 #include "vm/jit/executionstate.h"
-#include "vm/jit/patcher-common.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;
-       scontext_t     *_sc;
-       u1             *pv;
-       u1             *sp;
-       u1             *ra;
-       u1             *xpc;
-       u4              mcode;
-       intptr_t        addr;
-       int             type;
-       intptr_t        val;
-
-       _uc = (ucontext_t*) _p;
-       _sc = &_uc->uc_mcontext;
+       ucontext_t* _uc = (ucontext_t*) _p;
+       scontext_t* _sc = &_uc->uc_mcontext;
 
        /* ATTENTION: glibc included messed up kernel headers we needed a
           workaround for the ucontext structure. */
 
-       pv  = (u1 *) _sc->arm_ip;
-       sp  = (u1 *) _sc->arm_sp;
-       ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
-       xpc = (u1 *) _sc->arm_pc;
-
-       /* get exception-throwing instruction */
-
-       if (xpc == NULL)
-               vm_abort("md_signal_handler_sigsegv: the program counter is NULL");
-
-       mcode = *((s4 *) xpc);
-
-       /* This is a NullPointerException. */
+       void* xpc = (u1 *) _sc->arm_pc;
 
-       addr = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + ((mcode >> 16) & 0x0f));
-       type = addr;
-       val  = 0;
-
-       /* Handle the trap. */
-
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       // Handle the trap.
+       trap_handle(TRAP_SIGSEGV, xpc, _p);
 }
 
 
-/* md_signal_handler_sigill ****************************************************
-
-   Illegal Instruction signal handler for hardware exception checks.
-
-*******************************************************************************/
-
+/**
+ * Illegal instruction signal handler for hardware exception checks.
+ */
 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 {
        ucontext_t* _uc = (ucontext_t*) _p;
@@ -125,44 +87,10 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        /* ATTENTION: glibc included messed up kernel headers we needed a
           workaround for the ucontext structure. */
 
-       void* pv  = (void*) _sc->arm_ip;
-       void* sp  = (void*) _sc->arm_sp;
-       void* ra  = (void*) _sc->arm_lr; // The RA is correct for leaf methods.
        void* xpc = (void*) _sc->arm_pc;
 
-       // Get the exception-throwing instruction.
-       uint32_t mcode = *((uint32_t*) 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).
-               // NOTE: ARM uses SIGILL for other traps too, but it's OK to
-               // do this check anyway because it will fail.
-               if (patcher_is_patched_at(xpc) == true)
-                       return;
-
-               // We have a problem...
-               log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%x", mcode, xpc);
-#if defined(ENABLE_DISASSEMBLER)
-               (void) disassinstr(xpc);
-#endif
-               vm_abort("Aborting...");
-       }
-
-       int      type = (mcode >> 8) & 0x0fff;
-       intptr_t val  = *((int32_t*) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
-
-       if (type == TRAP_COMPILER) {
-               /* The XPC is the RA minus 4, because the RA points to the
-                  instruction after the call. */
-
-               xpc = (void*) (((uintptr_t) ra) - 4);
-       }
-
        // Handle the trap.
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       trap_handle(TRAP_SIGILL, xpc, _p);
 }
 
 
index c94a8f73c553e4a6a0826b429c13d6e9a6ba4113..0c7d1f499b6c17af60ee738524e30e6187515bea 100644 (file)
@@ -54,6 +54,17 @@ enum {
        TRAP_COUNTDOWN                      = 9
 };
 
+
+/**
+ * Macro to fixup a compiler stub. The XPC is the RA minus 4,
+ * because the RA points to the instruction after the call.
+ */
+#define MD_TRAP_COMPILER_FIXUP(xpc, ra, sp, pv) \
+       do { \
+               (xpc) = (void*) (((uintptr_t) (ra)) - 4); \
+       } while(0)
+
+
 #endif /* _MD_TRAP_H */
 
 
index e4549a1b7a67bfd8eb8bc8c305adf67c5e63b658..1fecb0a8355eb936529188f0b3f1149a45780dfa 100644 (file)
@@ -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.
 
@@ -32,6 +33,9 @@
 #include "vm/jit/arm/md.h"
 #include "vm/jit/arm/md-abi.h"
 
+#include "vm/jit/executionstate.h"
+#include "vm/jit/trap.hpp"
+
 
 /* md_init *********************************************************************
 
@@ -193,6 +197,52 @@ 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.
+               if (patcher_is_valid_trap_instruction_at(xpc)) {
+                       trp->type  = (mcode >> 8) & 0x0fff;
+                       trp->value = es->intregs[mcode & 0x0f];
+                       return true;
+               }
+               return false;
+
+       case TRAP_SIGSEGV:
+       {
+               // Sanity check for load/store instruction.
+#warning Implement this!
+
+               // Retrieve base address of load/store instruction.
+               uintptr_t addr = es->intregs[(mcode >> 16) & 0x0f];
+
+               // Check for implicit NullPointerException.
+               if (addr == 0) {
+                       trp->type  = TRAP_NullPointerException;
+                       trp->value = 0;
+                       return true;
+               }
+       }
+
+       default:
+               return false;
+       }
+}
+
+
 /**
  * Patch the given replacement point.
  */
index 903faf539151f9ef3b723176a3767038333c4f4d..3f77c9746e90b59ce5b2b6ef4187dcd356595889 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
@@ -52,6 +53,7 @@
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trap.hpp"
 
 #ifdef __cplusplus
 extern "C" {
@@ -97,28 +99,26 @@ void trap_init(void)
  * Handles the signal which is generated by trap instructions, caught
  * by a signal handler and calls the correct function.
  *
- * @param type trap number
- * @param 
+ * @param sig signal number
+ * @param xpc exception PC
+ * @param context pointer to OS dependent machine context
  */
-void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context)
+void trap_handle(int sig, void *xpc, void *context)
 {
        executionstate_t es;
        stackframeinfo_t sfi;
+       trapinfo_t       trp;
 
-#if !defined(NDEBUG)
-       if (opt_TraceTraps)
-               log_println("[trap_handle: type=%d, val=%p, pv=%p, sp=%p, ra=%p, xpc=%p]", type, val, pv, sp, ra, xpc);
-#endif
-       
-#if defined(ENABLE_VMLOG)
-       vmlog_cacao_signl_type(type);
-#endif
-
-       /* Prevent compiler warnings. */
-
+       // Prevent compiler warnings.
        java_handle_t* o = NULL;
        methodinfo*    m = NULL;
 
+#if !defined(NDEBUG)
+       // Sanity checking the XPC.
+       if (xpc == NULL)
+               vm_abort("trap_handle: The program counter is NULL!");
+#endif
+
 #if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
 # if !defined(NDEBUG)
        /* Perform a sanity check on our execution state functions. */
@@ -131,8 +131,8 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
        es.code = NULL;
        md_executionstate_read(&es, context);
 
-//# define TRAPS_VERBOSE
-# if !defined(NDEBUG) && defined(TRAPS_VERBOSE)
+//# define TRAP_TRACE_VERBOSE
+# if !defined(NDEBUG) && defined(TRAP_TRACE_VERBOSE)
        /* Dump contents of execution state */
 
        if (opt_TraceTraps) {
@@ -142,6 +142,39 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
 # endif
 #endif
 
+       // Extract information from executionstate
+       void* pv = es.pv;  // Maybe null, resolved during stackframeinfo creation.
+       void* sp = es.sp;
+#if defined(__I386__) || defined(__X86_64__)
+       void* ra = xpc;  // Return address is equal to XPC.
+#else
+       void* ra = es.ra;  // This is correct for leafs.
+#endif
+
+       // Decode machine-dependent trap instruction.
+       bool decode_result = md_trap_decode(&trp, sig, xpc, &es);
+
+       // Check if the trap instruction is valid and was decoded
+       // successfully.
+       if (!decode_result) {
+               // Check if the PC has been patched during our way to this
+               // trap handler (see PR85).
+               // NOTE: Some archs use SIGILL for other traps too, but it's OK to
+               // do this check anyway because it will fail.
+               if (patcher_is_patched_at(xpc) == true) {
+                       // XXX remove this debug output!
+                       log_println("trap_handle: Detected patcher race condition (PR85) at %p", xpc);
+                       return;
+               }
+
+               // We have a problem...
+               vm_abort_disassemble(xpc, 1, "trap_handle: Unknown trap instruction at %p", xpc);
+       }
+
+       // For convenience only.
+       int      type = trp.type;
+       intptr_t val  = trp.value;
+
        /* Do some preparations before we enter the nativeworld. */
        /* BEFORE: creating stackframeinfo */
 
@@ -153,6 +186,12 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
                break;
 
        case TRAP_COMPILER:
+               /* We need to fixup the XPC, SP and RA here because they
+                  all might point into the compiler stub instead of the
+                  calling method. */
+
+               MD_TRAP_COMPILER_FIXUP(xpc, ra, sp, pv);
+
                /* In this case the passed PV points to the compiler stub.  We
                   get the methodinfo pointer here and set PV to NULL so
                   stacktrace_stackframeinfo_add determines the PV for the
@@ -160,6 +199,7 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
 
                m  = code_get_methodinfo_for_pv(pv);
                pv = NULL;
+
                break;
 
        default:
@@ -167,6 +207,16 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
                break;
        }
 
+#if !defined(NDEBUG)
+       // Trace this trap.
+       if (opt_TraceTraps)
+               log_println("[trap_handle: sig=%d, type=%d, val=%p, pv=%p, sp=%p, ra=%p, xpc=%p]", sig, type, val, pv, sp, ra, xpc);
+#endif
+
+#if defined(ENABLE_VMLOG)
+       vmlog_cacao_signl_type(type);
+#endif
+
        /* Fill and add a stackframeinfo. */
 
        stacktrace_stackframeinfo_add(&sfi, pv, sp, ra, xpc);
@@ -234,20 +284,7 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
 
                /* If that does not work, print more debug info. */
 
-               log_println("signal_handle: unknown hardware exception type %d", type);
-
-#if SIZEOF_VOID_P == 8
-               log_println("PC=0x%016lx", xpc);
-#else
-               log_println("PC=0x%08x", xpc);
-#endif
-
-#if defined(ENABLE_DISASSEMBLER)
-               log_println("machine instruction at PC:");
-               disassinstr((uint8_t*) xpc);
-#endif
-
-               vm_abort("Exiting...");
+               vm_abort_disassemble(xpc, 1, "trap_handle: Unknown hardware exception type %d", type);
 
                /* keep compiler happy */
 
@@ -279,9 +316,13 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
                p = exceptions_get_and_clear_exception();
                assert(p != NULL);
 
+               // Remove RA from stack on some archs.
+
+               es.sp = (uint8_t*) sp;
+
                // Get and set the PV from the parent Java method.
 
-               es.pv = (uint8_t *) md_codegen_get_pv_from_pc(ra);
+               es.pv = (uint8_t*) md_codegen_get_pv_from_pc(ra);
 
                // Now fall-through to default exception handling.
 
@@ -312,7 +353,7 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
 
        md_executionstate_write(&es, context);
 
-# if !defined(NDEBUG) && defined(TRAPS_VERBOSE)
+# if !defined(NDEBUG) && defined(TRAP_TRACE_VERBOSE)
        /* Dump contents of execution state */
 
        if (opt_TraceTraps) {
@@ -321,14 +362,6 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
        }
 # endif
 #endif
-
-       /* Unwrap and return the exception object. */
-       /* AFTER: removing stackframeinfo */
-
-       if (type == TRAP_COMPILER)
-               return entry;
-       else
-               return LLNI_UNWRAP(p);
 }
 
 #ifdef __cplusplus
index ce0c044c14ebedf59b94acfa8de1e43968a8791d..338921f1b7fe1186edd3997f12c1d8d01b30241a 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #include <stdint.h>
 
+#include "vm/options.h"
+
+#include "vm/jit/executionstate.h"
+
+
+/**
+ * Contains information about a decoded trap instruction.
+ */
+typedef struct trapinfo_t {
+       int      type;   ///< Specific trap type (see md-trap.h).
+       intptr_t value;  ///< Value (numeric or address) passed with the trap.
+} trapinfo_t;
+
+
+/**
+ * Trap signal number defines. Use these instead of the signal
+ * numbers provided by your specific OS.
+ */
+enum {
+       TRAP_SIGRESERVED = 0,
+       TRAP_SIGSEGV     = 1,
+       TRAP_SIGILL      = 2,
+       TRAP_SIGTRAP     = 3,
+       TRAP_SIGFPE      = 4,
+       TRAP_SIGEND
+};
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -41,8 +70,10 @@ extern "C" {
 
 /* function prototypes ********************************************************/
 
-void  trap_init(void);
-void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context);
+void trap_init(void);
+void trap_handle(int sig, void* xpc, void* context);
+
+bool md_trap_decode(trapinfo_t* trp, int sig, void* xpc, executionstate_t* es);
 
 #ifdef __cplusplus
 }
index fd9244d33d4553012885a1821d94213db37cf46d..62ac3da95a795c4f31979f30b0f99d9a90350c08 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
index ca42a1926749c1b32914fee6f36e6f4fe16db3be..ad8fbd9fdbbe56596bf8ee76789aa97cf90946cf 100644 (file)
 
 #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/trap.hpp"
-#include "vm/jit/stacktrace.hpp"
 
 
-/* md_signal_handler_sigsegv ***************************************************
-
-   Signal handler for hardware exception.
-
-*******************************************************************************/
-
+/**
+ * Signal handler for hardware exception.
+ */
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t     *_uc;
-       mcontext_t     *_mc;
-       void           *pv;
-       u1             *sp;
-       u1             *ra;
-       u1             *xpc;
-       u1              opc;
-       u1              mod;
-       u1              rm;
-       s4              d;
-       s4              disp;
-       int             type;
-       intptr_t        val;
-       void           *p;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
+       ucontext_t* _uc = (ucontext_t *) _p;
+       mcontext_t* _mc = &_uc->uc_mcontext;
 
        /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
           different to the ones in <ucontext.h>. */
 
-       pv  = NULL;                 /* is resolved during stackframeinfo creation */
-       sp  = (u1 *) _mc->gregs[REG_RSP];
-       xpc = (u1 *) _mc->gregs[REG_RIP];
-       ra  = xpc;                              /* return address is equal to XPC */
-
-#if 0
-       /* check for StackOverflowException */
-
-       threads_check_stackoverflow(sp);
-#endif
-
-       /* 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 == 4)) {
-               /* 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;
-
-               /* XXX FIX ME! */
-
-               /* ATTENTION: The _mc->gregs layout is even worse than on
-                  i386! See /usr/include/sys/ucontext.h.  We need a
-                  switch-case here... */
-
-               switch (d) {
-               case 0:  /* REG_RAX == 13 */
-                       d = REG_RAX;
-                       break;
-               case 1:  /* REG_RCX == 14 */
-                       d = REG_RCX;
-                       break;
-               case 2:  /* REG_RDX == 12 */
-                       d = REG_RDX;
-                       break;
-               case 3:  /* REG_RBX == 11 */
-                       d = REG_RBX;
-                       break;
-               case 4:  /* REG_RSP == 15 */
-                       d = REG_RSP;
-                       break;
-               case 5:  /* REG_RBP == 10 */
-                       d = REG_RBP;
-                       break;
-               case 6:  /* REG_RSI == 9  */
-                       d = REG_RSI;
-                       break;
-               case 7:  /* REG_RDI == 8  */
-                       d = REG_RDI;
-                       break;
-               case 8:  /* REG_R8  == 0  */
-               case 9:  /* REG_R9  == 1  */
-               case 10: /* REG_R10 == 2  */
-               case 11: /* REG_R11 == 3  */
-               case 12: /* REG_R12 == 4  */
-               case 13: /* REG_R13 == 5  */
-               case 14: /* REG_R14 == 6  */
-               case 15: /* REG_R15 == 7  */
-                       d = d - 8;
-                       break;
-               }
-
-               val = _mc->gregs[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 1, because the RA points to the
-                          instruction after the call. */
-
-                       xpc = ra - 3;
-               }
-       }
-       else {
-               /* this was a normal NPE */
-
-               type = TRAP_NullPointerException;
-               val  = 0;
-       }
-
-       /* Handle the trap. */
-
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
-       /* Set registers. */
+       void* xpc = (void*) _mc->gregs[REG_RIP];
 
-       if (type == TRAP_COMPILER) {
-               if (p == NULL) {
-                       _mc->gregs[REG_RSP] = (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.
-
-*******************************************************************************/
-
+/**
+ * ArithmeticException signal handler for hardware divide by zero
+ * 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;
-       int             type;
-       intptr_t        val;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
+       ucontext_t* _uc = (ucontext_t *) _p;
+       mcontext_t* _mc = &_uc->uc_mcontext;
 
        /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
           different to the ones in <ucontext.h>. */
 
-       pv  = NULL;
-       sp  = (u1 *) _mc->gregs[REG_RSP];
-       xpc = (u1 *) _mc->gregs[REG_RIP];
-       ra  = xpc;                          /* return address is equal to xpc     */
-
-       /* This is an ArithmeticException. */
-
-       type = TRAP_ArithmeticException;
-       val  = 0;
-
-       /* Handle the trap. */
+       void* xpc = (void*) _mc->gregs[REG_RIP];
 
-       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 patchers.
-
-*******************************************************************************/
-
+/**
+ * Signal handler for patchers.
+ */
 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;
-       int             type;
-       intptr_t        val;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
+       ucontext_t* _uc = (ucontext_t *) _p;
+       mcontext_t* _mc = &_uc->uc_mcontext;
 
        /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
           different to the ones in <ucontext.h>. */
 
-       pv  = NULL;
-       sp  = (u1 *) _mc->gregs[REG_RSP];
-       xpc = (u1 *) _mc->gregs[REG_RIP];
-       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...");
-       }
-
-       /* This is a patcher. */
-
-       type = TRAP_PATCHER;
-       val  = 0;
-
-       /* Handle the trap. */
+       void* xpc = (void*) _mc->gregs[REG_RIP];
 
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       // Handle the trap.
+       trap_handle(TRAP_SIGILL, xpc, _p);
 }
 
 
@@ -362,6 +176,9 @@ void md_executionstate_read(executionstate_t *es, void *context)
        _uc = (ucontext_t *) context;
        _mc = &_uc->uc_mcontext;
 
+       /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+          different to the ones in <ucontext.h>. */
+
        /* read special registers */
        es->pc = (u1 *) _mc->gregs[REG_RIP];
        es->sp = (u1 *) _mc->gregs[REG_RSP];
@@ -433,6 +250,9 @@ void md_executionstate_write(executionstate_t *es, void *context)
        _uc = (ucontext_t *) context;
        _mc = &_uc->uc_mcontext;
 
+       /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+          different to the ones in <ucontext.h>. */
+
        /* write integer registers */
        for (i = 0; i < INT_REG_CNT; i++) {
                /* XXX FIX ME! */
index c78e31b9540031ca1567b81d8b9a6803662dfc60..8b09e3c6e8d50a0e5b2fa21e493d78c5cf4f6ec7 100644 (file)
@@ -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 1, 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)) - 3); \
+       } while(0)
+
+
 #endif /* _MD_TRAP_H */
 
 
index 586550cfd485340406a80c301f65564c815e50f2..cf682e09f76b387c7814716abf7124b776596774 100644 (file)
@@ -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.
 
 #include <stdint.h>
 #include <stdlib.h>
 
+#include "vm/jit/x86_64/codegen.h"
 #include "vm/jit/x86_64/md-abi.h"
 
 #include "vm/vm.hpp"
 
 #include "vm/jit/codegen-common.hpp"
+#include "vm/jit/executionstate.h"
 #include "vm/jit/jit.hpp"
+#include "vm/jit/trap.hpp"
 
 
 /* md_init *********************************************************************
@@ -135,6 +139,73 @@ 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;
+
+#if 0
+       // Check for StackOverflowException.
+       threads_check_stackoverflow(sp);
+#endif
+
+       switch (sig) {
+       case TRAP_SIGFPE:
+               // Check for 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 == 4)) {
+                       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.