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