Merge pull request #3692 from lateralusX/jlorenss/win-api-family-support-libmono
[mono.git] / mono / mini / exceptions-s390x.c
index b95c6ed30185eb0e26916800ce2cc4b14352b60c..fc2390d0b8596511ce63b68edea34504b213e227 100644 (file)
@@ -13,6 +13,7 @@
 /*              Dietmar Maurer (dietmar@ximian.com)                */
 /*                                                                 */
 /* Copyright   - 2001 Ximian, Inc.                                 */
+/* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
 /*                                                                 */
 /*------------------------------------------------------------------*/
 
@@ -33,8 +34,6 @@
 #define S390_THROWSTACK_ACCREGS                (S390_THROWSTACK_FLTREGS+(16*sizeof(gdouble)))
 #define S390_THROWSTACK_SIZE           (S390_THROWSTACK_ACCREGS+(16*sizeof(gint32)))
 
-#define S390_REG_SAVE_R13              (S390_REG_SAVE_OFFSET+(7*sizeof(gulong)))
-
 #define SZ_THROW       384
 
 #define setup_context(ctx)
@@ -61,6 +60,7 @@
 
 #include "mini.h"
 #include "mini-s390x.h"
+#include "support-s390x.h"
 
 /*========================= End of Includes ========================*/
 
 /*                   P r o t o t y p e s                            */
 /*------------------------------------------------------------------*/
 
-gboolean mono_arch_handle_exception (void     *ctx,
-                                    gpointer obj);
+static void throw_exception (MonoObject *, unsigned long, unsigned long, 
+                gulong *, gdouble *, gint32 *, guint, gboolean);
+static gpointer mono_arch_get_throw_exception_generic (int, MonoTrampInfo **, 
+                               int, gboolean, gboolean);
+static void handle_signal_exception (gpointer);
 
 /*========================= End of Prototypes ======================*/
 
@@ -212,6 +215,9 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) < SZ_THROW); 
 
+       mono_arch_flush_icache(start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
        if (info)
                *info = mono_tramp_info_create ("call_filter",
                                                start, code - start, ji,
@@ -235,13 +241,10 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
                 gulong *int_regs, gdouble *fp_regs, gint32 *acc_regs, 
                 guint fpc, gboolean rethrow)
 {
+       MonoError error;
        MonoContext ctx;
        int iReg;
-       static void (*restore_context) (MonoContext *);
 
-       if (!restore_context)
-               restore_context = mono_get_restore_context();
-       
        memset(&ctx, 0, sizeof(ctx));
 
        setup_context(&ctx);
@@ -260,14 +263,17 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
        MONO_CONTEXT_SET_BP (&ctx, sp);
        MONO_CONTEXT_SET_IP (&ctx, ip);
        
-       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)
+               if (!rethrow) {
                        mono_ex->stack_trace = NULL;
+                       mono_ex->trace_ips = NULL;
+               }
        }
+       mono_error_assert_ok (&error);
 //     mono_arch_handle_exception (&ctx, exc, FALSE);
        mono_handle_exception (&ctx, exc);
-       restore_context(&ctx);
+       mono_restore_context(&ctx);
 
        g_assert_not_reached ();
 }
@@ -304,12 +310,8 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info,
        s390_stg  (code, s390_r14, 0, STK_BASE, 0);
        s390_lgr  (code, s390_r3, s390_r2);
        if (corlib) {
-               s390_basr (code, s390_r13, 0);
-               s390_j    (code, 10);
-               s390_llong(code, mono_defaults.exception_class->image);
-               s390_llong(code, mono_exception_from_token);
-               s390_lg   (code, s390_r2, 0, s390_r13, 4);
-               s390_lg   (code, s390_r1, 0, s390_r13, 12);
+               S390_SET  (code, s390_r1, (guint8 *)mono_exception_from_token);
+               S390_SET  (code, s390_r2, (guint8 *)mono_defaults.exception_class->image);
                s390_basr (code, s390_r14, s390_r1);
        }
 
@@ -352,21 +354,21 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info,
        s390_la   (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCREGS);
        s390_stg  (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCPRM);
        s390_stfpc(code, STK_BASE, S390_THROWSTACK_FPCPRM+4);
+       S390_SET  (code, s390_r1, (guint8 *)throw_exception);
        s390_lghi (code, s390_r7, rethrow);
        s390_stg  (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_RETHROW);
-       s390_basr (code, s390_r13, 0);
-       s390_j    (code, 6);
-       s390_llong(code, throw_exception);
-       s390_lg   (code, s390_r1, 0, s390_r13, 4);
        s390_basr (code, s390_r14, s390_r1);
        /* we should never reach this breakpoint */
        s390_break (code);
        g_assert ((code - start) < size);
 
+       mono_arch_flush_icache (start, code - start);
+       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+
        if (info)
                *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" 
-                                                                      : (rethrow ? "rethrow_exception" 
-                                                                      : "throw_exception"), 
+                                                      : (rethrow ? "rethrow_exception" 
+                                                      : "throw_exception"), 
                                                start, code - start, ji, unwind_ops);
 
        return start;
@@ -416,7 +418,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
        if (info)
                *info = NULL;
 
-       return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot));
+       return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, TRUE, aot));
 }
 
 /*========================= End of Function ========================*/
@@ -446,21 +448,20 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
 
 /*------------------------------------------------------------------*/
 /*                                                                  */
-/* Name                - mono_arch_find_jit_info                           */
+/* Name                - mono_arch_unwind_frame                           */
 /*                                                                  */
 /* Function    - See exceptions-amd64.c for docs.                  */
 /*                                                                  */
 /*------------------------------------------------------------------*/
 
 gboolean
-mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, 
+mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, 
                         MonoJitInfo *ji, MonoContext *ctx, 
                         MonoContext *new_ctx, MonoLMF **lmf,
                         mgreg_t **save_locations,
                         StackFrameInfo *frame)
 {
        gpointer ip = (gpointer) MONO_CONTEXT_GET_IP (ctx);
-       MonoS390StackFrame *sframe;
 
        memset (frame, 0, sizeof (StackFrameInfo));
        frame->ji = ji;
@@ -474,34 +475,24 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint8 *unwind_info;
                mgreg_t regs[16];
 
-               frame->type = FRAME_TYPE_MANAGED;
-
-               if (ji->from_aot)
-                       unwind_info = mono_aot_get_unwind_info(ji, &unwind_info_len);
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
                else
-                       unwind_info = mono_get_cached_unwind_info(ji->used_regs, &unwind_info_len);
+                       frame->type = FRAME_TYPE_MANAGED;
 
-               if (*lmf && ((*lmf) != jit_tls->first_lmf) && 
-                   (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->ebp)) {
-                       /* remove any unused lmf */
-                       *lmf = (*lmf)->previous_lmf;
-               }
+               unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
                address = (char *)ip - (char *)ji->code_start;
 
                memcpy(&regs, &ctx->uc_mcontext.gregs, sizeof(regs));
                mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start,
-                               (guint8 *) ji->code_start + ji->code_size,
-                               ip, regs, 16, save_locations, 
-                               MONO_MAX_IREGS, &cfa);
+                                                  (guint8 *) ji->code_start + ji->code_size,
+                                                  ip, NULL, regs, 16, save_locations,
+                                                  MONO_MAX_IREGS, &cfa);
                memcpy (&new_ctx->uc_mcontext.gregs, &regs, sizeof(regs));
                MONO_CONTEXT_SET_IP(new_ctx, regs[14] - 2);
                MONO_CONTEXT_SET_BP(new_ctx, cfa);
        
-               if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->ebp)) {
-                       /* remove any unused lmf */
-                       *lmf = (*lmf)->previous_lmf;
-               }
                return TRUE;
        } else if (*lmf) {
 
@@ -532,52 +523,85 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
 
 /*------------------------------------------------------------------*/
 /*                                                                  */
-/* Name                - mono_arch_handle_exception                        */
+/* Name                - handle_signal_exception                           */
 /*                                                                  */
 /* Function    - Handle an exception raised by the JIT code.       */
 /*                                                                  */
-/* Parameters   - ctx       - Saved processor state                 */
-/*                obj       - The exception object                  */
+/* Parameters   - obj       - The exception object                  */
 /*                                                                  */
 /*------------------------------------------------------------------*/
 
-gboolean
-mono_arch_handle_exception (void *uc, gpointer obj)
+static void
+handle_signal_exception (gpointer obj)
 {
-       return mono_handle_exception (uc, obj);
+       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoContext ctx;
+
+       memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
+       mono_handle_exception (&ctx, obj);
+       mono_restore_context (&ctx);
 }
 
 /*========================= End of Function ========================*/
 
 /*------------------------------------------------------------------*/
 /*                                                                  */
-/* Name                - mono_arch_sigctx_to_monoctx.                      */
+/* Name                - mono_arch_handle_exception                        */
+/*                                                                  */
+/* Function    - Handle an exception raised by the JIT code.       */
 /*                                                                  */
-/* Function    - Called from the signal handler to convert signal  */
-/*                context to MonoContext.                           */
+/* Parameters   - ctx       - Saved processor state                 */
+/*                obj       - The exception object                  */
 /*                                                                  */
 /*------------------------------------------------------------------*/
 
-void
-mono_arch_sigctx_to_monoctx (void *ctx, MonoContext *mctx)
+gboolean
+mono_arch_handle_exception (void *sigctx, gpointer obj)
 {
-       mono_sigctx_to_monoctx(ctx, mctx);
+       MonoContext mctx;
+
+       /*
+        * Handling the exception in the signal handler is problematic, since the original
+        * 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);
+
+       /* Pass the ctx parameter in TLS */
+       mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
+
+       mctx = jit_tls->ex_ctx;
+       mono_arch_setup_async_callback (&mctx, handle_signal_exception, obj);
+       mono_monoctx_to_sigctx (&mctx, sigctx);
+
+       return TRUE;
 }
 
 /*========================= End of Function ========================*/
 
 /*------------------------------------------------------------------*/
 /*                                                                  */
-/* Name                - mono_arch_monoctx_to_sigctx.                      */
+/* Name                - mono_arch_setup_async_callback                    */
 /*                                                                  */
-/* Function    - Convert MonoContext structure to signal context.  */
+/* Function    - Establish the async callback.                     */
+/*                                                                  */
+/* Parameters   - ctx       - Context                               */
+/*                async_cb  - Callback routine address              */
+/*                user_data - Data to be passed to callback         */
 /*                                                                  */
 /*------------------------------------------------------------------*/
 
 void
-mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx)
+mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
 {
-       mono_monoctx_to_sigctx(mctx, ctx);
+       uintptr_t sp = (uintptr_t) MONO_CONTEXT_GET_SP(ctx);
+
+       ctx->uc_mcontext.gregs[2] = (unsigned long) user_data;
+
+       sp -= S390_MINIMAL_STACK_SIZE;
+       *(unsigned long *)sp = MONO_CONTEXT_GET_SP(ctx);
+       MONO_CONTEXT_SET_BP(ctx, sp);
+       MONO_CONTEXT_SET_IP(ctx, (unsigned long) async_cb);
 }
 
 /*========================= End of Function ========================*/