Merged with new-trap-decoding branch at rev a792088a3f04 (branch closed).
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Wed, 15 Apr 2009 15:04:15 +0000 (17:04 +0200)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Wed, 15 Apr 2009 15:04:15 +0000 (17:04 +0200)
23 files changed:
src/vm/jit/alpha/linux/md-os.c
src/vm/jit/alpha/md-trap.h
src/vm/jit/alpha/md.c
src/vm/jit/arm/linux/md-os.c
src/vm/jit/arm/md-trap.h
src/vm/jit/arm/md.c
src/vm/jit/i386/darwin/md-os.c
src/vm/jit/i386/linux/md-os.c
src/vm/jit/i386/md-trap.h
src/vm/jit/i386/md.c
src/vm/jit/powerpc/linux/md-os.c
src/vm/jit/powerpc/md-trap.h
src/vm/jit/powerpc/md.c
src/vm/jit/powerpc64/linux/md-os.c
src/vm/jit/powerpc64/md-trap.h
src/vm/jit/powerpc64/md.c
src/vm/jit/powerpc64/patcher.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 b81ff2bc733c59c22b79348514f80e6cb1d06dab..c6eb6b1287c335d294206761d3e7d5fd6e0ff38e 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.
 
 
 #include "threads/thread.hpp"
 
-#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.hpp"
-#include "vm/os.hpp"
 
-#include "vm/jit/asmpart.h"
-#include "vm/jit/disass.h"
 #include "vm/jit/executionstate.h"
 #include "vm/jit/trap.hpp"
 
 
-/* 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;
-       u1             *pv;
-       u1             *sp;
-       u1             *ra;
-       u1             *xpc;
-       u4              mcode;
-       s4              d;
-       s4              s1;
-       s4              disp;
-       intptr_t        val;
-       intptr_t        addr;
-       int             type;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
-
-       pv  = (u1 *) _mc->sc_regs[REG_PV];
-       sp  = (u1 *) _mc->sc_regs[REG_SP];
-       ra  = (u1 *) _mc->sc_regs[REG_RA];           /* this is correct for leafs */
-       xpc = (u1 *) _mc->sc_pc;
-
-       /* get exception-throwing instruction */
-
-       mcode = *((u4 *) xpc);
-
-       d    = M_MEM_GET_Ra(mcode);
-       s1   = M_MEM_GET_Rb(mcode);
-       disp = M_MEM_GET_Memory_disp(mcode);
-
-       val  = _mc->sc_regs[d];
-
-       /* check for special-load */
-
-       if (s1 == REG_ZERO) {
-               /* we use the exception type as load displacement */
-
-               type = disp;
-
-               if (type == TRAP_COMPILER) {
-                       /* The XPC is the RA minus 1, 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 = _mc->sc_regs[s1];
-               type = (int) addr;
-       }
+       ucontext_t* _uc = (ucontext_t *) _p;
+       mcontext_t* _mc = &_uc->uc_mcontext;
 
-       /* Handle the trap. */
+       void* xpc = (void*) _mc->sc_pc;
 
-       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;
        mcontext_t* _mc = &_uc->uc_mcontext;
 
-       void* pv  = (u1 *) _mc->sc_regs[REG_PV];
-       void* sp  = (u1 *) _mc->sc_regs[REG_SP];
-       void* ra  = (u1 *) _mc->sc_regs[REG_RA]; // RA is correct for leaf methods.
-       void* xpc = (u1 *) _mc->sc_pc;
+       void* xpc = (void*) _mc->sc_pc;
 
        // The PC points to the instruction after the illegal instruction.
        xpc = (void*) (((uintptr_t) xpc) - 4);
 
-       // Get the exception-throwing instruction.
-       uint32_t mcode = *((uint32_t*) xpc);
-
-       int opcode = M_OP3_GET_Opcode(mcode);
-
-       // Check for undefined instruction we use.
-       // TODO Check the whole instruction.
-       if (opcode != 0x4) {
-               log_println("md_signal_handler_sigill: Unknown illegal instruction %x at %p", mcode, xpc);
-#if defined(ENABLE_DISASSEMBLER)
-               (void) disassinstr(xpc);
-#endif
-               vm_abort("Aborting...");
-       }
-
-       // This signal is always a patcher.
-       int      type = TRAP_PATCHER;
-       intptr_t val  = 0;
-
        // Handle the trap.
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       trap_handle(TRAP_SIGILL, xpc, _p);
 }
 
 
index e6947d80eee0c47a352524fd3bf6fda6757ab60a..17503332ab98abbc1e1c781a9dd832eb26285a55 100644 (file)
@@ -62,6 +62,17 @@ enum {
        TRAP_END
 };
 
+
+/**
+ * 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 f769b3f7892b846a313c56cbb0e19b24a395770c..fd2e0d4ce9563646677c919dbfbdce7dbbd791f6 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.
 
@@ -189,6 +190,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 (M_OP3_GET_Opcode(mcode) == 0x4) {
+                       trp->type  = TRAP_PATCHER;
+                       trp->value = 0;
+                       return true;
+               }
+               return false;
+
+       case TRAP_SIGSEGV:
+       {
+               // Retrieve base address of instruction.
+               int32_t   s1   = M_MEM_GET_Rb(mcode);
+               uintptr_t addr = es->intregs[s1];
+
+               // Check for special-load.
+               if (s1 == REG_ZERO) {
+                       int32_t d    = M_MEM_GET_Ra(mcode);
+                       int32_t disp = M_MEM_GET_Memory_disp(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.
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 157267d20e4f123b64bbc09477b6c452ca452adf..9837409c9d6f84d66e1e52fc019a2bb5c6253980 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/darwin/md-os.c - machine dependent i386 Darwin 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.
 
 #include "threads/thread.hpp"
 
-#include "vm/jit/builtin.hpp"
 #include "vm/global.h"
 #include "vm/signallocal.hpp"
 
-#include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
-#include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.hpp"
 
 #include "vm/jit/i386/codegen.h"
 #define __ss ss
 #endif
 
-/* 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;
-       i386_thread_state_t *_ss;
-       u1                  *sp;
-       u1                  *ra;
-       u1                  *xpc;
-       u1                   opc;
-       u1                   mod;
-       u1                   rm;
-       int                  d;
-       int32_t              disp;
-       intptr_t             val;
-       int                  type;
-       void                *p;
-
-       _uc = (ucontext_t *) _p;
-       _mc = _uc->uc_mcontext;
-       _ss = &_mc->__ss;
-
-       pv  = NULL;                 /* is resolved during stackframeinfo creation */
-       sp  = (u1 *) _ss->__esp;
-       xpc = (u1 *) _ss->__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;
-
-               val = (d == 0) ? _ss->__eax :
-                       ((d == 1) ? _ss->__ecx :
-                       ((d == 2) ? _ss->__edx :
-                       ((d == 3) ? _ss->__ebx :
-                       ((d == 4) ? _ss->__esp :
-                       ((d == 5) ? _ss->__ebp :
-                       ((d == 6) ? _ss->__esi : _ss->__edi))))));
-
-               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 */
-
-               type = TRAP_NullPointerException;
-       }
-
-       /* Handle the trap. */
-
-       p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+       ucontext_t*          _uc = (ucontext_t *) _p;
+       mcontext_t           _mc = _uc->uc_mcontext;
+       i386_thread_state_t* _ss = &_mc->__ss;
 
