* Merged in twisti-branch.
[cacao.git] / src / vm / jit / i386 / linux / md-os.c
index 58a7afc555ad5c41b73af9f51d5e063773976e6d..16d314a21753d8e1ebe9a8b9a95c9ca1046ae8d3 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/linux/md-os.c - machine dependent i386 Linux functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: md-os.c 5172 2006-07-25 15:33:58Z twisti $
+   $Id: md-os.c 7571 2007-03-24 22:37:09Z twisti $
 
 */
 
 #include "vm/exceptions.h"
 #include "vm/signallocal.h"
 #include "vm/stringlocal.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/stacktrace.h"
 
+#include "vm/jit/i386/codegen.h"
+
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware exceptions.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *sp;
-       u1         *ra;
-       u1         *xpc;
+       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;
+       java_objectheader *e;
 
        _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     */
+       ra  = xpc;                              /* return address is equal to XPC */
 
-       _mc->gregs[REG_EAX] =
-               (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, 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];
+       }
+       else {
+               /* this was a normal NPE */
+
+               type = EXCEPTION_HARDWARE_NULLPOINTER;
+       }
+
+       /* generate appropriate exception */
+
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
 
+       _mc->gregs[REG_EAX] = (ptrint) e;
        _mc->gregs[REG_ECX] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
        _mc->gregs[REG_EIP] = (ptrint) asm_handle_exception;
 }