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 "vm/jit/patcher-common.hpp"
#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trap.hpp"
#ifdef __cplusplus
extern "C" {
* 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. */
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) {
# 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 */
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
m = code_get_methodinfo_for_pv(pv);
pv = NULL;
+
break;
default:
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);
/* 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 */
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.
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) {
}
# endif
#endif
-
- /* Unwrap and return the exception object. */
- /* AFTER: removing stackframeinfo */
-
- if (type == TRAP_COMPILER)
- return entry;
- else
- return LLNI_UNWRAP(p);
}
#ifdef __cplusplus