-       /* Set registers. */
+       void* xpc = (void*) _ss->__eip;
 
-       if (type == TRAP_COMPILER) {
-               if (p == NULL) {
-                       _ss->__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;
-       i386_thread_state_t *_ss;
-       u1                  *sp;
-       u1                  *ra;
-       u1                  *xpc;
-       int                  type;
-       intptr_t             val;
-
-
-       _uc = (ucontext_t *) _p;
-       _mc = _uc->uc_mcontext;
-       _ss = &_mc->__ss;
-
-       pv  = NULL;                 /* is resolved during stackframeinfo creation */
-       sp  = (u1 *) _ss->__esp;
-       xpc = (u1 *) _ss->__eip;
-       ra  = xpc;                          /* return address is equal to xpc     */
-
-       /* This is an ArithmeticException */
-
-       type = TRAP_ArithmeticException;
-       val  = 0;
+       ucontext_t*          _uc = (ucontext_t *) _p;
+       mcontext_t           _mc = _uc->uc_mcontext;
+       i386_thread_state_t* _ss = &_mc->__ss;
 
-       /* Handle the trap. */
+       void* xpc = (void*) _ss->__eip;
 
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       // Handle the trap.
+       trap_handle(TRAP_SIGFPE, xpc, _p);
 }
 
 
@@ -226,56 +117,19 @@ void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_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;
-       i386_thread_state_t *_ss;
-       u1                  *sp;
-       u1                  *ra;
-       u1                  *xpc;
-       int                  type;
-       intptr_t             val;
-
-
-       _uc = (ucontext_t *) _p;
-       _mc = _uc->uc_mcontext;
-       _ss = &_mc->__ss;
-
-       pv  = NULL;                 /* is resolved during stackframeinfo creation */
-       sp  = (u1 *) _ss->__esp;
-       xpc = (u1 *) _ss->__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;
+       i386_thread_state_t* _ss = &_mc->__ss;
 
-       /* Handle the trap. */
+       void* xpc = (void*) _ss->__eip;
 
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       // Handle the trap.
+       trap_handle(TRAP_SIGILL, xpc, _p);
 }
 
 /* md_executionstate_read ******************************************************
index 1f72d58d2ffca4f21a73fbd7508651312c9abb18..1417ec01a073347972182d543c5e6f1ac661c1bb 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 "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);
 }
 
 
index 52e6a0067ce0d74777e664f73cfc85da4c757e65..6cf2bbf20b99acfa7da6d9c3c28d72758f7d93e3 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 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 */
 
 
index 191cddabd02cdb6d88b8b99a1b62b38dd6598c02..4b9a02a431f08fb95362d601bcd4c1c2d75f82c0 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 "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.
index 3980348dbd1a29c6ace0fd5eddf1975b1d213bb9..2a6899381867ef9aef8817eccefd3ea169243b91 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.
 
 
 #include "threads/thread.hpp"
 
