Merge pull request #1266 from esdrubal/datetimenewformat
[mono.git] / mono / mini / mini-exceptions.c
index 3438f2d90862f98a005b643e51e614715adcebfc..5993ddddb63364b5b9834e3ea006d7260079572e 100644 (file)
@@ -50,7 +50,6 @@
 #include <mono/utils/mono-logger-internal.h>
 
 #include "mini.h"
-#include "debug-mini.h"
 #include "trace.h"
 #include "debugger-agent.h"
 
@@ -218,6 +217,14 @@ find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, Mo
        if (!err)
                return (gpointer)-1;
 
+       if (*lmf && ((*lmf) != jit_tls->first_lmf) && ((gpointer)MONO_CONTEXT_GET_SP (new_ctx) >= (gpointer)(*lmf))) {
+               /*
+                * Remove any unused lmf.
+                * Mask out the lower bits which might be used to hold additional information.
+                */
+               *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~(SIZEOF_VOID_P -1));
+       }
+
        /* Convert between the new and the old APIs */
        switch (frame.type) {
        case FRAME_TYPE_MANAGED:
@@ -370,6 +377,14 @@ mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
        if (!err)
                return FALSE;
 
+       if (*lmf && ((*lmf) != jit_tls->first_lmf) && ((gpointer)MONO_CONTEXT_GET_SP (new_ctx) >= (gpointer)(*lmf))) {
+               /*
+                * Remove any unused lmf.
+                * Mask out the lower bits which might be used to hold additional information.
+                */
+               *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~(SIZEOF_VOID_P -1));
+       }
+
        if (frame->ji && !frame->ji->async)
                method = jinfo_get_method (frame->ji);
 
@@ -1434,8 +1449,6 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3
 #ifndef DISABLE_PERFCOUNTERS
                                        mono_perfcounters->exceptions_filters++;
 #endif
-                                       mono_debugger_call_exception_handler (ei->data.filter, MONO_CONTEXT_GET_SP (ctx), ex_obj);
-
                                        /*
                                        Here's the thing, if this is a filter clause done by a wrapper like runtime invoke, we don't want to
                                        trim the stackframe since if it returns FALSE we lose information.
@@ -1512,7 +1525,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
        MonoContext initial_ctx;
        MonoMethod *method;
        int frame_count = 0;
-       gint32 filter_idx, first_filter_idx;
+       gint32 filter_idx, first_filter_idx = 0;
        int i;
        MonoObject *ex_obj;
        MonoObject *non_exception = NULL;
@@ -1545,6 +1558,12 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
 
        mono_ex = (MonoException*)obj;
 
+       if (mini_get_debug_options ()->suspend_on_exception) {
+               mono_runtime_printf_err ("Exception thrown, suspending...");
+               while (1)
+                       ;
+       }
+
        if (mono_object_isinst (obj, mono_defaults.exception_class)) {
                mono_ex = (MonoException*)obj;
        } else {
@@ -1796,9 +1815,8 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
                                        jit_tls->orig_ex_ctx_set = TRUE;
                                        mono_profiler_exception_clause_handler (method, ei->flags, i);
                                        jit_tls->orig_ex_ctx_set = FALSE;
-                                       mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
                                        MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
-                                       *(mono_get_lmf_addr ()) = lmf;
+                                       mono_set_lmf (lmf);
 #ifndef DISABLE_PERFCOUNTERS
                                        mono_perfcounters->exceptions_depth += frame_count;
 #endif
@@ -1814,7 +1832,6 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
                                        jit_tls->orig_ex_ctx_set = TRUE;
                                        mono_profiler_exception_clause_handler (method, ei->flags, i);
                                        jit_tls->orig_ex_ctx_set = FALSE;
-                                       mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
                                        call_filter (ctx, ei->handler_start);
                                }
                                if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
@@ -1824,11 +1841,10 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
                                        jit_tls->orig_ex_ctx_set = TRUE;
                                        mono_profiler_exception_clause_handler (method, ei->flags, i);
                                        jit_tls->orig_ex_ctx_set = FALSE;
-                                       mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
 #ifndef DISABLE_PERFCOUNTERS
                                        mono_perfcounters->exceptions_finallys++;
 #endif
-                                       *(mono_get_lmf_addr ()) = lmf;
+                                       mono_set_lmf (lmf);
                                        if (ji->from_llvm) {
                                                /* 
                                                 * LLVM compiled finally handlers follow the design
@@ -1865,72 +1881,6 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
        g_assert_not_reached ();
 }
 
-/*
- * mono_debugger_handle_exception:
- *
- *  Notify the debugger about exceptions.  Returns TRUE if the debugger wants us to stop
- *  at the exception and FALSE to resume with the normal exception handling.
- *
- *  The arch code is responsible to setup @ctx in a way that MONO_CONTEXT_GET_IP () and
- *  MONO_CONTEXT_GET_SP () point to the throw instruction; ie. before executing the
- *  `callq throw' instruction.
- */
-gboolean
-mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj)
-{
-       MonoDebuggerExceptionAction action;
-
-       if (!mono_debug_using_mono_debugger ())
-               return FALSE;
-
-       if (!obj) {
-               MonoException *ex = mono_get_exception_null_reference ();
-               MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_domain_get (), "Object reference not set to an instance of an object"));
-               obj = (MonoObject *)ex;
-       }
-
-       action = _mono_debugger_throw_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
-
-       if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP) {
-               /*
-                * The debugger wants us to stop on the `throw' instruction.
-                * By the time we get here, it already inserted a breakpoint there.
-                */
-               return TRUE;
-       } else if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED) {
-               MonoContext ctx_cp = *ctx;
-               MonoJitInfo *ji = NULL;
-               gboolean ret;
-
-               /*
-                * The debugger wants us to stop only if this exception is user-unhandled.
-                */
-
-               ret = mono_handle_exception_internal_first_pass (&ctx_cp, obj, NULL, &ji, NULL, NULL);
-               if (ret && (ji != NULL) && (jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)) {
-                       /*
-                        * The exception is handled in a runtime-invoke wrapper, that means that it's unhandled
-                        * inside the method being invoked, so we handle it like a user-unhandled exception.
-                        */
-                       ret = FALSE;
-               }
-
-               if (!ret) {
-                       /*
-                        * The exception is user-unhandled - tell the debugger to stop.
-                        */
-                       return _mono_debugger_unhandled_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
-               }
-
-               /*
-                * The exception is catched somewhere - resume with the normal exception handling and don't
-                * stop in the debugger.
-                */
-       }
-
-       return FALSE;
-}
-
 /**
  * mono_debugger_run_finally:
  * @start_ctx: saved processor state
@@ -2005,7 +1955,7 @@ mono_setup_altstack (MonoJitTlsData *tls)
        if (mono_running_on_valgrind ())
                return;
 
-       mono_thread_get_stack_bounds (&staddr, &stsize);
+       mono_thread_info_get_stack_bounds (&staddr, &stsize);
 
        g_assert (staddr);
 
@@ -2180,6 +2130,7 @@ typedef struct {
        int count;
 } PrintOverflowUserData;
 
+#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
 static gboolean
 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
 {
@@ -2218,12 +2169,15 @@ print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer da
 
        return FALSE;
 }
+#endif
 
 void
 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
 {
+#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
        PrintOverflowUserData ud;
        MonoContext mctx;
+#endif
 
        /* we don't do much now, but we can warn the user with a useful message */
        mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
