#include <mono/utils/mono-logger-internal.h>
#include "mini.h"
-#include "debug-mini.h"
#include "trace.h"
#include "debugger-agent.h"
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:
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);
#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.
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;
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 {
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
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)) &&
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
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
if (mono_running_on_valgrind ())
return;
- mono_thread_get_stack_bounds (&staddr, &stsize);
+ mono_thread_info_get_stack_bounds (&staddr, &stsize);
g_assert (staddr);
int count;
} PrintOverflowUserData;
+#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
static gboolean
print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
{
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);
return FALSE;
}
+#ifndef MONO_CROSS_COMPILE
+
static gboolean handling_sigsegv = FALSE;
/*
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 */
/* 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;
#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)
{
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) {
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;
+}