-#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.hpp"
 #include "vm/os.hpp"
 
-#include "vm/jit/asmpart.h"
-#include "vm/jit/disass.h"
 #include "vm/jit/executionstate.h"
-
-#if defined(ENABLE_PROFILING)
-# include "vm/jit/optimizing/profile.h"
-#endif
-
-#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;
-       mcontext_t     *_mc;
-       unsigned long  *_gregs;
-       u1             *pv;
-       u1             *sp;
-       u1             *ra;
-       u1             *xpc;
-       u4              mcode;
-       int             s1;
-       int16_t         disp;
-       int             d;
-       intptr_t        addr;
-       intptr_t        val;
-       int             type;
-
-       _uc = (ucontext_t *) _p;
+       ucontext_t* _uc = (ucontext_t*) _p;
+       mcontext_t* _mc;
+       unsigned long* _gregs;
 
 #if defined(__UCLIBC__)
        _mc    = &(_uc->uc_mcontext);
@@ -87,46 +62,10 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        _gregs = _mc->gregs;
 #endif
 
-       pv  = (u1 *) _gregs[REG_PV];
-       sp  = (u1 *) _gregs[REG_SP];
-       ra  = (u1 *) _gregs[PT_LNK];                 /* this is correct for leafs */
-       xpc = (u1 *) _gregs[PT_NIP];
-
-       /* get exception-throwing instruction */
-
-       mcode = *((u4 *) xpc);
-
-       s1   = M_INSTR_OP2_IMM_A(mcode);
-       disp = M_INSTR_OP2_IMM_I(mcode);
-       d    = M_INSTR_OP2_IMM_D(mcode);
-
-       val  = _gregs[d];
-
-       /* check for special-load */
-
-       if (s1 == REG_ZERO) {
-               /* we use the exception type as load displacement */
-
-               type = disp;
-
-               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 = addr;
-       }
-
-       /* Handle the trap. */
+       void* xpc = (void*) _gregs[PT_NIP];
 
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       // Handle the trap.
+       trap_handle(TRAP_SIGSEGV, xpc, _p);
 }
 
 
@@ -147,62 +86,21 @@ void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
        _gregs = _mc->gregs;
 #endif
 
-       /* get register values */
-
-       void* pv = (void*) _gregs[REG_PV];
-       void* sp = (void*) _gregs[REG_SP];
-       void* ra = (void*) _gregs[PT_LNK]; // The RA is correct for leag methods.
-       void* xpc =(void*) _gregs[PT_NIP];
-
-       // Get the illegal-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).
-               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%lx", mcode, xpc);
-#if defined(ENABLE_DISASSEMBLER)
-               (void) disassinstr(xpc);
-#endif
-               vm_abort("Aborting...");
-       }
-
-       // This signal is always a patcher.
-       int      type = TRAP_PATCHER;
-       intptr_t val  = 0;
+       void* xpc = (void*) _gregs[PT_NIP];
 
        // Handle the trap.
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       trap_handle(TRAP_SIGILL, xpc, _p);
 }
 
 
-/* md_signal_handler_sigtrap ***************************************************
-
-   Signal handler for hardware-traps.
-
-*******************************************************************************/
-
+/**
+ * Signal handler for hardware-traps.
+ */
 void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t     *_uc;
