#include <sys/syscall.h>
#endif
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
#include <mono/metadata/appdomain.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/threads.h>
#include <mono/metadata/profiler.h>
#include <mono/metadata/mono-endian.h>
#include <mono/metadata/environment.h>
+#include <mono/metadata/mono-mlist.h>
#include <mono/utils/mono-mmap.h>
#include <mono/utils/mono-logger-internal.h>
MonoTrampInfo *info;
restore_context_func = mono_arch_get_restore_context (&info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
call_filter_func = mono_arch_get_call_filter (&info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
throw_exception_func = mono_arch_get_throw_exception (&info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
rethrow_exception_func = mono_arch_get_rethrow_exception (&info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
}
#ifdef MONO_ARCH_HAVE_RESTORE_STACK_SUPPORT
try_more_restore_tramp = mono_create_specific_trampoline (try_more_restore, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL);
code = mono_aot_get_trampoline ("throw_corlib_exception");
else {
code = mono_arch_get_throw_corlib_exception (&info, FALSE);
- mono_tramp_info_register (info);
+ mono_tramp_info_register (info, NULL);
}
mono_memory_barrier ();
/*
* find_jit_info:
*
- * Translate between the mono_arch_find_jit_info function and the old API.
+ * Translate between the mono_arch_unwind_frame function and the old API.
*/
static MonoJitInfo *
find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx,
if (managed)
*managed = FALSE;
- err = mono_arch_find_jit_info (domain, jit_tls, ji, ctx, new_ctx, lmf, NULL, &frame);
+ err = mono_arch_unwind_frame (domain, jit_tls, ji, ctx, new_ctx, lmf, NULL, &frame);
if (!err)
return (gpointer)-1;
if (managed)
*managed = TRUE;
return frame.ji;
+ case FRAME_TYPE_TRAMPOLINE:
+ return frame.ji;
case FRAME_TYPE_MANAGED_TO_NATIVE:
if (frame.ji)
return frame.ji;
if (ji == (gpointer)-1)
return ji;
- if (ji)
+ if (ji && !ji->is_trampoline)
method = jinfo_get_method (ji);
- if (managed2 || (ji && method->wrapper_type)) {
+ if (managed2 || (method && method->wrapper_type)) {
const char *real_ip, *start;
gint32 offset;
if (save_locations)
memset (save_locations, 0, MONO_MAX_IREGS * sizeof (mgreg_t*));
- err = mono_arch_find_jit_info (target_domain, jit_tls, ji, ctx, new_ctx, lmf, save_locations, frame);
+ err = mono_arch_unwind_frame (target_domain, jit_tls, ji, ctx, new_ctx, lmf, save_locations, frame);
if (!err)
return FALSE;
*lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~(SIZEOF_VOID_P -1));
}
- if (frame->ji && !frame->ji->async)
+ if (frame->ji && !frame->ji->is_trampoline && !frame->ji->async)
method = jinfo_get_method (frame->ji);
if (frame->type == FRAME_TYPE_MANAGED && method) {
return TRUE;
}
+/*
+ * This function is async-safe.
+ */
static gpointer
get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx)
{
get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
{
MonoGenericContext context = { NULL, NULL };
- MonoClass *class, *method_container_class;
+ MonoClass *klass, *method_container_class;
MonoMethod *method;
g_assert (generic_info);
if (mono_method_get_context (method)->method_inst) {
MonoMethodRuntimeGenericContext *mrgctx = generic_info;
- class = mrgctx->class_vtable->klass;
+ klass = mrgctx->class_vtable->klass;
context.method_inst = mrgctx->method_inst;
g_assert (context.method_inst);
} else if ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype) {
MonoVTable *vtable = generic_info;
- class = vtable->klass;
+ klass = vtable->klass;
} else {
- class = generic_info;
+ klass = generic_info;
}
//g_assert (!method->klass->generic_container);
method_container_class = method->klass;
/* class might refer to a subclass of method's class */
- while (!(class == method->klass || (class->generic_class && class->generic_class->container_class == method_container_class))) {
- class = class->parent;
- g_assert (class);
+ while (!(klass == method->klass || (klass->generic_class && klass->generic_class->container_class == method_container_class))) {
+ klass = klass->parent;
+ g_assert (klass);
}
- if (class->generic_class || class->generic_container)
- context.class_inst = mini_class_get_context (class)->class_inst;
+ if (klass->generic_class || klass->generic_container)
+ context.class_inst = mini_class_get_context (klass)->class_inst;
- if (class->generic_class)
- g_assert (mono_class_has_parent_and_ignore_generics (class->generic_class->container_class, method_container_class));
+ if (klass->generic_class)
+ g_assert (mono_class_has_parent_and_ignore_generics (klass->generic_class->container_class, method_container_class));
else
- g_assert (mono_class_has_parent_and_ignore_generics (class, method_container_class));
+ g_assert (mono_class_has_parent_and_ignore_generics (klass, method_container_class));
return context;
}
return len > 0;
}
-MonoString *
-ves_icall_System_Exception_get_trace (MonoException *ex)
-{
- MonoDomain *domain = mono_domain_get ();
- MonoString *res;
- MonoArray *ta = ex->trace_ips;
- int i, len;
- GString *trace_str;
-
- if (ta == NULL)
- /* Exception is not thrown yet */
- return NULL;
-
- len = mono_array_length (ta) >> 1;
- trace_str = g_string_new ("");
- for (i = 0; i < len; i++) {
- MonoJitInfo *ji;
- gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
- gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
-
- ji = mono_jit_info_table_find (domain, ip);
- if (ji == NULL) {
- /* Unmanaged frame */
- g_string_append_printf (trace_str, "in (unmanaged) %p\n", ip);
- } else {
- gchar *location;
- gint32 address;
- MonoMethod *method = get_method_from_stack_frame (ji, generic_info);
-
- address = (char *)ip - (char *)ji->code_start;
- location = mono_debug_print_stack_frame (
- method, address, ex->object.vtable->domain);
-
- g_string_append_printf (trace_str, "%s\n", location);
- g_free (location);
- }
- }
-
- res = mono_string_new (ex->object.vtable->domain, trace_str->str);
- g_string_free (trace_str, TRUE);
-
- return res;
-}
-
MonoArray *
ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
{
char *s;
sf->method = NULL;
- s = mono_method_full_name (method, TRUE);
+ s = mono_method_get_name_full (method, TRUE, MONO_TYPE_NAME_FORMAT_REFLECTION);
MONO_OBJECT_SETREF (sf, internal_method_name, mono_string_new (domain, s));
g_free (s);
}
sf->il_offset = location->il_offset;
} else {
SeqPoint sp;
- if (find_prev_seq_point_for_native_offset (domain, jinfo_get_method (ji), sf->native_offset, NULL, &sp))
+ if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (ji), sf->native_offset, NULL, &sp))
sf->il_offset = sp.il_offset;
else
sf->il_offset = -1;
g_assert (state->valid);
+ if (!state->unwind_data [MONO_UNWIND_DATA_DOMAIN])
+ /* Not attached */
+ return;
+
mono_walk_stack_full (func,
&state->ctx,
state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
if (!res)
return;
- if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji) {
+ if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji && !frame.ji->is_trampoline) {
MonoDebugSourceLocation *source;
source = mono_debug_lookup_source_location (jinfo_get_method (frame.ji), frame.native_offset, domain);
il_offset = source->il_offset;
} else {
SeqPoint sp;
- if (find_prev_seq_point_for_native_offset (domain, jinfo_get_method (frame.ji), frame.native_offset, NULL, &sp))
+ if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (frame.ji), frame.native_offset, NULL, &sp))
il_offset = sp.il_offset;
else
il_offset = -1;
frame.il_offset = il_offset;
- if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji) {
+ if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji && !frame.ji->is_trampoline) {
frame.actual_method = get_method_from_stack_frame (frame.ji, get_generic_info_from_stack_frame (frame.ji, &ctx));
} else {
frame.actual_method = frame.method;
if (!res)
return FALSE;
- if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE || frame.type == FRAME_TYPE_DEBUGGER_INVOKE)
+ if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+ frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+ frame.type == FRAME_TYPE_TRAMPOLINE)
continue;
ji = frame.ji;
return TRUE;
}
-typedef struct {
- guint32 skips;
- MonoSecurityFrame *frame;
-} MonoFrameSecurityInfo;
-
-static gboolean
-callback_get_first_frame_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
-{
- MonoFrameSecurityInfo *si = (MonoFrameSecurityInfo*) data;
- MonoJitInfo *ji = frame->ji;
- MonoMethod *method;
-
- if (!ji)
- return FALSE;
-
- /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
- method = jinfo_get_method (ji);
- if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
- method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
- method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
- method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
- method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
- return FALSE;
- }
-
- if (si->skips > 0) {
- si->skips--;
- return FALSE;
- }
-
- si->frame = mono_declsec_create_frame (frame->domain, ji);
-
- /* Stop - we only want the first frame (e.g. LinkDemand and InheritanceDemand) */
- return TRUE;
-}
-
-/**
- * ves_icall_System_Security_SecurityFrame_GetSecurityFrame:
- * @skip: the number of stack frames to skip
- *
- * This function returns a the security informations of a single stack frame
- * (after the skipped ones). This is required for [NonCas]LinkDemand[Choice]
- * and [NonCas]InheritanceDemand[Choice] as only the caller security is
- * evaluated.
- */
-MonoSecurityFrame*
-ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip)
-{
- MonoFrameSecurityInfo si;
-
- si.skips = skip;
- si.frame = NULL;
-
- mono_walk_stack (callback_get_first_frame_security_info, MONO_UNWIND_DEFAULT, &si);
-
- return (si.skips == 0) ? si.frame : NULL;
-}
-
-
-typedef struct {
- guint32 skips;
- MonoArray *stack;
- guint32 count;
- guint32 maximum;
-} MonoSecurityStack;
-
-static void
-grow_array (MonoSecurityStack *stack)
-{
- MonoDomain *domain = mono_domain_get ();
- guint32 newsize = (stack->maximum << 1);
- MonoArray *newstack = mono_array_new (domain, mono_defaults.runtimesecurityframe_class, newsize);
- int i;
- for (i=0; i < stack->maximum; i++) {
- gpointer frame = mono_array_get (stack->stack, gpointer, i);
- mono_array_setref (newstack, i, frame);
- }
- stack->maximum = newsize;
- stack->stack = newstack;
-}
-
-static gboolean
-callback_get_stack_frames_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
-{
- MonoSecurityStack *ss = (MonoSecurityStack*) data;
- MonoJitInfo *ji = frame->ji;
- MonoMethod *method;
-
- if (!ji)
- return FALSE;
-
- /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
- method = jinfo_get_method (ji);
- if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
- method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
- method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
- method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
- method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
- return FALSE;
- }
-
- if (ss->skips > 0) {
- ss->skips--;
- return FALSE;
- }
-
- if (ss->count == ss->maximum)
- grow_array (ss);
-
- mono_array_setref (ss->stack, ss->count++, mono_declsec_create_frame (frame->domain, ji));
-
- /* continue down the stack */
- return FALSE;
-}
-
static MonoArray *
glist_to_array (GList *list, MonoClass *eclass)
{
return res;
}
-/**
- * ves_icall_System_Security_SecurityFrame_GetSecurityStack:
- * @skip: the number of stack frames to skip
- *
- * This function returns an managed array of containing the security
- * informations for each frame (after the skipped ones). This is used for
- * [NonCas]Demand[Choice] where the complete evaluation of the stack is
- * required.
- */
-MonoArray*
-ves_icall_System_Security_SecurityFrame_GetSecurityStack (gint32 skip)
-{
- MonoSecurityStack ss;
-
-#if defined(__ia64__) || defined(__s390__) || defined(__s390x__)
- skip--;
-#endif
-
- ss.skips = skip;
- ss.count = 0;
- ss.maximum = MONO_CAS_INITIAL_STACK_SIZE;
- ss.stack = mono_array_new (mono_domain_get (), mono_defaults.runtimesecurityframe_class, ss.maximum);
- mono_walk_stack (callback_get_stack_frames_security_info, MONO_UNWIND_DEFAULT, &ss);
- /* g_warning ("STACK RESULT: %d out of %d", ss.count, ss.maximum); */
- return ss.stack;
-}
-
static MonoClass*
get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
{
}
/*
- * mini_jit_info_table_find:
+ * mini_jit_info_table_find_ext:
*
* Same as mono_jit_info_table_find, but search all the domains of the current thread
* if ADDR is not found in DOMAIN. The domain where the method was found is stored into
* OUT_DOMAIN if it is not NULL.
*/
MonoJitInfo*
-mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
+mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_trampolines, MonoDomain **out_domain)
{
MonoJitInfo *ji;
MonoInternalThread *t = mono_thread_internal_current ();
if (out_domain)
*out_domain = NULL;
- ji = mono_jit_info_table_find (domain, addr);
+ ji = mono_jit_info_table_find_internal (domain, addr, TRUE, allow_trampolines);
if (ji) {
if (out_domain)
*out_domain = domain;
/* maybe it is shared code, so we also search in the root domain */
if (domain != mono_get_root_domain ()) {
- ji = mono_jit_info_table_find (mono_get_root_domain (), addr);
+ ji = mono_jit_info_table_find_internal (mono_get_root_domain (), addr, TRUE, allow_trampolines);
if (ji) {
if (out_domain)
*out_domain = mono_get_root_domain ();
refs = (t->appdomain_refs) ? *(gpointer *) t->appdomain_refs : NULL;
for (; refs && *refs; refs++) {
if (*refs != domain && *refs != mono_get_root_domain ()) {
- ji = mono_jit_info_table_find ((MonoDomain*) *refs, addr);
+ ji = mono_jit_info_table_find_internal ((MonoDomain*) *refs, addr, TRUE, allow_trampolines);
if (ji) {
if (out_domain)
*out_domain = (MonoDomain*) *refs;
return NULL;
}
+MonoJitInfo*
+mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
+{
+ return mini_jit_info_table_find_ext (domain, addr, TRUE, out_domain);
+}
+
/*
* wrap_non_exception_throws:
*
#endif
}
-#define setup_managed_stacktrace_information() do { \
- if (mono_ex && !initial_trace_ips) { \
- trace_ips = g_list_reverse (trace_ips); \
- MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (trace_ips, mono_defaults.int_class)); \
- MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ()); \
- if (has_dynamic_methods) \
- /* These methods could go away anytime, so compute the stack trace now */ \
- MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex)); \
- } \
- g_list_free (trace_ips); \
- trace_ips = NULL; \
-} while (0)
+static void
+setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, MonoArray *initial_trace_ips, GList **trace_ips)
+{
+ if (mono_ex && !initial_trace_ips) {
+ *trace_ips = g_list_reverse (*trace_ips);
+ MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (*trace_ips, mono_defaults.int_class));
+ MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ());
+ if (dynamic_methods) {
+ /* These methods could go away anytime, so save a reference to them in the exception object */
+ GSList *l;
+ MonoMList *list = NULL;
+
+ for (l = dynamic_methods; l; l = l->next) {
+ guint32 dis_link;
+ MonoDomain *domain = mono_domain_get ();
+
+ if (domain->method_to_dyn_method) {
+ mono_domain_lock (domain);
+ dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, l->data);
+ mono_domain_unlock (domain);
+ if (dis_link) {
+ MonoObject *o = mono_gchandle_get_target (dis_link);
+ if (o) {
+ list = mono_mlist_prepend (list, o);
+ }
+ }
+ }
+ }
+
+ MONO_OBJECT_SETREF (mono_ex, dynamic_methods, list);
+ }
+ }
+ g_list_free (*trace_ips);
+ *trace_ips = NULL;
+}
+
/*
* mono_handle_exception_internal_first_pass:
*
MonoLMF *lmf = mono_get_lmf ();
MonoArray *initial_trace_ips = NULL;
GList *trace_ips = NULL;
+ GSList *dynamic_methods = NULL;
MonoException *mono_ex;
gboolean stack_overflow = FALSE;
MonoContext initial_ctx;
MonoMethod *method;
int frame_count = 0;
- gboolean has_dynamic_methods = FALSE;
gint32 filter_idx;
int i;
MonoObject *ex_obj;
unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
if (unwind_res) {
- if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
+ if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+ frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+ frame.type == FRAME_TYPE_TRAMPOLINE) {
*ctx = new_ctx;
continue;
}
}
if (!unwind_res) {
- setup_managed_stacktrace_information ();
+ setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
+ g_slist_free (dynamic_methods);
return FALSE;
}
}
if (method->dynamic)
- has_dynamic_methods = TRUE;
+ dynamic_methods = g_slist_prepend (dynamic_methods, method);
if (stack_overflow) {
if (DOES_STACK_GROWS_UP)
FIXME Not 100% sure if it's a good idea even with user clauses.
*/
if (is_user_frame)
- setup_managed_stacktrace_information ();
+ setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
- if (ji->from_llvm) {
#ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
+ if (ji->from_llvm)
MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
-#else
- g_assert_not_reached ();
-#endif
- } else {
-#ifdef MONO_ARCH_HAVE_OP_GET_EX_OBJ
- MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
-#else
- /* store the exception object in bp + ei->exvar_offset */
+ else
+ /* Can't pass the ex object in a register yet to filter clauses, because call_filter () might not support it */
*((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
+#else
+ g_assert (!ji->from_llvm);
+ /* store the exception object in bp + ei->exvar_offset */
+ *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
#endif
- }
#ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
/*
if (filtered) {
if (!is_user_frame)
- setup_managed_stacktrace_information ();
+ setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
+ g_slist_free (dynamic_methods);
/* mono_debugger_agent_handle_exception () needs this */
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
return TRUE;
}
if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) {
- setup_managed_stacktrace_information ();
+ setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
+ g_slist_free (dynamic_methods);
if (out_ji)
*out_ji = ji;
gboolean unhandled = FALSE;
/*
- * The exceptions caught by the mono_runtime_invoke () calls in mono_async_invoke () needs to be treated as
- * unhandled (#669836).
- * FIXME: The check below is hackish, but its hard to distinguish these runtime invoke calls from others
- * in the runtime.
+ * The exceptions caught by the mono_runtime_invoke () calls
+ * in the threadpool needs to be treated as unhandled (#669836).
+ *
+ * FIXME: The check below is hackish, but its hard to distinguish
+ * these runtime invoke calls from others in the runtime.
*/
if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
- if (prev_ji) {
- MonoInternalThread *thread = mono_thread_internal_current ();
- if (jinfo_get_method (prev_ji) == thread->async_invoke_method)
- unhandled = TRUE;
- }
+ if (prev_ji && jinfo_get_method (prev_ji) == mono_defaults.threadpool_perform_wait_callback_method)
+ unhandled = TRUE;
}
+
if (unhandled)
mono_debugger_agent_handle_exception (obj, ctx, NULL);
else
unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
if (unwind_res) {
- if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
+ if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
+ frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
+ frame.type == FRAME_TYPE_TRAMPOLINE) {
*ctx = new_ctx;
continue;
}
ex_obj = obj;
if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
- if (ji->from_llvm) {
#ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
- MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
+ MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
#else
- g_assert_not_reached ();
-#endif
- } else {
-#ifdef MONO_ARCH_HAVE_OP_GET_EX_OBJ
- MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
-#else
- /* store the exception object in bp + ei->exvar_offset */
- *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
+ g_assert (!ji->from_llvm);
+ /* store the exception object in bp + ei->exvar_offset */
+ *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
#endif
- }
}
#ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
return 0;
}
- if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
- (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT)) {
+ if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
if (mono_trace_is_enabled () && mono_trace_eval (method))
g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
jit_tls->orig_ex_ctx_set = TRUE;
jit_tls->orig_ex_ctx_set = FALSE;
call_filter (ctx, ei->handler_start);
}
- if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
- (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
+ if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
if (mono_trace_is_enabled () && mono_trace_eval (method))
g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
jit_tls->orig_ex_ctx_set = TRUE;
PrintOverflowUserData *user_data = data;
gchar *location;
- if (frame->ji)
+ if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
method = jinfo_get_method (frame->ji);
if (method) {
mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
#else
- if (ji && jinfo_get_method (ji))
+ if (ji && !ji->is_trampoline && jinfo_get_method (ji))
mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
else
mono_runtime_printf_err ("At <unmanaged>.");
{
MonoMethod *method = NULL;
- if (frame->ji)
+ if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
method = jinfo_get_method (frame->ji);
if (method) {
GString *p = (GString*)data;
MonoMethod *method = NULL;
- if (frame->ji)
+ if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
method = jinfo_get_method (frame->ji);
if (method && frame->domain) {
* it will deadlock. Call the syscall directly instead.
*/
pid = mono_runtime_syscall_fork ();
-
+#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 value other than 0 (the most permissive ptrace scope). Most modern Linux
+ // distributions set the scope to 1 which allows attaching only to direct children of
+ // the current process
+ prctl (PR_SET_PTRACER, pid, 0, 0, 0);
+ }
+#endif
if (pid == 0) {
dup2 (STDERR_FILENO, STDOUT_FILENO);
return FALSE;
}
- if (sigctx)
+ if (sigctx) {
mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
- else
+
+ ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
+ ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
+ ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
+ }
+ else {
+ mono_thread_state_init (ctx);
+ }
+
+ if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF])
+ return FALSE;
+
+ ctx->valid = TRUE;
+ return TRUE;
+#else
+ g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
+ return FALSE;
+#endif
+}
+
+void
+mono_thread_state_init (MonoThreadUnwindState *ctx)
+{
+ MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
+
#if defined(MONO_CROSS_COMPILE)
- ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
+ ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
#elif MONO_ARCH_HAS_MONO_CONTEXT
- MONO_CONTEXT_GET_CURRENT (ctx->ctx);
+ MONO_CONTEXT_GET_CURRENT (ctx->ctx);
#else
- g_error ("Use a null sigctx requires a working mono-context");
+ g_error ("Use a null sigctx requires a working mono-context");
#endif
ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
- ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
+ ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
ctx->valid = TRUE;
- return TRUE;
-#else
- g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
- return FALSE;
-#endif
}
+
gboolean
mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
{