#define MONO_ARCH_CONTEXT_DEF
#endif
+#ifndef MONO_ARCH_STACK_GROWS_UP
+#define MONO_ARCH_STACK_GROWS_UP 0
+#endif
+
static gpointer restore_context_func, call_filter_func;
static gpointer throw_exception_func, rethrow_exception_func;
static gpointer throw_corlib_exception_func;
static void mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data);
static gboolean mono_current_thread_has_handle_block_guard (void);
+static gboolean
+first_managed (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer addr)
+{
+ gpointer **data = (gpointer **)addr;
+
+ if (!frame->managed)
+ return FALSE;
+
+ if (!ctx) {
+ // FIXME: Happens with llvm_only
+ *data = NULL;
+ return TRUE;
+ }
+
+ *data = MONO_CONTEXT_GET_SP (ctx);
+ g_assert (*data);
+ return TRUE;
+}
+
+static gpointer
+mono_thread_get_managed_sp (void)
+{
+ gpointer addr = NULL;
+ mono_walk_stack (first_managed, MONO_UNWIND_SIGNAL_SAFE, &addr);
+ return addr;
+}
+
+static inline int
+mini_abort_threshold_offset (gpointer threshold, gpointer sp)
+{
+ intptr_t stack_threshold = (intptr_t) threshold;
+ intptr_t stack_pointer = (intptr_t) sp;
+
+ const int direction = MONO_ARCH_STACK_GROWS_UP ? -1 : 1;
+ intptr_t magnitude = stack_pointer - stack_threshold;
+
+ return direction * magnitude;
+}
+
+static inline void
+mini_clear_abort_threshold (void)
+{
+ MonoJitTlsData *jit_tls = mono_get_jit_tls ();
+ jit_tls->abort_exc_stack_threshold = NULL;
+}
+
+static inline void
+mini_set_abort_threshold (MonoContext *ctx)
+{
+ gpointer sp = MONO_CONTEXT_GET_SP (ctx);
+ MonoJitTlsData *jit_tls = mono_get_jit_tls ();
+ // Only move it up, to avoid thrown/caught
+ // exceptions lower in the stack from triggering
+ // a rethrow
+ gboolean above_threshold = mini_abort_threshold_offset (jit_tls->abort_exc_stack_threshold, sp) >= 0;
+ if (!jit_tls->abort_exc_stack_threshold || above_threshold) {
+ jit_tls->abort_exc_stack_threshold = sp;
+ }
+}
+
+// Note: In the case that the frame is above where the thread abort
+// was set we bump the threshold so that functions called from the new,
+// higher threshold don't trigger the thread abort exception
+static inline gboolean
+mini_above_abort_threshold (void)
+{
+ gpointer sp = mono_thread_get_managed_sp ();
+ MonoJitTlsData *jit_tls = (MonoJitTlsData*) mono_tls_get_jit_tls ();
+
+ if (!sp)
+ return TRUE;
+
+ gboolean above_threshold = mini_abort_threshold_offset (jit_tls->abort_exc_stack_threshold, sp) >= 0;
+
+ if (above_threshold)
+ jit_tls->abort_exc_stack_threshold = sp;
+
+ return above_threshold;
+}
+
void
mono_exceptions_init (void)
{
cbs.mono_exception_walk_trace = mono_exception_walk_trace;
cbs.mono_install_handler_block_guard = mono_install_handler_block_guard;
cbs.mono_current_thread_has_handle_block_guard = mono_current_thread_has_handle_block_guard;
+ cbs.mono_clear_abort_threshold = mini_clear_abort_threshold;
+ cbs.mono_above_abort_threshold = mini_above_abort_threshold;
mono_install_eh_callbacks (&cbs);
}
klass = vtable->klass;
}
- //g_assert (!method->klass->generic_container);
- if (method->klass->generic_class)
- method_container_class = method->klass->generic_class->container_class;
+ //g_assert (!mono_class_is_gtd (method->klass));
+ if (mono_class_is_ginst (method->klass))
+ method_container_class = mono_class_get_generic_class (method->klass)->container_class;
else
method_container_class = method->klass;
/* class might refer to a subclass of method's class */
- while (!(klass == method->klass || (klass->generic_class && klass->generic_class->container_class == method_container_class))) {
+ while (!(klass == method->klass || (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->container_class == method_container_class))) {
klass = klass->parent;
g_assert (klass);
}
- if (klass->generic_class || klass->generic_container)
+ if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
context.class_inst = mini_class_get_context (klass)->class_inst;
- if (klass->generic_class)
- g_assert (mono_class_has_parent_and_ignore_generics (klass->generic_class->container_class, method_container_class));
+ if (mono_class_is_ginst (klass))
+ g_assert (mono_class_has_parent_and_ignore_generics (mono_class_get_generic_class (klass)->container_class, method_container_class));
else
g_assert (mono_class_has_parent_and_ignore_generics (klass, method_container_class));
mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
{
if (!start_ctx) {
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
if (jit_tls && jit_tls->orig_ex_ctx_set)
start_ctx = &jit_tls->orig_ex_ctx;
}
{
MonoError error;
MonoDomain *domain = mono_domain_get ();
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoLMF *lmf = mono_get_lmf ();
MonoJitInfo *ji = NULL;
MonoContext ctx, new_ctx;
return val;
}
-#ifndef MONO_ARCH_STACK_GROWS_UP
-#define DOES_STACK_GROWS_UP 1
-#else
-#define DOES_STACK_GROWS_UP 0
-#endif
-
#define MAX_UNMANAGED_BACKTRACE 128
static MonoArray*
build_native_trace (MonoError *error)
MonoDomain *domain = mono_domain_get ();
MonoJitInfo *ji = NULL;
static int (*call_filter) (MonoContext *, gpointer) = NULL;
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoLMF *lmf = mono_get_lmf ();
MonoArray *initial_trace_ips = NULL;
GList *trace_ips = NULL;
dynamic_methods = g_slist_prepend (dynamic_methods, method);
if (stack_overflow) {
- if (DOES_STACK_GROWS_UP)
- free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
- else
+ if (MONO_ARCH_STACK_GROWS_UP)
free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
+ else
+ free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
} else {
free_stack = 0xffffff;
}
setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
g_slist_free (dynamic_methods);
/* mono_debugger_agent_handle_exception () needs this */
+ mini_set_abort_threshold (ctx);
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
return TRUE;
}
MonoDomain *domain = mono_domain_get ();
MonoJitInfo *ji, *prev_ji;
static int (*call_filter) (MonoContext *, gpointer) = NULL;
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoLMF *lmf = mono_get_lmf ();
MonoException *mono_ex;
gboolean stack_overflow = FALSE;
// FIXME: This runs managed code so it might cause another stack overflow when
// we are handling a stack overflow
+ mini_set_abort_threshold (ctx);
mono_unhandled_exception (obj);
} else {
gboolean unhandled = FALSE;
//printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
if (stack_overflow) {
- if (DOES_STACK_GROWS_UP)
- free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
- else
+ if (MONO_ARCH_STACK_GROWS_UP)
free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
+ else
+ free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
} else {
free_stack = 0xffffff;
}
jit_tls->orig_ex_ctx_set = TRUE;
mono_profiler_exception_clause_handler (method, ei->flags, i);
jit_tls->orig_ex_ctx_set = FALSE;
+ mini_set_abort_threshold (ctx);
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
mono_set_lmf (lmf);
#ifndef DISABLE_PERFCOUNTERS
jit_tls->orig_ex_ctx_set = TRUE;
mono_profiler_exception_clause_handler (method, ei->flags, i);
jit_tls->orig_ex_ctx_set = FALSE;
+ mini_set_abort_threshold (ctx);
call_filter (ctx, ei->handler_start);
}
if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
jit_tls->resume_state.lmf = lmf;
jit_tls->resume_state.first_filter_idx = first_filter_idx;
jit_tls->resume_state.filter_idx = filter_idx;
+ mini_set_abort_threshold (ctx);
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
return 0;
} else {
+ mini_set_abort_threshold (ctx);
call_filter (ctx, ei->handler_start);
}
}
{
static int (*call_filter) (MonoContext *, gpointer) = NULL;
MonoDomain *domain = mono_domain_get ();
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoLMF *lmf = mono_get_lmf ();
MonoContext ctx, new_ctx;
MonoJitInfo *ji, rji;
static G_GNUC_UNUSED void
try_more_restore (void)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
if (try_restore_stack_protection (jit_tls, 500))
jit_tls->restore_stack_prot = NULL;
}
static G_GNUC_UNUSED void
restore_stack_protection (void)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoException *ex = mono_domain_get ()->stack_overflow_ex;
/* if we can't restore the stack protection, keep a callback installed so
* we'll try to restore as much stack as we can at each return from unmanaged
static gboolean handling_sigsegv = FALSE;
/*
- * mono_handle_native_sigsegv:
+ * mono_handle_native_crash:
*
- * Handle a SIGSEGV received while in native code by printing diagnostic
- * information and aborting.
+ * Handle a native crash (e.g. SIGSEGV) while in native code by
+ * printing diagnostic information and aborting.
*/
void
-mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
+mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
{
#ifdef MONO_ARCH_USE_SIGACTION
struct sigaction sa;
#endif
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
- const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
if (handling_sigsegv)
return;
if (mini_get_debug_options ()->suspend_on_sigsegv) {
- mono_runtime_printf_err ("Received SIGSEGV, suspending...");
+ mono_runtime_printf_err ("Received %s, suspending...", signal);
#ifdef HOST_WIN32
while (1)
;
int status;
pid_t crashed_pid = getpid ();
- //pid = fork ();
/*
* glibc fork acquires some locks, so if the crash happened inside malloc/free,
* it will deadlock. Call the syscall directly instead.
*/
- pid = mono_runtime_syscall_fork ();
+#if defined(PLATFORM_ANDROID)
+ /* SYS_fork is defined to be __NR_fork which is not defined in some ndk versions */
+ g_assert_not_reached ();
+#elif defined(SYS_fork)
+ pid = (pid_t) syscall (SYS_fork);
+#elif defined(PLATFORM_MACOSX) && HAVE_FORK
+ pid = (pid_t) fork ();
+#else
+ g_assert_not_reached ();
+#endif
+
#if defined (HAVE_PRCTL) && defined(PR_SET_PTRACER)
if (pid > 0) {
// Allow gdb to attach to the process even if ptrace_scope sysctl variable is set to
"a fatal error in the mono runtime or one of the native libraries \n"
"used by your application.\n"
"=================================================================\n",
- signal_str);
+ signal);
#ifdef MONO_ARCH_USE_SIGACTION
#else
void
-mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
+mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
{
g_assert_not_reached ();
}
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoContext new_ctx;
MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
static gboolean
mono_current_thread_has_handle_block_guard (void)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
return jit_tls && jit_tls->handler_block_return_address != NULL;
}
MonoJitTlsData *jit_tls = NULL;
if (mini_get_debug_options ()->better_cast_details) {
- jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
jit_tls->class_cast_from = from;
jit_tls->class_cast_to = to;
}
mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
{
#ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
jit_tls->ex_ctx = *ctx;
mono_arch_setup_async_callback (ctx, async_cb, user_data);