-       mcontext_t     *_mc;
-       unsigned long  *_gregs;
-       u1             *pv;
-       u1             *sp;
-       u1             *ra;
-       u1             *xpc;
-       u4              mcode;
-       int             s1;
-       intptr_t        val;
-       int             type;
-
-       _uc = (ucontext_t *) _p;
+       ucontext_t* _uc = (ucontext_t*) _p;
+       mcontext_t* _mc;
+       unsigned long* _gregs;
 
 #if defined(__UCLIBC__)
        _mc    = &(_uc->uc_mcontext);
@@ -212,25 +110,10 @@ void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p)
        _gregs = _mc->gregs;
 #endif
 
-       pv  = (u1 *) _gregs[REG_PV];
-       sp  = (u1 *) _gregs[REG_SP];
-       ra  = (u1 *) _gregs[PT_LNK];                 /* this is correct for leafs */
-       xpc = (u1 *) _gregs[PT_NIP];
-
-       /* get exception-throwing instruction */
+       void* xpc = (void*) _gregs[PT_NIP];
 
-       mcode = *((u4 *) xpc);
-
-       s1 = M_OP3_GET_A(mcode);
-
-       /* For now we only handle ArrayIndexOutOfBoundsException. */
-
-       type = TRAP_ArrayIndexOutOfBoundsException;
-       val  = _gregs[s1];
-
-       /* Handle the trap. */
-
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       // Handle the trap.
+       trap_handle(TRAP_SIGTRAP, xpc, _p);
 }
 
 
index fc9807d081ee0e4e60e4495c940ca469694082dd..45e1a6ab97a864c06910c216be165b83b6261c62 100644 (file)
@@ -62,6 +62,17 @@ enum {
        TRAP_END
 };
 
+
+/**
+ * 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 3595f407a4c2688c48b44d5e280a53e974c7329f..2c9333b359d38a2a5fff55cdf66c43f18ef17603 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.
 
@@ -38,6 +39,7 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/jit.hpp"
+#include "vm/jit/trap.hpp"
 
 
 /* md_init *********************************************************************
@@ -153,6 +155,72 @@ 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  = TRAP_PATCHER;
+                       trp->value = 0;
+                       return true;
+               }
+               return false;
+
+       case TRAP_SIGTRAP:
+       {
+               int s1 = M_OP3_GET_A(mcode);
+
+               // For now we only handle ArrayIndexOutOfBoundsException.
+               trp->type  = TRAP_ArrayIndexOutOfBoundsException;
+               trp->value = es->intregs[s1];
+               return true;
+       }
+
+       case TRAP_SIGSEGV:
+       {
+               int       s1   = M_INSTR_OP2_IMM_A(mcode);
+               uintptr_t addr = es->intregs[s1];
+
+               // Check for special-load.
+               if (s1 == REG_ZERO) {
+                       int16_t disp = M_INSTR_OP2_IMM_I(mcode);
+                       int     d    = M_INSTR_OP2_IMM_D(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.
index 25d0b1bf4d19ddfffc47a64763ae45fea8b71e3f..23b1a541576a046aea522a06286879a92b11d194 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/powerpc64/linux/md-os.c - machine dependent PowerPC64 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
    Copyright (C) 2008 Theobroma Systems Ltd.
 
 
 #include "threads/thread.hpp"
 
-#include "vm/jit/builtin.hpp"
 #include "vm/signallocal.hpp"
-#include "vm/os.hpp"
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
-
-#if defined(ENABLE_PROFILING)
-# include "vm/jit/optimizing/profile.h"
-#endif
-
-#include "vm/jit/disass.h"
 #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;
-       u4              mcode;
-       int             s1;
-       int16_t         disp;
-       int             d;
-       int             type;
-       intptr_t        addr;
-       intptr_t        val;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &(_uc->uc_mcontext);
-
-       /* get register values */
-
-       pv = (u1*) _mc->gp_regs[REG_PV];
-       sp = (u1*) _mc->gp_regs[REG_SP];
-       ra = (u1*) _mc->gp_regs[PT_LNK];                     /* correct for leafs */
-       xpc =(u1*) _mc->gp_regs[PT_NIP];
+       ucontext_t* _uc = (ucontext_t *) _p;
+       mcontext_t* _mc = &(_uc->uc_mcontext);
 
-       /* get the throwing instruction */
+       void* xpc = (void*) _mc->gp_regs[PT_NIP];
 
