Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / exceptions-arm.c
index b478a713bc5e108ea30e7d59ed5e4a2f8c24a9c0..de769c87fff8d41d8af7e149f6173e65d1568f8a 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * exceptions-arm.c: exception support for ARM
+/**
+ * \file
+ * exception support for ARM
  *
  * Authors:
  *   Dietmar Maurer (dietmar@ximian.com)
@@ -14,9 +15,9 @@
 #include <string.h>
 
 #ifndef MONO_CROSS_COMPILE
-#ifdef HAVE_ASM_SIGCONTEXT_H
+#ifdef HOST_ANDROID
 #include <asm/sigcontext.h>
-#endif  /* def HAVE_ASM_SIGCONTEXT_H */
+#endif  /* def HOST_ANDROID */
 #endif
 
 #ifdef HAVE_UCONTEXT_H
@@ -111,6 +112,8 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_SP);
        ARM_PUSH (code, MONO_ARM_REGSAVE_MASK);
 
+       ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
+
        /* restore all the regs from ctx (in r0), but not sp, the stack pointer */
        ctx_reg = ARMREG_R0;
        ARM_LDR_IMM (code, ARMREG_IP, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, pc));
@@ -121,6 +124,8 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
        ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1);
 
+       ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
+
        /* epilog */
        ARM_POP_NWB (code, 0xff0 | ((1 << ARMREG_SP) | (1 << ARMREG_PC)));
 
@@ -137,6 +142,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 void
 mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
 {
+       MonoError error;
        MonoContext ctx;
        gboolean rethrow = sp & 1;
 
@@ -152,25 +158,27 @@ mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_
        memcpy (((guint8*)&ctx.regs) + (ARMREG_R4 * sizeof (mgreg_t)), int_regs, 8 * sizeof (mgreg_t));
        memcpy (&ctx.fregs, fp_regs, sizeof (double) * 16);
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
        mono_handle_exception (&ctx, exc);
        mono_restore_context (&ctx);
        g_assert_not_reached ();
 }
 
 void
-mono_arm_throw_exception_by_token (guint32 type_token, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
+mono_arm_throw_exception_by_token (guint32 ex_token_index, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
 {
+       guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
        /* Clear thumb bit */
        pc &= ~1;
 
-       mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, type_token), pc, sp, int_regs, fp_regs);
+       mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs);
 }
 
 void
@@ -245,9 +253,15 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
        /* exc is already in place in r0 */
        if (corlib) {
                /* The caller ip is already in R1 */
-               if (llvm)
-                       /* Negate the ip adjustment done in mono_arm_throw_exception */
-                       ARM_ADD_REG_IMM8 (code, ARMREG_R1, ARMREG_R1, 4);
+               if (llvm) {
+                       /*
+                        * The address passed by llvm might point to before the call,
+                        * thus outside the eh range recorded by llvm. Use the return
+                        * address instead.
+                        * FIXME: Do this on more platforms.
+                        */
+                       ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
+               }
        } else {
                ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
        }
@@ -323,11 +337,10 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
 
 /**
  * mono_arch_get_throw_corlib_exception:
- *
- * Returns a function pointer which can be used to raise 
+ * \returns a function pointer which can be used to raise 
  * corlib exceptions. The returned function has the following 
  * signature: void (*func) (guint32 ex_token, guint32 offset); 
- * Here, offset is the offset which needs to be substracted from the caller IP 
+ * Here, \c offset is the offset which needs to be substracted from the caller IP 
  * to get the IP of the throw. Passing the offset has the advantage that it 
  * needs no relocations in the caller.
  * On ARM, the ip is passed instead of an offset.
@@ -452,20 +465,24 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
        } else if (*lmf) {
 
                if (((gsize)(*lmf)->previous_lmf) & 2) {
-                       /* 
-                        * This LMF entry is created by the soft debug code to mark transitions to
-                        * managed code done during invokes.
-                        */
                        MonoLMFExt *ext = (MonoLMFExt*)(*lmf);
 
-                       g_assert (ext->debugger_invoke);
-
-                       memcpy (new_ctx, &ext->ctx, sizeof (MonoContext));
+                       if (ext->debugger_invoke) {
+                               /*
+                                * This LMF entry is created by the soft debug code to mark transitions to
+                                * managed code done during invokes.
+                                */
+                               frame->type = FRAME_TYPE_DEBUGGER_INVOKE;
+                               memcpy (new_ctx, &ext->ctx, sizeof (MonoContext));
+                       } else if (ext->interp_exit) {
+                               frame->type = FRAME_TYPE_INTERP_TO_MANAGED;
+                               frame->interp_exit_data = ext->interp_exit_data;
+                       } else {
+                               g_assert_not_reached ();
+                       }
 
                        *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3);
 
-                       frame->type = FRAME_TYPE_DEBUGGER_INVOKE;
-
                        return TRUE;
                }
 
@@ -514,7 +531,7 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
 static void
 handle_signal_exception (gpointer obj)
 {
-       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
        MonoContext ctx;
 
        memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
@@ -549,7 +566,7 @@ mono_arch_handle_exception (void *ctx, gpointer obj)
         * signal is disabled, and we could run arbitrary code though the debugger. So
         * resume into the normal stack and do most work there if possible.
         */
-       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
        guint64 sp = UCONTEXT_REG_SP (sigctx);
 
        /* Pass the ctx parameter in TLS */
@@ -592,8 +609,6 @@ mono_arch_ip_from_context (void *sigctx)
 {
 #ifdef MONO_CROSS_COMPILE
        g_assert_not_reached ();
-#elif defined(__native_client__)
-       g_assert_not_reached ();
 #else
        arm_ucontext *my_uc = sigctx;
        return (void*) UCONTEXT_REG_PC (my_uc);