Disable stack overflow trampolines in llvm-only mode.
[mono.git] / mono / mini / mini-exceptions.c
1 /*
2  * mini-exceptions.c: generic exception support
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Mono Team (mono-list@lists.ximian.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc.
9  * Copyright 2003-2008 Novell, Inc.
10  * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
11  */
12
13 #include <config.h>
14 #include <glib.h>
15 #include <string.h>
16
17 #ifdef HAVE_SIGNAL_H
18 #include <signal.h>
19 #endif
20
21 #ifdef HAVE_EXECINFO_H
22 #include <execinfo.h>
23 #endif
24
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
27 #endif
28
29 #ifdef HAVE_SYS_WAIT_H
30 #include <sys/wait.h>
31 #endif
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #ifdef HAVE_SYS_SYSCALL_H
38 #include <sys/syscall.h>
39 #endif
40
41 #ifdef HAVE_SYS_PRCTL_H
42 #include <sys/prctl.h>
43 #endif
44
45 #include <mono/metadata/appdomain.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/threads.h>
48 #include <mono/metadata/threads-types.h>
49 #include <mono/metadata/debug-helpers.h>
50 #include <mono/metadata/exception.h>
51 #include <mono/metadata/gc-internal.h>
52 #include <mono/metadata/mono-debug.h>
53 #include <mono/metadata/profiler.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/environment.h>
56 #include <mono/metadata/mono-mlist.h>
57 #include <mono/utils/mono-mmap.h>
58 #include <mono/utils/mono-logger-internal.h>
59
60 #include "mini.h"
61 #include "trace.h"
62 #include "debugger-agent.h"
63 #include "seq-points.h"
64
65 #ifdef ENABLE_EXTENSION_MODULE
66 #include "../../../mono-extensions/mono/mini/mini-exceptions.c"
67 #endif
68
69 #ifndef MONO_ARCH_CONTEXT_DEF
70 #define MONO_ARCH_CONTEXT_DEF
71 #endif
72
73 static gpointer restore_context_func, call_filter_func;
74 static gpointer throw_exception_func, rethrow_exception_func;
75 static gpointer throw_corlib_exception_func;
76
77 static gpointer try_more_restore_tramp = NULL;
78 static gpointer restore_stack_protection_tramp = NULL;
79
80 static MonoUnhandledExceptionFunc unhandled_exception_hook = NULL;
81 static gpointer unhandled_exception_hook_data = NULL;
82
83 static void try_more_restore (void);
84 static void restore_stack_protection (void);
85 static void mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data);
86 static void mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx);
87 static void mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data);
88
89 void
90 mono_exceptions_init (void)
91 {
92         MonoRuntimeExceptionHandlingCallbacks cbs;
93         if (mono_aot_only) {
94                 restore_context_func = mono_aot_get_trampoline ("restore_context");
95                 call_filter_func = mono_aot_get_trampoline ("call_filter");
96                 throw_exception_func = mono_aot_get_trampoline ("throw_exception");
97                 rethrow_exception_func = mono_aot_get_trampoline ("rethrow_exception");
98         } else {
99                 MonoTrampInfo *info;
100
101                 restore_context_func = mono_arch_get_restore_context (&info, FALSE);
102                 mono_tramp_info_register (info, NULL);
103                 call_filter_func = mono_arch_get_call_filter (&info, FALSE);
104                 mono_tramp_info_register (info, NULL);
105                 throw_exception_func = mono_arch_get_throw_exception (&info, FALSE);
106                 mono_tramp_info_register (info, NULL);
107                 rethrow_exception_func = mono_arch_get_rethrow_exception (&info, FALSE);
108                 mono_tramp_info_register (info, NULL);
109         }
110 #ifdef MONO_ARCH_HAVE_RESTORE_STACK_SUPPORT
111         if (!mono_llvm_only) {
112                 try_more_restore_tramp = mono_create_specific_trampoline (try_more_restore, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL);
113                 restore_stack_protection_tramp = mono_create_specific_trampoline (restore_stack_protection, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL);
114         }
115 #endif
116
117 #ifdef MONO_ARCH_HAVE_EXCEPTIONS_INIT
118         mono_arch_exceptions_init ();
119 #endif
120         cbs.mono_walk_stack_with_ctx = mono_runtime_walk_stack_with_ctx;
121         cbs.mono_walk_stack_with_state = mono_walk_stack_with_state;
122         cbs.mono_raise_exception = mono_get_throw_exception ();
123         cbs.mono_raise_exception_with_ctx = mono_raise_exception_with_ctx;
124         cbs.mono_exception_walk_trace = mono_exception_walk_trace;
125         cbs.mono_install_handler_block_guard = mono_install_handler_block_guard;
126         mono_install_eh_callbacks (&cbs);
127 }
128
129 gpointer
130 mono_get_throw_exception (void)
131 {
132         g_assert (throw_exception_func);
133         return throw_exception_func;
134 }
135
136 gpointer
137 mono_get_rethrow_exception (void)
138 {
139         g_assert (rethrow_exception_func);
140         return rethrow_exception_func;
141 }
142
143 gpointer
144 mono_get_call_filter (void)
145 {
146         g_assert (call_filter_func);
147         return call_filter_func;
148 }
149
150 gpointer
151 mono_get_restore_context (void)
152 {
153         g_assert (restore_context_func);
154         return restore_context_func;
155 }
156
157 gpointer
158 mono_get_throw_corlib_exception (void)
159 {
160         gpointer code = NULL;
161         MonoTrampInfo *info;
162
163         /* This depends on corlib classes so cannot be inited in mono_exceptions_init () */
164         if (throw_corlib_exception_func)
165                 return throw_corlib_exception_func;
166
167         if (mono_aot_only)
168                 code = mono_aot_get_trampoline ("throw_corlib_exception");
169         else {
170                 code = mono_arch_get_throw_corlib_exception (&info, FALSE);
171                 mono_tramp_info_register (info, NULL);
172         }
173
174         mono_memory_barrier ();
175
176         throw_corlib_exception_func = code;
177
178         return throw_corlib_exception_func;
179 }
180
181 static gboolean
182 is_address_protected (MonoJitInfo *ji, MonoJitExceptionInfo *ei, gpointer ip)
183 {
184         MonoTryBlockHoleTableJitInfo *table;
185         int i;
186         guint32 offset;
187         guint16 clause;
188
189         if (ei->try_start > ip || ip >= ei->try_end)
190                 return FALSE;
191
192         if (!ji->has_try_block_holes)
193                 return TRUE;
194
195         table = mono_jit_info_get_try_block_hole_table_info (ji);
196         offset = (guint32)((char*)ip - (char*)ji->code_start);
197         clause = (guint16)(ei - ji->clauses);
198         g_assert (clause < ji->num_clauses);
199
200         for (i = 0; i < table->num_holes; ++i) {
201                 MonoTryBlockHoleJitInfo *hole = &table->holes [i];
202                 if (hole->clause == clause && hole->offset <= offset && hole->offset + hole->length > offset)
203                         return FALSE;
204         }
205         return TRUE;
206 }
207
208 /*
209  * find_jit_info:
210  *
211  * Translate between the mono_arch_unwind_frame function and the old API.
212  */
213 static MonoJitInfo *
214 find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, 
215                            MonoContext *new_ctx, MonoLMF **lmf, gboolean *managed)
216 {
217         StackFrameInfo frame;
218         MonoJitInfo *ji;
219         gboolean err;
220         gpointer ip = MONO_CONTEXT_GET_IP (ctx);
221
222         /* Avoid costly table lookup during stack overflow */
223         if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
224                 ji = prev_ji;
225         else
226                 ji = mini_jit_info_table_find (domain, ip, NULL);
227
228         if (managed)
229                 *managed = FALSE;
230
231         err = mono_arch_unwind_frame (domain, jit_tls, ji, ctx, new_ctx, lmf, NULL, &frame);
232         if (!err)
233                 return (gpointer)-1;
234
235         if (*lmf && ((*lmf) != jit_tls->first_lmf) && ((gpointer)MONO_CONTEXT_GET_SP (new_ctx) >= (gpointer)(*lmf))) {
236                 /*
237                  * Remove any unused lmf.
238                  * Mask out the lower bits which might be used to hold additional information.
239                  */
240                 *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~(SIZEOF_VOID_P -1));
241         }
242
243         /* Convert between the new and the old APIs */
244         switch (frame.type) {
245         case FRAME_TYPE_MANAGED:
246                 if (managed)
247                         *managed = TRUE;
248                 return frame.ji;
249         case FRAME_TYPE_TRAMPOLINE:
250                 return frame.ji;
251         case FRAME_TYPE_MANAGED_TO_NATIVE:
252                 if (frame.ji)
253                         return frame.ji;
254                 else {
255                         memset (res, 0, sizeof (MonoJitInfo));
256                         res->d.method = frame.method;
257                         return res;
258                 }
259         case FRAME_TYPE_DEBUGGER_INVOKE: {
260                 MonoContext tmp_ctx;
261
262                 /*
263                  * The normal exception handling code can't handle this frame, so just
264                  * skip it.
265                  */
266                 ji = find_jit_info (domain, jit_tls, res, NULL, new_ctx, &tmp_ctx, lmf, managed);
267                 memcpy (new_ctx, &tmp_ctx, sizeof (MonoContext));
268                 return ji;
269         }
270         default:
271                 g_assert_not_reached ();
272                 return NULL;
273         }
274 }
275
276 /* mono_find_jit_info:
277  *
278  * This function is used to gather information from @ctx. It return the 
279  * MonoJitInfo of the corresponding function, unwinds one stack frame and
280  * stores the resulting context into @new_ctx. It also stores a string 
281  * describing the stack location into @trace (if not NULL), and modifies
282  * the @lmf if necessary. @native_offset return the IP offset from the 
283  * start of the function or -1 if that info is not available.
284  */
285 MonoJitInfo *
286 mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx,
287                     MonoContext *new_ctx, char **trace, MonoLMF **lmf, int *native_offset,
288                     gboolean *managed)
289 {
290         gboolean managed2;
291         gpointer ip = MONO_CONTEXT_GET_IP (ctx);
292         MonoJitInfo *ji;
293         MonoMethod *method = NULL;
294
295         if (trace)
296                 *trace = NULL;
297
298         if (native_offset)
299                 *native_offset = -1;
300
301         if (managed)
302                 *managed = FALSE;
303
304         ji = find_jit_info (domain, jit_tls, res, prev_ji, ctx, new_ctx, lmf, &managed2);
305
306         if (ji == (gpointer)-1)
307                 return ji;
308
309         if (ji && !ji->is_trampoline)
310                 method = jinfo_get_method (ji);
311
312         if (managed2 || (method && method->wrapper_type)) {
313                 const char *real_ip, *start;
314                 gint32 offset;
315
316                 start = (const char *)ji->code_start;
317                 if (!managed2)
318                         /* ctx->ip points into native code */
319                         real_ip = (const char*)MONO_CONTEXT_GET_IP (new_ctx);
320                 else
321                         real_ip = (const char*)ip;
322
323                 if ((real_ip >= start) && (real_ip <= start + ji->code_size))
324                         offset = real_ip - start;
325                 else
326                         offset = -1;
327
328                 if (native_offset)
329                         *native_offset = offset;
330
331                 if (managed)
332                         if (!method->wrapper_type || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
333                                 *managed = TRUE;
334
335                 if (trace)
336                         *trace = mono_debug_print_stack_frame (method, offset, domain);
337         } else {
338                 if (trace) {
339                         char *fname = mono_method_full_name (jinfo_get_method (res), TRUE);
340                         *trace = g_strdup_printf ("in (unmanaged) %s", fname);
341                         g_free (fname);
342                 }
343         }
344
345         return ji;
346 }
347
348 /*
349  * mono_find_jit_info_ext:
350  *
351  *   A version of mono_find_jit_info which returns all data in the StackFrameInfo
352  * structure.
353  * A note about frames of type FRAME_TYPE_MANAGED_TO_NATIVE:
354  * - These frames are used to mark managed-to-native transitions, so CTX will refer to native
355  * code, and new_ctx will refer to the last managed frame. The caller should unwind once more
356  * to obtain the last managed frame.
357  * If SAVE_LOCATIONS is not NULL, it should point to an array of size MONO_MAX_IREGS.
358  * On return, it will be filled with the locations where callee saved registers are saved
359  * by the current frame. This is returned outside of StackFrameInfo because it can be
360  * quite large on some platforms.
361  * If ASYNC true, this function will be async safe, but some fields of frame and frame->ji will
362  * not be set.
363  */
364 gboolean
365 mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, 
366                                                 MonoJitInfo *prev_ji, MonoContext *ctx,
367                                                 MonoContext *new_ctx, char **trace, MonoLMF **lmf,
368                                                 mgreg_t **save_locations,
369                                                 StackFrameInfo *frame)
370 {
371         gboolean err;
372         gpointer ip = MONO_CONTEXT_GET_IP (ctx);
373         MonoJitInfo *ji;
374         MonoDomain *target_domain = domain;
375         MonoMethod *method = NULL;
376         gboolean async = mono_thread_info_is_async_context ();
377
378         if (trace)
379                 *trace = NULL;
380
381         /* Avoid costly table lookup during stack overflow */
382         if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
383                 ji = prev_ji;
384         else
385                 ji = mini_jit_info_table_find (domain, ip, &target_domain);
386
387         if (!target_domain)
388                 target_domain = domain;
389
390         if (save_locations)
391                 memset (save_locations, 0, MONO_MAX_IREGS * sizeof (mgreg_t*));
392
393         err = mono_arch_unwind_frame (target_domain, jit_tls, ji, ctx, new_ctx, lmf, save_locations, frame);
394         if (!err)
395                 return FALSE;
396
397         if (*lmf && ((*lmf) != jit_tls->first_lmf) && ((gpointer)MONO_CONTEXT_GET_SP (new_ctx) >= (gpointer)(*lmf))) {
398                 /*
399                  * Remove any unused lmf.
400                  * Mask out the lower bits which might be used to hold additional information.
401                  */
402                 *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~(SIZEOF_VOID_P -1));
403         }
404
405         if (frame->ji && !frame->ji->is_trampoline && !frame->ji->async)
406                 method = jinfo_get_method (frame->ji);
407
408         if (frame->type == FRAME_TYPE_MANAGED && method) {
409                 if (!method->wrapper_type || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
410                         frame->managed = TRUE;
411         }
412
413         if (frame->type == FRAME_TYPE_MANAGED_TO_NATIVE) {
414                 /*
415                  * This type of frame is just a marker, the caller should unwind once more to get the
416                  * last managed frame.
417                  */
418                 frame->ji = NULL;
419                 frame->method = NULL;
420         }
421
422         frame->native_offset = -1;
423         frame->domain = target_domain;
424         frame->async_context = async;
425
426         ji = frame->ji;
427
428         if (frame->type == FRAME_TYPE_MANAGED)
429                 frame->method = method;
430
431         if (ji && (frame->managed || (method && method->wrapper_type))) {
432                 const char *real_ip, *start;
433
434                 start = (const char *)ji->code_start;
435                 if (!frame->managed)
436                         /* ctx->ip points into native code */
437                         real_ip = (const char*)MONO_CONTEXT_GET_IP (new_ctx);
438                 else
439                         real_ip = (const char*)ip;
440
441                 if ((real_ip >= start) && (real_ip <= start + ji->code_size))
442                         frame->native_offset = real_ip - start;
443                 else
444                         frame->native_offset = -1;
445
446                 if (trace)
447                         *trace = mono_debug_print_stack_frame (method, frame->native_offset, domain);
448         } else {
449                 if (trace && frame->method) {
450                         char *fname = mono_method_full_name (frame->method, TRUE);
451                         *trace = g_strdup_printf ("in (unmanaged) %s", fname);
452                         g_free (fname);
453                 }
454         }
455
456         return TRUE;
457 }
458
459 /*
460  * This function is async-safe.
461  */
462 static gpointer
463 get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx)
464 {
465         MonoGenericJitInfo *gi;
466         MonoMethod *method;
467         gpointer info;
468
469         if (!ji->has_generic_jit_info)
470                 return NULL;
471         gi = mono_jit_info_get_generic_jit_info (ji);
472         if (!gi->has_this)
473                 return NULL;
474
475         info = NULL;
476         /*
477          * Search location list if available, it contains the precise location of the
478          * argument for every pc offset, even if the method was interrupted while it was in
479          * its prolog.
480          */
481         if (gi->nlocs) {
482                 int offset = (mgreg_t)MONO_CONTEXT_GET_IP (ctx) - (mgreg_t)ji->code_start;
483                 int i;
484
485                 for (i = 0; i < gi->nlocs; ++i) {
486                         MonoDwarfLocListEntry *entry = &gi->locations [i];
487
488                         if (offset >= entry->from && (offset < entry->to || entry->to == 0)) {
489                                 if (entry->is_reg)
490                                         info = (gpointer)mono_arch_context_get_int_reg (ctx, entry->reg);
491                                 else
492                                         info = *(gpointer*)(gpointer)((char*)mono_arch_context_get_int_reg (ctx, entry->reg) + entry->offset);
493                                 break;
494                         }
495                 }
496                 g_assert (i < gi->nlocs);
497         } else {
498                 if (gi->this_in_reg)
499                         info = (gpointer)mono_arch_context_get_int_reg (ctx, gi->this_reg);
500                 else
501                         info = *(gpointer*)(gpointer)((char*)mono_arch_context_get_int_reg (ctx, gi->this_reg) +
502                                                                                   gi->this_offset);
503         }
504
505         method = jinfo_get_method (ji);
506         if (mono_method_get_context (method)->method_inst) {
507                 return info;
508         } else if ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype) {
509                 return info;
510         } else {
511                 /* Avoid returning a managed object */
512                 MonoObject *this_obj = info;
513
514                 return this_obj->vtable->klass;
515         }
516 }
517
518 static MonoGenericContext
519 get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
520 {
521         MonoGenericContext context = { NULL, NULL };
522         MonoClass *klass, *method_container_class;
523         MonoMethod *method;
524
525         g_assert (generic_info);
526
527         method = jinfo_get_method (ji);
528         g_assert (method->is_inflated);
529         if (mono_method_get_context (method)->method_inst) {
530                 MonoMethodRuntimeGenericContext *mrgctx = generic_info;
531
532                 klass = mrgctx->class_vtable->klass;
533                 context.method_inst = mrgctx->method_inst;
534                 g_assert (context.method_inst);
535         } else if ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype) {
536                 MonoVTable *vtable = generic_info;
537
538                 klass = vtable->klass;
539         } else {
540                 klass = generic_info;
541         }
542
543         //g_assert (!method->klass->generic_container);
544         if (method->klass->generic_class)
545                 method_container_class = method->klass->generic_class->container_class;
546         else
547                 method_container_class = method->klass;
548
549         /* class might refer to a subclass of method's class */
550         while (!(klass == method->klass || (klass->generic_class && klass->generic_class->container_class == method_container_class))) {
551                 klass = klass->parent;
552                 g_assert (klass);
553         }
554
555         if (klass->generic_class || klass->generic_container)
556                 context.class_inst = mini_class_get_context (klass)->class_inst;
557
558         if (klass->generic_class)
559                 g_assert (mono_class_has_parent_and_ignore_generics (klass->generic_class->container_class, method_container_class));
560         else
561                 g_assert (mono_class_has_parent_and_ignore_generics (klass, method_container_class));
562
563         return context;
564 }
565
566 static MonoMethod*
567 get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
568 {
569         MonoError error;
570         MonoGenericContext context;
571         MonoMethod *method;
572         
573         if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
574                 return jinfo_get_method (ji);
575         context = get_generic_context_from_stack_frame (ji, generic_info);
576
577         method = jinfo_get_method (ji);
578         method = mono_method_get_declaring_generic_method (method);
579         method = mono_class_inflate_generic_method_checked (method, &context, &error);
580         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
581
582         return method;
583 }
584
585 /**
586  * mono_exception_walk_native_trace:
587  * @ex: The exception object whose frames should be walked
588  * @func: callback to call for each stack frame
589  * @user_data: data passed to the callback
590  *
591  * This function walks the stacktrace of an exception. For
592  * each frame the callback function is called with the relevant info.
593  * The walk ends when no more stack frames are found or when the callback
594  * returns a TRUE value.
595  */
596  
597 gboolean
598 mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpointer user_data)
599 {
600         MonoDomain *domain = mono_domain_get ();
601         MonoArray *ta = ex->trace_ips;
602         int len, i;
603
604         if (ta == NULL)
605                 return FALSE;
606
607         len = mono_array_length (ta) >> 1;
608         for (i = 0; i < len; i++) {
609                 gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
610                 gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
611                 MonoJitInfo *ji = mono_jit_info_table_find (domain, ip);
612
613                 if (ji == NULL) {
614                         if (func (NULL, ip, 0, FALSE, user_data))
615                                 return TRUE;
616                 } else {
617                         MonoMethod *method = get_method_from_stack_frame (ji, generic_info);
618                         if (func (method, ji->code_start, (char *) ip - (char *) ji->code_start, TRUE, user_data))
619                                 return TRUE;
620                 }
621         }
622         
623         return len > 0;
624 }
625
626 MonoArray *
627 ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
628 {
629         MonoDomain *domain = mono_domain_get ();
630         MonoArray *res;
631         MonoArray *ta = exc->trace_ips;
632         MonoDebugSourceLocation *location;
633         int i, len;
634
635         if (ta == NULL) {
636                 /* Exception is not thrown yet */
637                 return mono_array_new (domain, mono_defaults.stack_frame_class, 0);
638         }
639
640         len = mono_array_length (ta) >> 1;
641
642         res = mono_array_new (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0);
643
644         for (i = skip; i < len; i++) {
645                 MonoJitInfo *ji;
646                 MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class);
647                 gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
648                 gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
649                 MonoMethod *method;
650
651                 ji = mono_jit_info_table_find (domain, ip);
652                 if (ji == NULL) {
653                         /* Unmanaged frame */
654                         mono_array_setref (res, i, sf);
655                         continue;
656                 }
657
658                 g_assert (ji != NULL);
659
660                 method = get_method_from_stack_frame (ji, generic_info);
661                 if (jinfo_get_method (ji)->wrapper_type) {
662                         char *s;
663
664                         sf->method = NULL;
665                         s = mono_method_get_name_full (method, TRUE, MONO_TYPE_NAME_FORMAT_REFLECTION);
666                         MONO_OBJECT_SETREF (sf, internal_method_name, mono_string_new (domain, s));
667                         g_free (s);
668                 }
669                 else
670                         MONO_OBJECT_SETREF (sf, method, mono_method_get_object (domain, method, NULL));
671
672                 sf->method_index = ji->from_aot ? mono_aot_find_method_index (method) : 0xffffff;
673                 sf->method_address = (gsize) ji->code_start;
674                 sf->native_offset = (char *)ip - (char *)ji->code_start;
675
676                 /*
677                  * mono_debug_lookup_source_location() returns both the file / line number information
678                  * and the IL offset.  Note that computing the IL offset is already an expensive
679                  * operation, so we shouldn't call this method twice.
680                  */
681                 location = mono_debug_lookup_source_location (jinfo_get_method (ji), sf->native_offset, domain);
682                 if (location) {
683                         sf->il_offset = location->il_offset;
684                 } else {
685                         SeqPoint sp;
686                         if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (ji), sf->native_offset, NULL, &sp))
687                                 sf->il_offset = sp.il_offset;
688                         else
689                                 sf->il_offset = -1;
690                 }
691
692                 if (need_file_info) {
693                         if (location && location->source_file) {
694                                 MONO_OBJECT_SETREF (sf, filename, mono_string_new (domain, location->source_file));
695                                 sf->line = location->row;
696                                 sf->column = location->column;
697                         } else {
698                                 sf->line = sf->column = 0;
699                                 sf->filename = NULL;
700                         }
701                 }
702
703                 mono_debug_free_source_location (location);
704                 mono_array_setref (res, i, sf);
705         }
706
707         return res;
708 }
709
710 static void
711 mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
712 {
713         if (!start_ctx) {
714                 MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
715                 if (jit_tls && jit_tls->orig_ex_ctx_set)
716                         start_ctx = &jit_tls->orig_ex_ctx;
717         }
718         mono_walk_stack_with_ctx (func, start_ctx, unwind_options, user_data);
719 }
720 /**
721  * mono_walk_stack_with_ctx:
722  *
723  * Unwind the current thread starting at @start_ctx.
724  * 
725  * If @start_ctx is null, we capture the current context.
726  */
727 void
728 mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
729 {
730         MonoContext extra_ctx;
731         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
732         MONO_ARCH_CONTEXT_DEF
733
734         if (!thread || !thread->jit_data)
735                 return;
736
737         if (!start_ctx) {
738                 mono_arch_flush_register_windows ();
739
740 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
741                 MONO_INIT_CONTEXT_FROM_CURRENT (&extra_ctx);
742 #else
743                 MONO_INIT_CONTEXT_FROM_FUNC (&extra_ctx, mono_walk_stack_with_ctx);
744 #endif
745                 start_ctx = &extra_ctx;
746         }
747
748         mono_walk_stack_full (func, start_ctx, mono_domain_get (), thread->jit_data, mono_get_lmf (), unwind_options, user_data);
749 }
750
751 /**
752  * mono_walk_stack_with_state:
753  *
754  * Unwind a thread described by @state.
755  *
756  * State must be valid (state->valid == TRUE).
757  *
758  * If you are using this function to unwind another thread, make sure it is suspended.
759  * 
760  * If @state is null, we capture the current context.
761  */
762 void
763 mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, MonoUnwindOptions unwind_options, void *user_data)
764 {
765         MonoThreadUnwindState extra_state;
766         if (!state) {
767                 g_assert (!mono_thread_info_is_async_context ());
768                 if (!mono_thread_state_init_from_current (&extra_state))
769                         return;
770                 state = &extra_state;
771         }
772
773         g_assert (state->valid);
774
775         if (!state->unwind_data [MONO_UNWIND_DATA_DOMAIN])
776                 /* Not attached */
777                 return;
778
779         mono_walk_stack_full (func,
780                 &state->ctx, 
781                 state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
782                 state->unwind_data [MONO_UNWIND_DATA_JIT_TLS],
783                 state->unwind_data [MONO_UNWIND_DATA_LMF],
784                 unwind_options, user_data);
785 }
786
787 void
788 mono_walk_stack (MonoJitStackWalk func, MonoUnwindOptions options, void *user_data)
789 {
790         MonoThreadUnwindState state;
791         if (!mono_thread_state_init_from_current (&state))
792                 return;
793         mono_walk_stack_with_state (func, &state, options, user_data);
794 }
795
796 /**
797  * mono_walk_stack_full:
798  * @func: callback to call for each stack frame
799  * @domain: starting appdomain, can be NULL to use the current domain
800  * @unwind_options: what extra information the unwinder should gather
801  * @start_ctx: starting state of the stack walk, can be NULL.
802  * @thread: the thread whose stack to walk, can be NULL to use the current thread
803  * @lmf: the LMF of @thread, can be NULL to use the LMF of the current thread
804  * @user_data: data passed to the callback
805  *
806  * This function walks the stack of a thread, starting from the state
807  * represented by start_ctx. For each frame the callback
808  * function is called with the relevant info. The walk ends when no more
809  * managed stack frames are found or when the callback returns a TRUE value.
810  */
811 static void
812 mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data)
813 {
814         gint il_offset, i;
815         MonoContext ctx, new_ctx;
816         StackFrameInfo frame;
817         gboolean res;
818         mgreg_t *reg_locations [MONO_MAX_IREGS];
819         mgreg_t *new_reg_locations [MONO_MAX_IREGS];
820         gboolean get_reg_locations = unwind_options & MONO_UNWIND_REG_LOCATIONS;
821         gboolean async = mono_thread_info_is_async_context ();
822
823         g_assert (start_ctx);
824         g_assert (domain);
825         g_assert (jit_tls);
826         /*The LMF will be null if the target have no managed frames.*/
827         /* g_assert (lmf); */
828
829         if (async)
830                 g_assert (unwind_options == MONO_UNWIND_NONE);
831
832         memcpy (&ctx, start_ctx, sizeof (MonoContext));
833         memset (reg_locations, 0, sizeof (reg_locations));
834
835         while (MONO_CONTEXT_GET_SP (&ctx) < jit_tls->end_of_stack) {
836                 frame.lmf = lmf;
837                 res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, get_reg_locations ? new_reg_locations : NULL, &frame);
838                 if (!res)
839                         return;
840
841                 if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji && !frame.ji->is_trampoline) {
842                         MonoDebugSourceLocation *source;
843
844                         source = mono_debug_lookup_source_location (jinfo_get_method (frame.ji), frame.native_offset, domain);
845                         if (source) {
846                                 il_offset = source->il_offset;
847                         } else {
848                                 SeqPoint sp;
849                                 if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (frame.ji), frame.native_offset, NULL, &sp))
850                                         il_offset = sp.il_offset;
851                                 else
852                                         il_offset = -1;
853                         }
854                         mono_debug_free_source_location (source);
855                 } else
856                         il_offset = -1;
857
858                 frame.il_offset = il_offset;
859
860                 if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji && !frame.ji->is_trampoline) {
861                         frame.actual_method = get_method_from_stack_frame (frame.ji, get_generic_info_from_stack_frame (frame.ji, &ctx));
862                 } else {
863                         frame.actual_method = frame.method;
864                 }
865
866                 if (get_reg_locations)
867                         frame.reg_locations = reg_locations;
868
869                 if (func (&frame, &ctx, user_data))
870                         return;
871
872                 if (get_reg_locations) {
873                         for (i = 0; i < MONO_MAX_IREGS; ++i)
874                                 if (new_reg_locations [i])
875                                         reg_locations [i] = new_reg_locations [i];
876                 }
877                 
878                 ctx = new_ctx;
879         }
880 }
881
882 MonoBoolean
883 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
884                           MonoReflectionMethod **method, 
885                           gint32 *iloffset, gint32 *native_offset,
886                           MonoString **file, gint32 *line, gint32 *column)
887 {
888         MonoDomain *domain = mono_domain_get ();
889         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
890         MonoLMF *lmf = mono_get_lmf ();
891         MonoJitInfo *ji = NULL;
892         MonoContext ctx, new_ctx;
893         MonoDebugSourceLocation *location;
894         MonoMethod *jmethod = NULL, *actual_method;
895         StackFrameInfo frame;
896         gboolean res;
897
898         MONO_ARCH_CONTEXT_DEF;
899
900         mono_arch_flush_register_windows ();
901
902 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
903         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx);
904 #else
905         MONO_INIT_CONTEXT_FROM_FUNC (&ctx, ves_icall_get_frame_info);
906 #endif
907
908         new_ctx = ctx;
909         do {
910                 ctx = new_ctx;
911                 res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, &frame);
912                 if (!res)
913                         return FALSE;
914
915                 if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
916                                 frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
917                                 frame.type == FRAME_TYPE_TRAMPOLINE)
918                         continue;
919
920                 ji = frame.ji;
921                 *native_offset = frame.native_offset;
922
923                 /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */
924                 jmethod = jinfo_get_method (ji);
925                 if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE)
926                         continue;
927                 skip--;
928         } while (skip >= 0);
929
930         actual_method = get_method_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, &ctx));
931
932         mono_gc_wbarrier_generic_store (method, (MonoObject*) mono_method_get_object (domain, actual_method, NULL));
933
934         location = mono_debug_lookup_source_location (jmethod, *native_offset, domain);
935         if (location)
936                 *iloffset = location->il_offset;
937         else
938                 *iloffset = 0;
939
940         if (need_file_info) {
941                 if (location) {
942                         mono_gc_wbarrier_generic_store (file, (MonoObject*) mono_string_new (domain, location->source_file));
943                         *line = location->row;
944                         *column = location->column;
945                 } else {
946                         *file = NULL;
947                         *line = *column = 0;
948                 }
949         }
950
951         mono_debug_free_source_location (location);
952
953         return TRUE;
954 }
955
956 static MonoArray *
957 glist_to_array (GList *list, MonoClass *eclass) 
958 {
959         MonoDomain *domain = mono_domain_get ();
960         MonoArray *res;
961         int len, i;
962
963         if (!list)
964                 return NULL;
965
966         len = g_list_length (list);
967         res = mono_array_new (domain, eclass, len);
968
969         for (i = 0; list; list = list->next, i++)
970                 mono_array_set (res, gpointer, i, list->data);
971
972         return res;
973 }
974
975 static MonoClass*
976 get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
977 {
978         MonoClass *catch_class = ei->data.catch_class;
979         MonoType *inflated_type;
980         MonoGenericContext context;
981
982         /*MonoJitExceptionInfo::data is an union used by filter and finally clauses too.*/
983         if (!catch_class || ei->flags != MONO_EXCEPTION_CLAUSE_NONE)
984                 return NULL;
985
986         if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
987                 return catch_class;
988         context = get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx));
989
990         /* FIXME: we shouldn't inflate but instead put the
991            type in the rgctx and fetch it from there.  It
992            might be a good idea to do this lazily, i.e. only
993            when the exception is actually thrown, so as not to
994            waste space for exception clauses which might never
995            be encountered. */
996         inflated_type = mono_class_inflate_generic_type (&catch_class->byval_arg, &context);
997         catch_class = mono_class_from_mono_type (inflated_type);
998         mono_metadata_free_type (inflated_type);
999
1000         return catch_class;
1001 }
1002
1003 /*
1004  * mini_jit_info_table_find_ext:
1005  *
1006  *   Same as mono_jit_info_table_find, but search all the domains of the current thread
1007  * if ADDR is not found in DOMAIN. The domain where the method was found is stored into
1008  * OUT_DOMAIN if it is not NULL.
1009  */
1010 MonoJitInfo*
1011 mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_trampolines, MonoDomain **out_domain)
1012 {
1013         MonoJitInfo *ji;
1014         MonoInternalThread *t = mono_thread_internal_current ();
1015         gpointer *refs;
1016
1017         if (out_domain)
1018                 *out_domain = NULL;
1019
1020         ji = mono_jit_info_table_find_internal (domain, addr, TRUE, allow_trampolines);
1021         if (ji) {
1022                 if (out_domain)
1023                         *out_domain = domain;
1024                 return ji;
1025         }
1026
1027         /* maybe it is shared code, so we also search in the root domain */
1028         if (domain != mono_get_root_domain ()) {
1029                 ji = mono_jit_info_table_find_internal (mono_get_root_domain (), addr, TRUE, allow_trampolines);
1030                 if (ji) {
1031                         if (out_domain)
1032                                 *out_domain = mono_get_root_domain ();
1033                         return ji;
1034                 }
1035         }
1036
1037         if (!t)
1038                 return NULL;
1039
1040         refs = (t->appdomain_refs) ? *(gpointer *) t->appdomain_refs : NULL;
1041         for (; refs && *refs; refs++) {
1042                 if (*refs != domain && *refs != mono_get_root_domain ()) {
1043                         ji = mono_jit_info_table_find_internal ((MonoDomain*) *refs, addr, TRUE, allow_trampolines);
1044                         if (ji) {
1045                                 if (out_domain)
1046                                         *out_domain = (MonoDomain*) *refs;
1047                                 return ji;
1048                         }
1049                 }
1050         }
1051
1052         return NULL;
1053 }
1054
1055 MonoJitInfo*
1056 mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
1057 {
1058         return mini_jit_info_table_find_ext (domain, addr, TRUE, out_domain);
1059 }
1060
1061 /*
1062  * wrap_non_exception_throws:
1063  *
1064  *   Determine whenever M's assembly has a RuntimeCompatibilityAttribute with the
1065  * WrapNonExceptionThrows flag set.
1066  */
1067 static gboolean
1068 wrap_non_exception_throws (MonoMethod *m)
1069 {
1070         MonoAssembly *ass = m->klass->image->assembly;
1071         MonoCustomAttrInfo* attrs;
1072         static MonoClass *klass;
1073         int i;
1074         gboolean val = FALSE;
1075
1076         g_assert (ass);
1077         if (ass->wrap_non_exception_throws_inited)
1078                 return ass->wrap_non_exception_throws;
1079
1080         klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1081
1082         attrs = mono_custom_attrs_from_assembly (ass);
1083         if (attrs) {
1084                 for (i = 0; i < attrs->num_attrs; ++i) {
1085                         MonoCustomAttrEntry *attr = &attrs->attrs [i];
1086                         const gchar *p;
1087                         int num_named, named_type, name_len;
1088                         char *name;
1089
1090                         if (!attr->ctor || attr->ctor->klass != klass)
1091                                 continue;
1092                         /* Decode the RuntimeCompatibilityAttribute. See reflection.c */
1093                         p = (const char*)attr->data;
1094                         g_assert (read16 (p) == 0x0001);
1095                         p += 2;
1096                         num_named = read16 (p);
1097                         if (num_named != 1)
1098                                 continue;
1099                         p += 2;
1100                         named_type = *p;
1101                         p ++;
1102                         /* data_type = *p; */
1103                         p ++;
1104                         /* Property */
1105                         if (named_type != 0x54)
1106                                 continue;
1107                         name_len = mono_metadata_decode_blob_size (p, &p);
1108                         name = g_malloc (name_len + 1);
1109                         memcpy (name, p, name_len);
1110                         name [name_len] = 0;
1111                         p += name_len;
1112                         g_assert (!strcmp (name, "WrapNonExceptionThrows"));
1113                         g_free (name);
1114                         /* The value is a BOOLEAN */
1115                         val = *p;
1116                 }
1117                 mono_custom_attrs_free (attrs);
1118         }
1119
1120         ass->wrap_non_exception_throws = val;
1121         mono_memory_barrier ();
1122         ass->wrap_non_exception_throws_inited = TRUE;
1123
1124         return val;
1125 }
1126
1127 #ifndef MONO_ARCH_STACK_GROWS_UP
1128 #define DOES_STACK_GROWS_UP 1
1129 #else
1130 #define DOES_STACK_GROWS_UP 0
1131 #endif
1132
1133 #define MAX_UNMANAGED_BACKTRACE 128
1134 static MonoArray*
1135 build_native_trace (void)
1136 {
1137 /* This puppy only makes sense on mobile, IOW, ARM. */
1138 #if defined (HAVE_BACKTRACE_SYMBOLS) && defined (TARGET_ARM)
1139         MonoArray *res;
1140         void *native_trace [MAX_UNMANAGED_BACKTRACE];
1141         int size = backtrace (native_trace, MAX_UNMANAGED_BACKTRACE);
1142         int i;
1143
1144         if (!size)
1145                 return NULL;
1146         res = mono_array_new (mono_domain_get (), mono_defaults.int_class, size);
1147
1148         for (i = 0; i < size; i++)
1149                 mono_array_set (res, gpointer, i, native_trace [i]);
1150         return res;
1151 #else
1152         return NULL;
1153 #endif
1154 }
1155
1156 static void
1157 setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, MonoArray *initial_trace_ips, GList **trace_ips)
1158 {
1159         if (mono_ex && !initial_trace_ips) {
1160                 *trace_ips = g_list_reverse (*trace_ips);
1161                 MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (*trace_ips, mono_defaults.int_class));
1162                 MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ());
1163                 if (dynamic_methods) {
1164                         /* These methods could go away anytime, so save a reference to them in the exception object */
1165                         GSList *l;
1166                         MonoMList *list = NULL;
1167
1168                         for (l = dynamic_methods; l; l = l->next) {
1169                                 guint32 dis_link;
1170                                 MonoDomain *domain = mono_domain_get ();
1171
1172                                 if (domain->method_to_dyn_method) {
1173                                         mono_domain_lock (domain);
1174                                         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, l->data);
1175                                         mono_domain_unlock (domain);
1176                                         if (dis_link) {
1177                                                 MonoObject *o = mono_gchandle_get_target (dis_link);
1178                                                 if (o) {
1179                                                         list = mono_mlist_prepend (list, o);
1180                                                 }
1181                                         }
1182                                 }
1183                         }
1184
1185                         MONO_OBJECT_SETREF (mono_ex, dynamic_methods, list);
1186                 }
1187         }
1188         g_list_free (*trace_ips);
1189         *trace_ips = NULL;
1190 }
1191
1192 /*
1193  * mono_handle_exception_internal_first_pass:
1194  *
1195  *   The first pass of exception handling. Unwind the stack until a catch clause which can catch
1196  * OBJ is found. Run the index of the filter clause which caught the exception into
1197  * OUT_FILTER_IDX. Return TRUE if the exception is caught, FALSE otherwise.
1198  */
1199 static gboolean
1200 mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception)
1201 {
1202         MonoDomain *domain = mono_domain_get ();
1203         MonoJitInfo *ji = NULL;
1204         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1205         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1206         MonoLMF *lmf = mono_get_lmf ();
1207         MonoArray *initial_trace_ips = NULL;
1208         GList *trace_ips = NULL;
1209         GSList *dynamic_methods = NULL;
1210         MonoException *mono_ex;
1211         gboolean stack_overflow = FALSE;
1212         MonoContext initial_ctx;
1213         MonoMethod *method;
1214         int frame_count = 0;
1215         gint32 filter_idx;
1216         int i;
1217         MonoObject *ex_obj;
1218
1219         g_assert (ctx != NULL);
1220
1221         if (obj == domain->stack_overflow_ex)
1222                 stack_overflow = TRUE;
1223
1224         mono_ex = (MonoException*)obj;
1225         initial_trace_ips = mono_ex->trace_ips;
1226
1227         if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1228                 mono_ex = (MonoException*)obj;
1229                 initial_trace_ips = mono_ex->trace_ips;
1230         } else {
1231                 mono_ex = NULL;
1232         }
1233
1234         if (!call_filter)
1235                 call_filter = mono_get_call_filter ();
1236
1237         g_assert (jit_tls->end_of_stack);
1238         g_assert (jit_tls->abort_func);
1239
1240         if (out_filter_idx)
1241                 *out_filter_idx = -1;
1242         if (out_ji)
1243                 *out_ji = NULL;
1244         if (out_prev_ji)
1245                 *out_prev_ji = NULL;
1246         filter_idx = 0;
1247         initial_ctx = *ctx;
1248
1249         while (1) {
1250                 MonoContext new_ctx;
1251                 guint32 free_stack;
1252                 int clause_index_start = 0;
1253                 gboolean unwind_res = TRUE;
1254                 
1255                 StackFrameInfo frame;
1256
1257                 if (out_prev_ji)
1258                         *out_prev_ji = ji;
1259
1260                 unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1261                 if (unwind_res) {
1262                         if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
1263                                         frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
1264                                         frame.type == FRAME_TYPE_TRAMPOLINE) {
1265                                 *ctx = new_ctx;
1266                                 continue;
1267                         }
1268                         g_assert (frame.type == FRAME_TYPE_MANAGED);
1269                         ji = frame.ji;
1270                 }
1271
1272                 if (!unwind_res) {
1273                         setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
1274                         g_slist_free (dynamic_methods);
1275                         return FALSE;
1276                 }
1277
1278                 frame_count ++;
1279                 method = jinfo_get_method (ji);
1280                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1281
1282                 if (mini_get_debug_options ()->reverse_pinvoke_exceptions && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
1283                         g_error ("A native frame was found while unwinding the stack after an exception.\n"
1284                                          "The native frame called the managed method:\n%s\n",
1285                                          mono_method_full_name (method, TRUE));
1286                 }
1287
1288                 if (method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
1289                         /* 
1290                          * Avoid overwriting the stack trace if the exception is
1291                          * rethrown. Also avoid giant stack traces during a stack
1292                          * overflow.
1293                          */
1294                         if (!initial_trace_ips && (frame_count < 1000)) {
1295                                 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
1296                                 trace_ips = g_list_prepend (trace_ips,
1297                                                                                         get_generic_info_from_stack_frame (ji, ctx));
1298                         }
1299                 }
1300
1301                 if (method->dynamic)
1302                         dynamic_methods = g_slist_prepend (dynamic_methods, method);
1303
1304                 if (stack_overflow) {
1305                         if (DOES_STACK_GROWS_UP)
1306                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1307                         else
1308                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1309                 } else {
1310                         free_stack = 0xffffff;
1311                 }
1312                                 
1313                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1314                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1315                         gboolean filtered = FALSE;
1316
1317                         /* 
1318                          * During stack overflow, wait till the unwinding frees some stack
1319                          * space before running handlers/finalizers.
1320                          */
1321                         if (free_stack <= (64 * 1024))
1322                                 continue;
1323
1324                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1325                                 /* catch block */
1326                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1327
1328                                 /*
1329                                  * Have to unwrap RuntimeWrappedExceptions if the
1330                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1331                                  */
1332                                 if (non_exception && !wrap_non_exception_throws (method))
1333                                         ex_obj = non_exception;
1334                                 else
1335                                         ex_obj = obj;
1336
1337                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1338                                         gboolean is_user_frame = method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD;
1339 #ifndef DISABLE_PERFCOUNTERS
1340                                         mono_perfcounters->exceptions_filters++;
1341 #endif
1342                                         /*
1343                                         Here's the thing, if this is a filter clause done by a wrapper like runtime invoke, we don't want to
1344                                         trim the stackframe since if it returns FALSE we lose information.
1345
1346                                         FIXME Not 100% sure if it's a good idea even with user clauses.
1347                                         */
1348                                         if (is_user_frame)
1349                                                 setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
1350
1351 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1352                                         if (ji->from_llvm)
1353                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1354                                         else
1355                                                 /* Can't pass the ex object in a register yet to filter clauses, because call_filter () might not support it */
1356                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1357 #else
1358                                         g_assert (!ji->from_llvm);
1359                                         /* store the exception object in bp + ei->exvar_offset */
1360                                         *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1361 #endif
1362
1363 #ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
1364                                         /*
1365                                          * Pass the original il clause index to the landing pad so it can
1366                                          * branch to the landing pad associated with the il clause.
1367                                          * This is needed because llvm compiled code assumes that the EH
1368                                          * code always branches to the innermost landing pad.
1369                                          */
1370                                         if (ji->from_llvm)
1371                                                 MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
1372 #endif
1373
1374                                         mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
1375                                         filtered = call_filter (ctx, ei->data.filter);
1376                                         mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
1377                                         if (filtered && out_filter_idx)
1378                                                 *out_filter_idx = filter_idx;
1379                                         if (out_ji)
1380                                                 *out_ji = ji;
1381                                         filter_idx ++;
1382
1383                                         if (filtered) {
1384                                                 if (!is_user_frame)
1385                                                         setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
1386                                                 g_slist_free (dynamic_methods);
1387                                                 /* mono_debugger_agent_handle_exception () needs this */
1388                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1389                                                 return TRUE;
1390                                         }
1391                                 }
1392
1393                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) {
1394                                         setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
1395                                         g_slist_free (dynamic_methods);
1396
1397                                         if (out_ji)
1398                                                 *out_ji = ji;
1399
1400                                         /* mono_debugger_agent_handle_exception () needs this */
1401                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1402                                         return TRUE;
1403                                 }
1404                         }
1405                 }
1406
1407                 *ctx = new_ctx;
1408         }
1409
1410         g_assert_not_reached ();
1411 }
1412
1413 /**
1414  * mono_handle_exception_internal:
1415  * @ctx: saved processor state
1416  * @obj: the exception object
1417  * @resume: whenever to resume unwinding based on the state in MonoJitTlsData.
1418  */
1419 static gboolean
1420 mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume, MonoJitInfo **out_ji)
1421 {
1422         MonoDomain *domain = mono_domain_get ();
1423         MonoJitInfo *ji, *prev_ji;
1424         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1425         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1426         MonoLMF *lmf = mono_get_lmf ();
1427         MonoException *mono_ex;
1428         gboolean stack_overflow = FALSE;
1429         MonoContext initial_ctx;
1430         MonoMethod *method;
1431         int frame_count = 0;
1432         gint32 filter_idx, first_filter_idx = 0;
1433         int i;
1434         MonoObject *ex_obj;
1435         MonoObject *non_exception = NULL;
1436
1437         g_assert (ctx != NULL);
1438         if (!obj) {
1439                 MonoException *ex = mono_get_exception_null_reference ();
1440                 MONO_OBJECT_SETREF (ex, message, mono_string_new (domain, "Object reference not set to an instance of an object"));
1441                 obj = (MonoObject *)ex;
1442         } 
1443
1444         /*
1445          * Allocate a new exception object instead of the preconstructed ones.
1446          */
1447         if (obj == domain->stack_overflow_ex) {
1448                 /*
1449                  * It is not a good idea to try and put even more pressure on the little stack available.
1450                  * obj = mono_get_exception_stack_overflow ();
1451                  */
1452                 stack_overflow = TRUE;
1453         }
1454         else if (obj == domain->null_reference_ex) {
1455                 obj = mono_get_exception_null_reference ();
1456         }
1457
1458         if (!mono_object_isinst (obj, mono_defaults.exception_class)) {
1459                 non_exception = obj;
1460                 obj = mono_get_exception_runtime_wrapped (obj);
1461         }
1462
1463         mono_ex = (MonoException*)obj;
1464
1465         if (mini_get_debug_options ()->suspend_on_exception) {
1466                 mono_runtime_printf_err ("Exception thrown, suspending...");
1467                 while (1)
1468                         ;
1469         }
1470
1471         if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1472                 mono_ex = (MonoException*)obj;
1473         } else {
1474                 mono_ex = NULL;
1475         }
1476
1477         if (mono_ex && jit_tls->class_cast_from) {
1478                 if (!strcmp (mono_ex->object.vtable->klass->name, "InvalidCastException")) {
1479                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1480                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1481                         char *msg = g_strdup_printf ("Unable to cast object of type '%s' to type '%s'.", from_name, to_name);
1482                         mono_ex->message = mono_string_new (domain, msg);
1483                         g_free (from_name);
1484                         g_free (to_name);
1485                         g_free (msg);
1486                 }
1487                 if (!strcmp (mono_ex->object.vtable->klass->name, "ArrayTypeMismatchException")) {
1488                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1489                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1490                         char *msg = g_strdup_printf ("Source array of type '%s' cannot be cast to destination array type '%s'.", from_name, to_name);
1491                         mono_ex->message = mono_string_new (domain, msg);
1492                         g_free (from_name);
1493                         g_free (to_name);
1494                         g_free (msg);
1495                 }
1496         }
1497
1498         if (!call_filter)
1499                 call_filter = mono_get_call_filter ();
1500
1501         g_assert (jit_tls->end_of_stack);
1502         g_assert (jit_tls->abort_func);
1503
1504         /*
1505          * We set orig_ex_ctx_set to TRUE/FALSE around profiler calls to make sure it doesn't
1506          * end up being TRUE on any code path.
1507          */
1508         memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
1509
1510         if (!resume) {
1511                 gboolean res;
1512
1513                 MonoContext ctx_cp = *ctx;
1514                 if (mono_trace_is_enabled ()) {
1515                         MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
1516                         MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
1517                         MonoObject *message;
1518                         const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
1519                         char *msg = NULL;
1520                         MonoObject *exc = NULL;
1521                         if (get_message == NULL) {
1522                                 message = NULL;
1523                         } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
1524                                 message = NULL;
1525                                 msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
1526                         } else {
1527                                 message = mono_runtime_invoke (get_message, obj, NULL, &exc);
1528                                 
1529                         }
1530                         if (msg == NULL) {
1531                                 msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
1532                         }
1533                         g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)GetCurrentThreadId (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg);
1534                         g_free (msg);
1535                         if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
1536                                 mono_print_thread_dump_from_ctx (ctx);
1537                 }
1538                 jit_tls->orig_ex_ctx_set = TRUE;
1539                 mono_profiler_exception_thrown (obj);
1540                 jit_tls->orig_ex_ctx_set = FALSE;
1541
1542                 res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
1543
1544                 if (!res) {
1545                         if (mini_get_debug_options ()->break_on_exc)
1546                                 G_BREAKPOINT ();
1547                         mono_debugger_agent_handle_exception (obj, ctx, NULL);
1548
1549                         if (mini_get_debug_options ()->suspend_on_unhandled) {
1550                                 mono_runtime_printf_err ("Unhandled exception, suspending...");
1551                                 while (1)
1552                                         ;
1553                         }
1554
1555                         // FIXME: This runs managed code so it might cause another stack overflow when
1556                         // we are handling a stack overflow
1557                         mono_unhandled_exception (obj);
1558                 } else {
1559                         gboolean unhandled = FALSE;
1560
1561                         /*
1562                          * The exceptions caught by the mono_runtime_invoke () calls
1563                          * in the threadpool needs to be treated as unhandled (#669836).
1564                          *
1565                          * FIXME: The check below is hackish, but its hard to distinguish
1566                          * these runtime invoke calls from others in the runtime.
1567                          */
1568                         if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
1569                                 if (prev_ji && jinfo_get_method (prev_ji) == mono_defaults.threadpool_perform_wait_callback_method)
1570                                         unhandled = TRUE;
1571                         }
1572
1573                         if (unhandled)
1574                                 mono_debugger_agent_handle_exception (obj, ctx, NULL);
1575                         else
1576                                 mono_debugger_agent_handle_exception (obj, ctx, &ctx_cp);
1577                 }
1578         }
1579
1580         if (out_ji)
1581                 *out_ji = NULL;
1582         filter_idx = 0;
1583         initial_ctx = *ctx;
1584
1585         while (1) {
1586                 MonoContext new_ctx;
1587                 guint32 free_stack;
1588                 int clause_index_start = 0;
1589                 gboolean unwind_res = TRUE;
1590                 
1591                 if (resume) {
1592                         resume = FALSE;
1593                         ji = jit_tls->resume_state.ji;
1594                         new_ctx = jit_tls->resume_state.new_ctx;
1595                         clause_index_start = jit_tls->resume_state.clause_index;
1596                         lmf = jit_tls->resume_state.lmf;
1597                         first_filter_idx = jit_tls->resume_state.first_filter_idx;
1598                         filter_idx = jit_tls->resume_state.filter_idx;
1599                 } else {
1600                         StackFrameInfo frame;
1601
1602                         unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1603                         if (unwind_res) {
1604                                 if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
1605                                                 frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
1606                                                 frame.type == FRAME_TYPE_TRAMPOLINE) {
1607                                         *ctx = new_ctx;
1608                                         continue;
1609                                 }
1610                                 g_assert (frame.type == FRAME_TYPE_MANAGED);
1611                                 ji = frame.ji;
1612                         }
1613                 }
1614
1615                 if (!unwind_res) {
1616                         *(mono_get_lmf_addr ()) = lmf;
1617
1618                         jit_tls->abort_func (obj);
1619                         g_assert_not_reached ();
1620                 }
1621
1622                 method = jinfo_get_method (ji);
1623                 frame_count ++;
1624                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1625
1626                 if (stack_overflow) {
1627                         if (DOES_STACK_GROWS_UP)
1628                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1629                         else
1630                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1631                 } else {
1632                         free_stack = 0xffffff;
1633                 }
1634                                 
1635                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1636                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1637                         gboolean filtered = FALSE;
1638
1639                         /* 
1640                          * During stack overflow, wait till the unwinding frees some stack
1641                          * space before running handlers/finalizers.
1642                          */
1643                         if (free_stack <= (64 * 1024))
1644                                 continue;
1645
1646                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1647                                 /* catch block */
1648                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1649
1650                                 /*
1651                                  * Have to unwrap RuntimeWrappedExceptions if the
1652                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1653                                  */
1654                                 if (non_exception && !wrap_non_exception_throws (method))
1655                                         ex_obj = non_exception;
1656                                 else
1657                                         ex_obj = obj;
1658
1659                                 if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
1660 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1661                                         MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1662 #else
1663                                         g_assert (!ji->from_llvm);
1664                                         /* store the exception object in bp + ei->exvar_offset */
1665                                         *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1666 #endif
1667                                 }
1668
1669 #ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
1670                                 if (ji->from_llvm)
1671                                         MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
1672 #endif
1673
1674                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1675                                         /* 
1676                                          * Filter clauses should only be run in the 
1677                                          * first pass of exception handling.
1678                                          */
1679                                         filtered = (filter_idx == first_filter_idx);
1680                                         filter_idx ++;
1681                                 }
1682
1683                                 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
1684                                          mono_object_isinst (ex_obj, catch_class)) || filtered) {
1685                                         /*
1686                                          * This guards against the situation that we abort a thread that is executing a finally clause
1687                                          * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
1688                                          * check for this situation here and resume interruption if we are below the guarded block.
1689                                          */
1690                                         if (G_UNLIKELY (jit_tls->handler_block_return_address)) {
1691                                                 gboolean is_outside = FALSE;
1692                                                 gpointer prot_bp = MONO_CONTEXT_GET_BP (&jit_tls->handler_block_context);
1693                                                 gpointer catch_bp = MONO_CONTEXT_GET_BP (ctx);
1694                                                 //FIXME make this stack direction aware
1695                                                 if (catch_bp > prot_bp) {
1696                                                         is_outside = TRUE;
1697                                                 } else if (catch_bp == prot_bp) {
1698                                                         /* Can be either try { try { } catch {} } finally {} or try { try { } finally {} } catch {}
1699                                                          * So we check if the catch handler_start is protected by the guarded handler protected region
1700                                                          *
1701                                                          * Assumptions:
1702                                                          *      If there is an outstanding guarded_block return address, it means the current thread must be aborted.
1703                                                          *      This is the only way to reach out the guarded block as other cases are handled by the trampoline.
1704                                                          *      There aren't any further finally/fault handler blocks down the stack over this exception.
1705                                                          *   This must be ensured by the code that installs the guard trampoline.
1706                                                          */
1707                                                         g_assert (ji == mini_jit_info_table_find (domain, MONO_CONTEXT_GET_IP (&jit_tls->handler_block_context), NULL));
1708
1709                                                         if (!is_address_protected (ji, jit_tls->handler_block, ei->handler_start)) {
1710                                                                 is_outside = TRUE;
1711                                                         }
1712                                                 }
1713                                                 if (is_outside) {
1714                                                         jit_tls->handler_block_return_address = NULL;
1715                                                         jit_tls->handler_block = NULL;
1716                                                         mono_thread_resume_interruption (); /*We ignore the exception here, it will be raised later*/
1717                                                 }
1718                                         }
1719
1720                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1721                                                 g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1722                                         jit_tls->orig_ex_ctx_set = TRUE;
1723                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1724                                         jit_tls->orig_ex_ctx_set = FALSE;
1725                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1726                                         mono_set_lmf (lmf);
1727 #ifndef DISABLE_PERFCOUNTERS
1728                                         mono_perfcounters->exceptions_depth += frame_count;
1729 #endif
1730                                         if (obj == domain->stack_overflow_ex)
1731                                                 jit_tls->handling_stack_ovf = FALSE;
1732
1733                                         return 0;
1734                                 }
1735                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
1736                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1737                                                 g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1738                                         jit_tls->orig_ex_ctx_set = TRUE;
1739                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1740                                         jit_tls->orig_ex_ctx_set = FALSE;
1741                                         call_filter (ctx, ei->handler_start);
1742                                 }
1743                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
1744                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1745                                                 g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1746                                         jit_tls->orig_ex_ctx_set = TRUE;
1747                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1748                                         jit_tls->orig_ex_ctx_set = FALSE;
1749 #ifndef DISABLE_PERFCOUNTERS
1750                                         mono_perfcounters->exceptions_finallys++;
1751 #endif
1752                                         mono_set_lmf (lmf);
1753                                         if (ji->from_llvm) {
1754                                                 /* 
1755                                                  * LLVM compiled finally handlers follow the design
1756                                                  * of the c++ ehabi, i.e. they call a resume function
1757                                                  * at the end instead of returning to the caller.
1758                                                  * So save the exception handling state,
1759                                                  * mono_resume_unwind () will call us again to continue
1760                                                  * the unwinding.
1761                                                  */
1762                                                 jit_tls->resume_state.ex_obj = obj;
1763                                                 jit_tls->resume_state.ji = ji;
1764                                                 jit_tls->resume_state.clause_index = i + 1;
1765                                                 jit_tls->resume_state.ctx = *ctx;
1766                                                 jit_tls->resume_state.new_ctx = new_ctx;
1767                                                 jit_tls->resume_state.lmf = lmf;
1768                                                 jit_tls->resume_state.first_filter_idx = first_filter_idx;
1769                                                 jit_tls->resume_state.filter_idx = filter_idx;
1770                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1771                                                 return 0;
1772                                         } else {
1773                                                 call_filter (ctx, ei->handler_start);
1774                                         }
1775                                 }
1776                         }
1777                 }
1778
1779                 jit_tls->orig_ex_ctx_set = TRUE;
1780                 mono_profiler_exception_method_leave (method);
1781                 jit_tls->orig_ex_ctx_set = FALSE;
1782
1783                 *ctx = new_ctx;
1784         }
1785
1786         g_assert_not_reached ();
1787 }
1788
1789 /**
1790  * mono_debugger_run_finally:
1791  * @start_ctx: saved processor state
1792  *
1793  * This method is called by the Mono Debugger to call all `finally' clauses of the
1794  * current stack frame.  It's used when the user issues a `return' command to make
1795  * the current stack frame return.  After returning from this method, the debugger
1796  * unwinds the stack one frame and gives control back to the user.
1797  *
1798  * NOTE: This method is only used when running inside the Mono Debugger.
1799  */
1800 void
1801 mono_debugger_run_finally (MonoContext *start_ctx)
1802 {
1803         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1804         MonoDomain *domain = mono_domain_get ();
1805         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1806         MonoLMF *lmf = mono_get_lmf ();
1807         MonoContext ctx, new_ctx;
1808         MonoJitInfo *ji, rji;
1809         int i;
1810
1811         ctx = *start_ctx;
1812
1813         ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
1814         if (!ji || ji == (gpointer)-1)
1815                 return;
1816
1817         if (!call_filter)
1818                 call_filter = mono_get_call_filter ();
1819
1820         for (i = 0; i < ji->num_clauses; i++) {
1821                 MonoJitExceptionInfo *ei = &ji->clauses [i];
1822
1823                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
1824                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
1825                         call_filter (&ctx, ei->handler_start);
1826                 }
1827         }
1828 }
1829
1830 /**
1831  * mono_handle_exception:
1832  * @ctx: saved processor state
1833  * @obj: the exception object
1834  */
1835 gboolean
1836 mono_handle_exception (MonoContext *ctx, gpointer obj)
1837 {
1838 #ifndef DISABLE_PERFCOUNTERS
1839         mono_perfcounters->exceptions_thrown++;
1840 #endif
1841
1842         return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
1843 }
1844
1845 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
1846
1847 #ifndef MONO_ARCH_USE_SIGACTION
1848 #error "Can't use sigaltstack without sigaction"
1849 #endif
1850
1851 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
1852
1853 void
1854 mono_setup_altstack (MonoJitTlsData *tls)
1855 {
1856         size_t stsize = 0;
1857         stack_t sa;
1858         guint8 *staddr = NULL;
1859
1860         if (mono_running_on_valgrind ())
1861                 return;
1862
1863         mono_thread_info_get_stack_bounds (&staddr, &stsize);
1864
1865         g_assert (staddr);
1866
1867         tls->end_of_stack = staddr + stsize;
1868         tls->stack_size = stsize;
1869
1870         /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
1871
1872         tls->stack_ovf_guard_base = staddr + mono_pagesize ();
1873         tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
1874
1875         g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
1876
1877         if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
1878                 /* mprotect can fail for the main thread stack */
1879                 gpointer gaddr = mono_valloc (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON|MONO_MMAP_FIXED);
1880                 g_assert (gaddr == tls->stack_ovf_guard_base);
1881                 tls->stack_ovf_valloced = TRUE;
1882         }
1883
1884         /* Setup an alternate signal stack */
1885         tls->signal_stack = mono_valloc (0, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON);
1886         tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1887
1888         g_assert (tls->signal_stack);
1889
1890         sa.ss_sp = tls->signal_stack;
1891         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1892         sa.ss_flags = 0;
1893         g_assert (sigaltstack (&sa, NULL) == 0);
1894
1895         mono_gc_register_altstack ((char*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size, (char*)staddr + stsize - ((char*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size), tls->signal_stack, tls->signal_stack_size);
1896 }
1897
1898 void
1899 mono_free_altstack (MonoJitTlsData *tls)
1900 {
1901         stack_t sa;
1902         int err;
1903
1904         sa.ss_sp = tls->signal_stack;
1905         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1906         sa.ss_flags = SS_DISABLE;
1907         err = sigaltstack  (&sa, NULL);
1908         g_assert (err == 0);
1909
1910         if (tls->signal_stack)
1911                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE);
1912         if (tls->stack_ovf_valloced)
1913                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size);
1914         else
1915                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
1916 }
1917
1918 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
1919
1920 void
1921 mono_setup_altstack (MonoJitTlsData *tls)
1922 {
1923 }
1924
1925 void
1926 mono_free_altstack (MonoJitTlsData *tls)
1927 {
1928 }
1929
1930 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
1931
1932 static gboolean
1933 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
1934 {
1935         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
1936         /* we need to leave some room for throwing the exception */
1937         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
1938                 unprotect_size -= mono_pagesize ();
1939         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
1940          * is sufficient stack
1941          */
1942         //fprintf (stderr, "restoring stack protection: %p-%p (%d)\n", jit_tls->stack_ovf_guard_base, (char*)jit_tls->stack_ovf_guard_base + unprotect_size, unprotect_size);
1943         if (unprotect_size)
1944                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
1945         return unprotect_size == jit_tls->stack_ovf_guard_size;
1946 }
1947
1948 static G_GNUC_UNUSED void
1949 try_more_restore (void)
1950 {
1951         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1952         if (try_restore_stack_protection (jit_tls, 500))
1953                 jit_tls->restore_stack_prot = NULL;
1954 }
1955
1956 static G_GNUC_UNUSED void
1957 restore_stack_protection (void)
1958 {
1959         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1960         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
1961         /* if we can't restore the stack protection, keep a callback installed so
1962          * we'll try to restore as much stack as we can at each return from unmanaged
1963          * code.
1964          */
1965         if (try_restore_stack_protection (jit_tls, 4096))
1966                 jit_tls->restore_stack_prot = NULL;
1967         else
1968                 jit_tls->restore_stack_prot = try_more_restore_tramp;
1969         /* here we also throw a stack overflow exception */
1970         ex->trace_ips = NULL;
1971         ex->stack_trace = NULL;
1972         mono_raise_exception (ex);
1973 }
1974
1975 gpointer
1976 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
1977 {
1978         void (*func)(void) = (gpointer)tramp_data;
1979         func ();
1980         return NULL;
1981 }
1982
1983 gboolean
1984 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr)
1985 {
1986         if (mono_llvm_only)
1987                 return FALSE;
1988
1989         /* we got a stack overflow in the soft-guard pages
1990          * There are two cases:
1991          * 1) managed code caused the overflow: we unprotect the soft-guard page
1992          * and let the arch-specific code trigger the exception handling mechanism
1993          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
1994          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
1995          * and hope we can continue with those enabled, at least until the hard-guard page
1996          * is hit. The alternative to continuing here is to just print a message and abort.
1997          * We may add in the future the code to protect the pages again in the codepath
1998          * when we return from unmanaged to managed code.
1999          */
2000         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2001                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2002                 /* we unprotect the minimum amount we can */
2003                 guint32 guard_size;
2004                 gboolean handled = FALSE;
2005
2006                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2007                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2008                         guard_size -= mono_pagesize ();
2009                 }
2010                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2011                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2012                 mono_mprotect ((char*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size - guard_size, guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
2013 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2014                 if (ji) {
2015                         mono_arch_handle_altstack_exception (ctx, siginfo, fault_addr, TRUE);
2016                         handled = TRUE;
2017                 }
2018 #endif
2019                 if (!handled) {
2020                         /* We print a message: after this even managed stack overflows
2021                          * may crash the runtime
2022                          */
2023                         mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2024                         if (!jit_tls->handling_stack_ovf) {
2025                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2026                                 jit_tls->handling_stack_ovf = 1;
2027                         } else {
2028                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2029                         }
2030                 }
2031                 return TRUE;
2032         }
2033         return FALSE;
2034 }
2035
2036 typedef struct {
2037         MonoMethod *omethod;
2038         int count;
2039 } PrintOverflowUserData;
2040
2041 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2042 static gboolean
2043 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2044 {
2045         MonoMethod *method = NULL;
2046         PrintOverflowUserData *user_data = data;
2047         gchar *location;
2048
2049         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2050                 method = jinfo_get_method (frame->ji);
2051
2052         if (method) {
2053                 if (user_data->count == 0) {
2054                         /* The first frame is in its prolog, so a line number cannot be computed */
2055                         user_data->count ++;
2056                         return FALSE;
2057                 }
2058
2059                 /* If this is a one method overflow, skip the other instances */
2060                 if (method == user_data->omethod)
2061                         return FALSE;
2062
2063                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2064                 mono_runtime_printf_err ("  %s", location);
2065                 g_free (location);
2066
2067                 if (user_data->count == 1) {
2068                         mono_runtime_printf_err ("  <...>");
2069                         user_data->omethod = method;
2070                 } else {
2071                         user_data->omethod = NULL;
2072                 }
2073
2074                 user_data->count ++;
2075         } else
2076                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2077
2078         return FALSE;
2079 }
2080 #endif
2081
2082 void
2083 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2084 {
2085 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2086         PrintOverflowUserData ud;
2087         MonoContext mctx;
2088 #endif
2089
2090         /* we don't do much now, but we can warn the user with a useful message */
2091         mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2092
2093 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2094         mono_sigctx_to_monoctx (ctx, &mctx);
2095                         
2096         mono_runtime_printf_err ("Stacktrace:");
2097
2098         memset (&ud, 0, sizeof (ud));
2099
2100         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2101 #else
2102         if (ji && !ji->is_trampoline && jinfo_get_method (ji))
2103                 mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
2104         else
2105                 mono_runtime_printf_err ("At <unmanaged>.");
2106 #endif
2107
2108         _exit (1);
2109 }
2110
2111 static gboolean
2112 print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2113 {
2114         MonoMethod *method = NULL;
2115
2116         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2117                 method = jinfo_get_method (frame->ji);
2118
2119         if (method) {
2120                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2121                 mono_runtime_printf_err ("  %s", location);
2122                 g_free (location);
2123         } else
2124                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2125
2126         return FALSE;
2127 }
2128
2129 static G_GNUC_UNUSED gboolean
2130 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2131 {
2132         GString *p = (GString*)data;
2133         MonoMethod *method = NULL;
2134
2135         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2136                 method = jinfo_get_method (frame->ji);
2137
2138         if (method && frame->domain) {
2139                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
2140                 g_string_append_printf (p, "  %s\n", location);
2141                 g_free (location);
2142         } else
2143                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2144
2145         return FALSE;
2146 }
2147
2148 #ifndef MONO_CROSS_COMPILE
2149
2150 static gboolean handling_sigsegv = FALSE;
2151
2152 /*
2153  * mono_handle_native_sigsegv:
2154  *
2155  *   Handle a SIGSEGV received while in native code by printing diagnostic 
2156  * information and aborting.
2157  */
2158 void
2159 mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2160 {
2161 #ifdef MONO_ARCH_USE_SIGACTION
2162         struct sigaction sa;
2163 #endif
2164         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2165         const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
2166
2167         if (handling_sigsegv)
2168                 return;
2169
2170         if (mini_get_debug_options ()->suspend_on_sigsegv) {
2171                 mono_runtime_printf_err ("Received SIGSEGV, suspending...");
2172 #ifdef HOST_WIN32
2173                 while (1)
2174                         ;
2175 #else
2176                 while (1) {
2177                         sleep (1);
2178                 }
2179 #endif
2180         }
2181
2182         /* To prevent infinite loops when the stack walk causes a crash */
2183         handling_sigsegv = TRUE;
2184
2185         /* !jit_tls means the thread was not registered with the runtime */
2186         if (jit_tls && mono_thread_internal_current ()) {
2187                 mono_runtime_printf_err ("Stacktrace:\n");
2188
2189                 mono_walk_stack (print_stack_frame_to_stderr, TRUE, NULL);
2190         }
2191
2192 #ifdef HAVE_BACKTRACE_SYMBOLS
2193  {
2194         void *array [256];
2195         char **names;
2196         int i, size;
2197
2198         mono_runtime_printf_err ("\nNative stacktrace:\n");
2199
2200         size = backtrace (array, 256);
2201         names = backtrace_symbols (array, size);
2202         for (i =0; i < size; ++i) {
2203                 mono_runtime_printf_err ("\t%s", names [i]);
2204         }
2205         free (names);
2206
2207         /* Try to get more meaningful information using gdb */
2208
2209 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2210         if (!mini_get_debug_options ()->no_gdb_backtrace) {
2211                 /* From g_spawn_command_line_sync () in eglib */
2212                 pid_t pid;
2213                 int status;
2214                 pid_t crashed_pid = getpid ();
2215
2216                 //pid = fork ();
2217                 /*
2218                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2219                  * it will deadlock. Call the syscall directly instead.
2220                  */
2221                 pid = mono_runtime_syscall_fork ();
2222 #if defined (HAVE_PRCTL) && defined(PR_SET_PTRACER)
2223                 if (pid > 0) {
2224                         // Allow gdb to attach to the process even if ptrace_scope sysctl variable is set to
2225                         // a value other than 0 (the most permissive ptrace scope). Most modern Linux
2226                         // distributions set the scope to 1 which allows attaching only to direct children of
2227                         // the current process
2228                         prctl (PR_SET_PTRACER, pid, 0, 0, 0);
2229                 }
2230 #endif
2231                 if (pid == 0) {
2232                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2233
2234                         mono_gdb_render_native_backtraces (crashed_pid);
2235                         exit (1);
2236                 }
2237
2238                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2239                 waitpid (pid, &status, 0);
2240         }
2241 #endif
2242  }
2243 #elif defined (ENABLE_EXTENSION_MODULE)
2244         mono_extension_handle_native_sigsegv (ctx, info);
2245 #endif
2246
2247         /*
2248          * A SIGSEGV indicates something went very wrong so we can no longer depend
2249          * on anything working. So try to print out lots of diagnostics, starting 
2250          * with ones which have a greater chance of working.
2251          */
2252         mono_runtime_printf_err (
2253                          "\n"
2254                          "=================================================================\n"
2255                          "Got a %s while executing native code. This usually indicates\n"
2256                          "a fatal error in the mono runtime or one of the native libraries \n"
2257                          "used by your application.\n"
2258                          "=================================================================\n",
2259                         signal_str);
2260
2261
2262 #ifdef MONO_ARCH_USE_SIGACTION
2263
2264         /* Remove our SIGABRT handler */
2265         sa.sa_handler = SIG_DFL;
2266         sigemptyset (&sa.sa_mask);
2267         sa.sa_flags = 0;
2268
2269         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2270
2271 #endif
2272
2273         if (!mono_do_crash_chaining) {
2274                 /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2275 #if defined (PLATFORM_ANDROID)
2276                 exit (-1);
2277 #else
2278                 abort ();
2279 #endif
2280         }
2281 }
2282
2283 #else
2284
2285 void
2286 mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2287 {
2288         g_assert_not_reached ();
2289 }
2290
2291 #endif /* !MONO_CROSS_COMPILE */
2292
2293 static void
2294 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2295 {
2296         MonoInternalThread *thread = mono_thread_internal_current ();
2297 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2298         MonoContext ctx;
2299 #endif
2300         GString* text;
2301         char *name;
2302 #ifndef HOST_WIN32
2303         char *wapi_desc;
2304 #endif
2305         GError *error = NULL;
2306
2307         if (!thread)
2308                 return;
2309
2310         text = g_string_new (0);
2311         if (thread->name) {
2312                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2313                 g_assert (!error);
2314                 g_string_append_printf (text, "\n\"%s\"", name);
2315                 g_free (name);
2316         }
2317         else if (thread->threadpool_thread)
2318                 g_string_append (text, "\n\"<threadpool thread>\"");
2319         else
2320                 g_string_append (text, "\n\"<unnamed thread>\"");
2321
2322 #ifndef HOST_WIN32
2323         wapi_desc = wapi_current_thread_desc ();
2324         g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
2325         free (wapi_desc);
2326 #endif
2327
2328 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2329         if (start_ctx) {
2330                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2331         } else if (!sigctx)
2332                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2333         else
2334                 mono_sigctx_to_monoctx (sigctx, &ctx);
2335
2336         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2337 #else
2338         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2339 #endif
2340
2341         mono_runtime_printf ("%s", text->str);
2342
2343 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2344         OutputDebugStringA(text->str);
2345 #endif
2346
2347         g_string_free (text, TRUE);
2348         mono_runtime_stdout_fflush ();
2349 }
2350
2351 /*
2352  * mono_print_thread_dump:
2353  *
2354  *   Print information about the current thread to stdout.
2355  * SIGCTX can be NULL, allowing this to be called from gdb.
2356  */
2357 void
2358 mono_print_thread_dump (void *sigctx)
2359 {
2360         mono_print_thread_dump_internal (sigctx, NULL);
2361 }
2362
2363 void
2364 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2365 {
2366         mono_print_thread_dump_internal (NULL, ctx);
2367 }
2368
2369 /*
2370  * mono_resume_unwind:
2371  *
2372  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2373  * unwinding.
2374  */
2375 void
2376 mono_resume_unwind (MonoContext *ctx)
2377 {
2378         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2379         MonoContext new_ctx;
2380
2381         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2382         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2383         new_ctx = *ctx;
2384
2385         mono_handle_exception_internal (&new_ctx, jit_tls->resume_state.ex_obj, TRUE, NULL);
2386
2387         mono_restore_context (&new_ctx);
2388 }
2389
2390 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2391
2392 typedef struct {
2393         MonoJitInfo *ji;
2394         MonoContext ctx;
2395         MonoJitExceptionInfo *ei;
2396 } FindHandlerBlockData;
2397
2398 static gboolean
2399 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2400 {
2401         int i;
2402         gpointer ip;
2403         FindHandlerBlockData *pdata = data;
2404         MonoJitInfo *ji = frame->ji;
2405
2406         if (!ji)
2407                 return FALSE;
2408
2409         ip = MONO_CONTEXT_GET_IP (ctx);
2410
2411         for (i = 0; i < ji->num_clauses; ++i) {
2412                 MonoJitExceptionInfo *ei = ji->clauses + i;
2413                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2414                         continue;
2415                 /*If ip points to the first instruction it means the handler block didn't start
2416                  so we can leave its execution to the EH machinery*/
2417                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2418                         pdata->ji = ji;
2419                         pdata->ei = ei;
2420                         pdata->ctx = *ctx;
2421                         break;
2422                 }
2423         }
2424         return FALSE;
2425 }
2426
2427
2428 static gpointer
2429 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2430 {
2431         int i;
2432         MonoJitExceptionInfo *clause = NULL;
2433         gpointer ip;
2434
2435         ip = MONO_CONTEXT_GET_IP (ctx);
2436
2437         for (i = 0; i < ji->num_clauses; ++i) {
2438                 clause = &ji->clauses [i];
2439                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2440                         continue;
2441                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2442                         break;
2443         }
2444
2445         /*no matching finally */
2446         if (i == ji->num_clauses)
2447                 return NULL;
2448
2449         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2450         if (ip == clause->handler_start)
2451                 return NULL;
2452
2453         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2454 }
2455
2456 /*
2457  * Finds the bottom handler block running and install a block guard if needed.
2458  * FIXME add full-aot support.
2459  */
2460 gboolean
2461 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2462 {
2463         FindHandlerBlockData data = { 0 };
2464         MonoJitTlsData *jit_tls = ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2465         gpointer resume_ip;
2466
2467         /* FIXME */
2468         if (mono_aot_only)
2469                 return FALSE;
2470
2471         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2472          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2473          */
2474         if (!jit_tls || jit_tls->handler_block_return_address)
2475                 return FALSE;
2476
2477         /* Do an async safe stack walk */
2478         mono_thread_info_set_is_async_context (TRUE);
2479         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data);
2480         mono_thread_info_set_is_async_context (FALSE);
2481
2482         if (!data.ji)
2483                 return FALSE;
2484
2485         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2486
2487         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2488         if (resume_ip == NULL)
2489                 return FALSE;
2490
2491         jit_tls->handler_block_return_address = resume_ip;
2492         jit_tls->handler_block = data.ei;
2493
2494         return TRUE;
2495 }
2496
2497 #else
2498 gboolean
2499 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2500 {
2501         return FALSE;
2502 }
2503
2504 #endif
2505
2506 void
2507 mono_set_cast_details (MonoClass *from, MonoClass *to)
2508 {
2509         MonoJitTlsData *jit_tls = NULL;
2510
2511         if (mini_get_debug_options ()->better_cast_details) {
2512                 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2513                 jit_tls->class_cast_from = from;
2514                 jit_tls->class_cast_to = to;
2515         }
2516 }
2517
2518
2519 /*returns false if the thread is not attached*/
2520 gboolean
2521 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
2522 {
2523 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2524         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2525         if (!thread) {
2526                 ctx->valid = FALSE;
2527                 G_BREAKPOINT ();
2528                 return FALSE;
2529         }
2530
2531         if (sigctx) {
2532                 mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
2533
2534                 ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2535                 ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2536                 ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2537         }
2538         else {
2539                 mono_thread_state_init (ctx);
2540         }
2541
2542         if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF])
2543                 return FALSE;
2544
2545         ctx->valid = TRUE;
2546         return TRUE;
2547 #else
2548         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
2549         return FALSE;
2550 #endif
2551 }
2552
2553 void
2554 mono_thread_state_init (MonoThreadUnwindState *ctx)
2555 {
2556         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2557
2558 #if defined(MONO_CROSS_COMPILE)
2559         ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
2560 #elif MONO_ARCH_HAS_MONO_CONTEXT
2561         MONO_CONTEXT_GET_CURRENT (ctx->ctx);
2562 #else
2563         g_error ("Use a null sigctx requires a working mono-context");
2564 #endif
2565
2566         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2567         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2568         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
2569         ctx->valid = TRUE;
2570 }
2571
2572
2573 gboolean
2574 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
2575 {
2576         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2577         if (!thread) {
2578                 ctx->valid = FALSE;
2579                 return FALSE;
2580         }
2581
2582         ctx->ctx = *mctx;
2583         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2584         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2585         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2586         ctx->valid = TRUE;
2587         return TRUE;
2588 }
2589
2590 /*returns false if the thread is not attached*/
2591 gboolean
2592 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
2593 {
2594         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2595         MONO_ARCH_CONTEXT_DEF
2596
2597         mono_arch_flush_register_windows ();
2598
2599         if (!thread || !thread->jit_data) {
2600                 ctx->valid = FALSE;
2601                 return FALSE;
2602         }
2603 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
2604         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
2605 #else
2606         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
2607 #endif
2608                 
2609         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2610         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2611         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2612         ctx->valid = TRUE;
2613         return TRUE;
2614 }
2615
2616 static void
2617 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
2618 {
2619         mono_handle_exception (ctx, exc);
2620         mono_restore_context (ctx);
2621 }
2622
2623 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
2624 void
2625 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
2626 {
2627 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
2628         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2629         jit_tls->ex_ctx = *ctx;
2630
2631         mono_arch_setup_async_callback (ctx, async_cb, user_data);
2632 #else
2633         g_error ("This target doesn't support mono_arch_setup_async_callback");
2634 #endif
2635 }
2636
2637 void
2638 mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
2639 {
2640         unhandled_exception_hook = func;
2641         unhandled_exception_hook_data = user_data;
2642 }
2643
2644 void
2645 mono_invoke_unhandled_exception_hook (MonoObject *exc)
2646 {
2647         if (unhandled_exception_hook) {
2648                 unhandled_exception_hook (exc, unhandled_exception_hook_data);
2649         } else {
2650                 MonoObject *other = NULL;
2651                 MonoString *str = mono_object_to_string (exc, &other);
2652                 char *msg = NULL;
2653                 
2654                 if (str)
2655                         msg = mono_string_to_utf8 (str);
2656                 else if (other) {
2657                         char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
2658                         char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);
2659
2660                         msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
2661                                 original_backtrace, nested_backtrace);
2662
2663                         g_free (original_backtrace);
2664                         g_free (nested_backtrace);
2665                 } else {
2666                         msg = g_strdup ("Nested exception trying to figure out what went wrong");
2667                 }
2668                 mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
2669                 g_free (msg);
2670 #if defined(HOST_IOS)
2671                 g_assertion_message ("Terminating runtime due to unhandled exception");
2672 #else
2673                 exit (mono_environment_exitcode_get ());
2674 #endif
2675         }
2676
2677         g_assert_not_reached ();
2678 }
2679
2680 /*
2681  * mono_restore_context:
2682  *
2683  *   Call the architecture specific restore context function.
2684  */
2685 void
2686 mono_restore_context (MonoContext *ctx)
2687 {
2688         static void (*restore_context) (MonoContext *);
2689
2690         if (!restore_context)
2691                 restore_context = mono_get_restore_context ();
2692         restore_context (ctx);
2693         g_assert_not_reached ();
2694 }
2695
2696 /*
2697  * mono_jinfo_get_unwind_info:
2698  *
2699  *   Return the unwind info for JI.
2700  */
2701 guint8*
2702 mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
2703 {
2704         if (ji->from_aot)
2705                 return mono_aot_get_unwind_info (ji, unwind_info_len);
2706         else
2707                 return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len);
2708 }
2709
2710 int
2711 mono_jinfo_get_epilog_size (MonoJitInfo *ji)
2712 {
2713         MonoArchEHJitInfo *info;
2714
2715         info = mono_jit_info_get_arch_eh_info (ji);
2716         g_assert (info);
2717
2718         return info->epilog_size;
2719 }