-       mcode = *((u4*)xpc);
-
-       s1   = M_INSTR_OP2_IMM_A(mcode);
-       disp = M_INSTR_OP2_IMM_I(mcode);
-       d    = M_INSTR_OP2_IMM_D(mcode);
-
-       val  = _mc->gp_regs[d];
-
-       if (s1 == REG_ZERO) {
-               /* We use the exception type as load displacement. */
-               type = disp;
-
-               if (type == TRAP_COMPILER) {
-                       /* The XPC is the RA minus 1, because the RA points to the
-                          instruction after the call. */
-
-                       xpc = ra - 4;
-               }
-       }
-       else {
-               /* Normal NPE. */
-               addr = _mc->gp_regs[s1];
-               type = (int) addr;
-       }
-
-       /* Handle the trap. */
-
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       // Handle the trap.
+       trap_handle(TRAP_SIGSEGV, xpc, _p);
 }
 
 
@@ -126,38 +68,10 @@ void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
        ucontext_t* _uc = (ucontext_t*) _p;
        mcontext_t* _mc = &(_uc->uc_mcontext);
 
-       /* get register values */
-
-       void* pv = (void*) _mc->gp_regs[REG_PV];
-       void* sp = (void*) _mc->gp_regs[REG_SP];
-       void* ra = (void*) _mc->gp_regs[PT_LNK]; // The RA is correct for leag methods.
        void* xpc =(void*) _mc->gp_regs[PT_NIP];
 
-       // Get the illegal-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).
-               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%lx", mcode, xpc);
-#if defined(ENABLE_DISASSEMBLER)
-               (void) disassinstr(xpc);
-#endif
-               vm_abort("Aborting...");
-       }
-
-       // This signal is always a patcher.
-       int      type = TRAP_PATCHER;
-       intptr_t val  = 0;
-
        // Handle the trap.
-       trap_handle(type, val, pv, sp, ra, xpc, _p);
+       trap_handle(TRAP_SIGILL, xpc, _p);
 }
 
 
index 3830d1598ef9eb95c94cd248c7182f98105675bf..aeac454da69f5d1d18175c54861be78fc787ba8d 100644 (file)
@@ -64,6 +64,17 @@ enum {
        TRAP_PATCHER                        = 99 // A large number.
 };
 
+
+/**
+ * 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 fd10194005ec08b1eda76b8b2dd65b2318f47424..0b61ced6ab70e89be1029ded302f05d6af239afc 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/powerpc64/md.c - machine dependent PowerPC 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, 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -157,6 +155,60 @@ 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 throwing instruction.
+       uint32_t mcode = *((uint32_t*) xpc);
+
+       switch (sig) {
+       case TRAP_SIGILL:
+               // Check for valid trap instruction.
+               if (mcode == 0x00000000) {
+                       trp->type  = TRAP_PATCHER;
+                       trp->value = 0;
+                       return true;
+               }
+               return false;
+
+       case TRAP_SIGSEGV:
+       {
+               // Decode the throwing instruction.
+               int     s1   = M_INSTR_OP2_IMM_A(mcode);
+               int16_t disp = M_INSTR_OP2_IMM_I(mcode);
+               int     d    = M_INSTR_OP2_IMM_D(mcode);
+
+               // We use the exception type as load displacement.
+               if (s1 == REG_ZERO) {
+                       trp->type  = disp;
+                       trp->value = es->intregs[d];
+                       return true;
+               }
+
+               // Default case is a normal NullPointerException.
+               if (es->intregs[s1] == 0) {
+                       trp->type  = TRAP_NullPointerException;
+                       trp->value = 0;
+                       return true;
+               }
+
+               return false;
+       }
+
+       default:
+               return false;
+       }
+}
+
+
 /* md_patch_replacement_point **************************************************
 
    Patch the given replacement point.
index c923f84484df325666cd3cf0e4b6e3ea77fe15b8..f5875a04ebf91b4addcb754f0353a36635d5762c 100644 (file)
@@ -66,22 +66,6 @@ void patcher_patch_code(patchref_t *pr)
 }
 
 
-/**
- * Check if the trap instruction at the given PC is valid.
- *
- * @param pc Program counter.
- *
- * @return true if valid, false otherwise.
- */
-bool patcher_is_valid_trap_instruction_at(void* pc)
-{
-       uint32_t mcode = *((uint32_t*) pc);
-
-       // Check for the undefined instruction we use.
-       return (mcode == 0x00000000);
-}
-
-
 /* patcher_get_putstatic *******************************************************
 
    Machine code:
index 903faf539151f9ef3b723176a3767038333c4f4d..3f95aaa90909159728f7a127770d60a3037940f4 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);
@@ -221,7 +271,7 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
 #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;
@@ -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.