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