@@ -2283,6 +2237,8 @@ print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer d
        return FALSE;
 }
 
+#ifndef MONO_CROSS_COMPILE
+
 static gboolean handling_sigsegv = FALSE;
 
 /*
@@ -2305,8 +2261,14 @@ mono_handle_native_sigsegv (int signal, void *ctx)
 
        if (mini_get_debug_options ()->suspend_on_sigsegv) {
                mono_runtime_printf_err ("Received SIGSEGV, suspending...");
+#ifdef HOST_WIN32
                while (1)
                        ;
+#else
+               while (1) {
+                       sleep (1);
+               }
+#endif
        }
 
        /* To prevent infinite loops when the stack walk causes a crash */
@@ -2337,7 +2299,7 @@ mono_handle_native_sigsegv (int signal, void *ctx)
        /* Try to get more meaningful information using gdb */
 
 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
-       if (!mini_get_debug_options ()->no_gdb_backtrace && !mono_debug_using_mono_debugger ()) {
+       if (!mini_get_debug_options ()->no_gdb_backtrace) {
                /* From g_spawn_command_line_sync () in eglib */
                pid_t pid;
                int status;
@@ -2390,14 +2352,26 @@ mono_handle_native_sigsegv (int signal, void *ctx)
 
 #endif
 
-       /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
+       if (!mono_do_crash_chaining) {
+               /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
 #if defined (PLATFORM_ANDROID)
-       exit (-1);
+               exit (-1);
 #else
-       abort ();
+               abort ();
 #endif
+       }
 }
 
+#else
+
+void
+mono_handle_native_sigsegv (int signal, void *ctx)
+{
+       g_assert_not_reached ();
+}
+
+#endif /* !MONO_CROSS_COMPILE */
+
 static void
 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
 {
@@ -2406,7 +2380,10 @@ mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
        MonoContext ctx;
 #endif
        GString* text = g_string_new (0);
-       char *name, *wapi_desc;
+       char *name;
+#ifndef HOST_WIN32
+       char *wapi_desc;
+#endif
        GError *error = NULL;
 
        if (thread->name) {
@@ -2771,3 +2748,27 @@ mono_restore_context (MonoContext *ctx)
        g_assert_not_reached ();
 }
 
+/*
+ * mono_jinfo_get_unwind_info:
+ *
+ *   Return the unwind info for JI.
+ */
+guint8*
+mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
+{
+       if (ji->from_aot)
+               return mono_aot_get_unwind_info (ji, unwind_info_len);
+       else
+               return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len);
+}
+
+int
+mono_jinfo_get_epilog_size (MonoJitInfo *ji)
+{
+       MonoArchEHJitInfo *info;
+
+       info = mono_jit_info_get_arch_eh_info (ji);
+       g_assert (info);
+
+       return info->epilog_size;
+}