First set of licensing changes
[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                 return mono_array_new (domain, mono_defaults.stack_frame_class, 0);
713         }
714
715         len = mono_array_length (ta) >> 1;
716
717         res = mono_array_new (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0);
718
719         for (i = skip; i < len; i++) {
720                 MonoJitInfo *ji;
721                 MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, &error);
722                 if (!mono_error_ok (&error)) {
723                         mono_error_set_pending_exception (&error);
724                         return NULL;
725                 }
726                 gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
727                 gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
728                 MonoMethod *method;
729
730                 ji = mono_jit_info_table_find (domain, (char *)ip);
731                 if (ji == NULL) {
732                         /* Unmanaged frame */
733                         mono_array_setref (res, i, sf);
734                         continue;
735                 }
736
737                 g_assert (ji != NULL);
738
739                 if (mono_llvm_only)
740                         /* Can't resolve actual method */
741                         method = jinfo_get_method (ji);
742                 else
743                         method = get_method_from_stack_frame (ji, generic_info);
744                 if (jinfo_get_method (ji)->wrapper_type) {
745                         char *s;
746
747                         sf->method = NULL;
748                         s = mono_method_get_name_full (method, TRUE, FALSE, MONO_TYPE_NAME_FORMAT_REFLECTION);
749                         MONO_OBJECT_SETREF (sf, internal_method_name, mono_string_new (domain, s));
750                         g_free (s);
751                 }
752                 else {
753                         MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, &error);
754                         if (!mono_error_ok (&error)) {
755                                 mono_error_set_pending_exception (&error);
756                                 return NULL;
757                         }
758                         MONO_OBJECT_SETREF (sf, method, rm);
759                 }
760
761                 sf->method_index = ji->from_aot ? mono_aot_find_method_index (method) : 0xffffff;
762                 sf->method_address = (gsize) ji->code_start;
763                 sf->native_offset = (char *)ip - (char *)ji->code_start;
764
765                 /*
766                  * mono_debug_lookup_source_location() returns both the file / line number information
767                  * and the IL offset.  Note that computing the IL offset is already an expensive
768                  * operation, so we shouldn't call this method twice.
769                  */
770                 location = mono_debug_lookup_source_location (jinfo_get_method (ji), sf->native_offset, domain);
771                 if (location) {
772                         sf->il_offset = location->il_offset;
773                 } else {
774                         SeqPoint sp;
775                         if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (ji), sf->native_offset, NULL, &sp))
776                                 sf->il_offset = sp.il_offset;
777                         else
778                                 sf->il_offset = -1;
779                 }
780
781                 if (need_file_info) {
782                         if (location && location->source_file) {
783                                 MONO_OBJECT_SETREF (sf, filename, mono_string_new (domain, location->source_file));
784                                 sf->line = location->row;
785                                 sf->column = location->column;
786                         } else {
787                                 sf->line = sf->column = 0;
788                                 sf->filename = NULL;
789                         }
790                 }
791
792                 mono_debug_free_source_location (location);
793                 mono_array_setref (res, i, sf);
794         }
795
796         return res;
797 }
798
799 static void
800 mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
801 {
802         if (!start_ctx) {
803                 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
804                 if (jit_tls && jit_tls->orig_ex_ctx_set)
805                         start_ctx = &jit_tls->orig_ex_ctx;
806         }
807         mono_walk_stack_with_ctx (func, start_ctx, unwind_options, user_data);
808 }
809 /**
810  * mono_walk_stack_with_ctx:
811  *
812  * Unwind the current thread starting at @start_ctx.
813  * 
814  * If @start_ctx is null, we capture the current context.
815  */
816 void
817 mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
818 {
819         MonoContext extra_ctx;
820         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
821         MONO_ARCH_CONTEXT_DEF
822
823         if (!thread || !thread->jit_data)
824                 return;
825
826         if (!start_ctx) {
827                 mono_arch_flush_register_windows ();
828
829 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
830                 MONO_INIT_CONTEXT_FROM_CURRENT (&extra_ctx);
831 #else
832                 MONO_INIT_CONTEXT_FROM_FUNC (&extra_ctx, mono_walk_stack_with_ctx);
833 #endif
834                 start_ctx = &extra_ctx;
835         }
836
837         mono_walk_stack_full (func, start_ctx, mono_domain_get (), (MonoJitTlsData *)thread->jit_data, mono_get_lmf (), unwind_options, user_data);
838 }
839
840 /**
841  * mono_walk_stack_with_state:
842  *
843  * Unwind a thread described by @state.
844  *
845  * State must be valid (state->valid == TRUE).
846  *
847  * If you are using this function to unwind another thread, make sure it is suspended.
848  * 
849  * If @state is null, we capture the current context.
850  */
851 void
852 mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, MonoUnwindOptions unwind_options, void *user_data)
853 {
854         MonoThreadUnwindState extra_state;
855         if (!state) {
856                 g_assert (!mono_thread_info_is_async_context ());
857                 if (!mono_thread_state_init_from_current (&extra_state))
858                         return;
859                 state = &extra_state;
860         }
861
862         g_assert (state->valid);
863
864         if (!state->unwind_data [MONO_UNWIND_DATA_DOMAIN])
865                 /* Not attached */
866                 return;
867
868         mono_walk_stack_full (func,
869                 &state->ctx, 
870                 (MonoDomain *)state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
871                 (MonoJitTlsData *)state->unwind_data [MONO_UNWIND_DATA_JIT_TLS],
872                 (MonoLMF *)state->unwind_data [MONO_UNWIND_DATA_LMF],
873                 unwind_options, user_data);
874 }
875
876 void
877 mono_walk_stack (MonoJitStackWalk func, MonoUnwindOptions options, void *user_data)
878 {
879         MonoThreadUnwindState state;
880         if (!mono_thread_state_init_from_current (&state))
881                 return;
882         mono_walk_stack_with_state (func, &state, options, user_data);
883 }
884
885 /**
886  * mono_walk_stack_full:
887  * @func: callback to call for each stack frame
888  * @domain: starting appdomain, can be NULL to use the current domain
889  * @unwind_options: what extra information the unwinder should gather
890  * @start_ctx: starting state of the stack walk, can be NULL.
891  * @thread: the thread whose stack to walk, can be NULL to use the current thread
892  * @lmf: the LMF of @thread, can be NULL to use the LMF of the current thread
893  * @user_data: data passed to the callback
894  *
895  * This function walks the stack of a thread, starting from the state
896  * represented by start_ctx. For each frame the callback
897  * function is called with the relevant info. The walk ends when no more
898  * managed stack frames are found or when the callback returns a TRUE value.
899  */
900 static void
901 mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data)
902 {
903         gint il_offset, i;
904         MonoContext ctx, new_ctx;
905         StackFrameInfo frame;
906         gboolean res;
907         mgreg_t *reg_locations [MONO_MAX_IREGS];
908         mgreg_t *new_reg_locations [MONO_MAX_IREGS];
909         gboolean get_reg_locations = unwind_options & MONO_UNWIND_REG_LOCATIONS;
910         gboolean async = mono_thread_info_is_async_context ();
911
912         if (mono_llvm_only) {
913                 GSList *l, *ips;
914
915                 if (async)
916                         return;
917
918                 ips = get_unwind_backtrace ();
919                 for (l = ips; l; l = l->next) {
920                         guint8 *ip = (guint8*)l->data;
921                         memset (&frame, 0, sizeof (StackFrameInfo));
922                         frame.ji = mini_jit_info_table_find (domain, (char*)ip, &frame.domain);
923                         if (!frame.ji || frame.ji->is_trampoline)
924                                 continue;
925                         frame.type = FRAME_TYPE_MANAGED;
926                         frame.method = jinfo_get_method (frame.ji);
927                         // FIXME: Cannot lookup the actual method
928                         frame.actual_method = frame.method;
929                         if (frame.type == FRAME_TYPE_MANAGED) {
930                                 if (!frame.method->wrapper_type || frame.method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
931                                         frame.managed = TRUE;
932                         }
933                         frame.native_offset = ip - (guint8*)frame.ji->code_start;
934                         frame.il_offset = -1;
935
936                         if (func (&frame, NULL, user_data))
937                                 break;
938                 }
939                 g_free (ips);
940                 return;
941         }
942
943         g_assert (start_ctx);
944         g_assert (domain);
945         g_assert (jit_tls);
946         /*The LMF will be null if the target have no managed frames.*/
947         /* g_assert (lmf); */
948
949         if (async)
950                 g_assert (unwind_options == MONO_UNWIND_NONE);
951
952         memcpy (&ctx, start_ctx, sizeof (MonoContext));
953         memset (reg_locations, 0, sizeof (reg_locations));
954
955         while (MONO_CONTEXT_GET_SP (&ctx) < jit_tls->end_of_stack) {
956                 frame.lmf = lmf;
957                 res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, get_reg_locations ? new_reg_locations : NULL, &frame);
958                 if (!res)
959                         return;
960
961                 if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji && !frame.ji->is_trampoline) {
962                         MonoDebugSourceLocation *source;
963
964                         source = mono_debug_lookup_source_location (jinfo_get_method (frame.ji), frame.native_offset, domain);
965                         if (source) {
966                                 il_offset = source->il_offset;
967                         } else {
968                                 SeqPoint sp;
969                                 if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (frame.ji), frame.native_offset, NULL, &sp))
970                                         il_offset = sp.il_offset;
971                                 else
972                                         il_offset = -1;
973                         }
974                         mono_debug_free_source_location (source);
975                 } else
976                         il_offset = -1;
977
978                 frame.il_offset = il_offset;
979
980                 if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji && !frame.ji->is_trampoline) {
981                         frame.actual_method = get_method_from_stack_frame (frame.ji, get_generic_info_from_stack_frame (frame.ji, &ctx));
982                 } else {
983                         frame.actual_method = frame.method;
984                 }
985
986                 if (get_reg_locations)
987                         frame.reg_locations = reg_locations;
988
989                 if (func (&frame, &ctx, user_data))
990                         return;
991
992                 if (get_reg_locations) {
993                         for (i = 0; i < MONO_MAX_IREGS; ++i)
994                                 if (new_reg_locations [i])
995                                         reg_locations [i] = new_reg_locations [i];
996                 }
997                 
998                 ctx = new_ctx;
999         }
1000 }
1001
1002 MonoBoolean
1003 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
1004                           MonoReflectionMethod **method, 
1005                           gint32 *iloffset, gint32 *native_offset,
1006                           MonoString **file, gint32 *line, gint32 *column)
1007 {
1008         MonoError error;
1009         MonoDomain *domain = mono_domain_get ();
1010         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
1011         MonoLMF *lmf = mono_get_lmf ();
1012         MonoJitInfo *ji = NULL;
1013         MonoContext ctx, new_ctx;
1014         MonoDebugSourceLocation *location;
1015         MonoMethod *jmethod = NULL, *actual_method;
1016         StackFrameInfo frame;
1017         gboolean res;
1018
1019         MONO_ARCH_CONTEXT_DEF;
1020
1021         if (mono_llvm_only) {
1022                 GSList *l, *ips;
1023                 MonoDomain *frame_domain;
1024                 guint8 *frame_ip = NULL;
1025
1026                 /* FIXME: Generalize this code with an interface which returns an array of StackFrame structures */
1027                 jmethod = NULL;
1028                 ips = get_unwind_backtrace ();
1029                 for (l = ips; l && skip >= 0; l = l->next) {
1030                         guint8 *ip = (guint8*)l->data;
1031
1032                         frame_ip = ip;
1033
1034                         ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &frame_domain);
1035                         if (!ji || ji->is_trampoline)
1036                                 continue;
1037
1038                         /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */
1039                         jmethod = jinfo_get_method (ji);
1040                         if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE)
1041                                 continue;
1042                         skip--;
1043                 }
1044                 g_slist_free (ips);
1045                 if (!jmethod || !l)
1046                         return FALSE;
1047                 /* No way to resolve generic instances */
1048                 actual_method = jmethod;
1049                 *native_offset = frame_ip - (guint8*)ji->code_start;
1050         } else {
1051                 mono_arch_flush_register_windows ();
1052
1053 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
1054                 MONO_INIT_CONTEXT_FROM_CURRENT (&ctx);
1055 #else
1056                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, ves_icall_get_frame_info);
1057 #endif
1058
1059                 new_ctx = ctx;
1060                 do {
1061                         ctx = new_ctx;
1062                         res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1063                         if (!res)
1064                                 return FALSE;
1065
1066                         if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
1067                                 frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
1068                                 frame.type == FRAME_TYPE_TRAMPOLINE)
1069                                 continue;
1070
1071                         ji = frame.ji;
1072                         *native_offset = frame.native_offset;
1073
1074                         /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */
1075                         jmethod = jinfo_get_method (ji);
1076                         if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE)
1077                                 continue;
1078                         skip--;
1079                 } while (skip >= 0);
1080
1081                 actual_method = get_method_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, &ctx));
1082         }
1083
1084         MonoReflectionMethod *rm = mono_method_get_object_checked (domain, actual_method, NULL, &error);
1085         if (!mono_error_ok (&error)) {
1086                 mono_error_set_pending_exception (&error);
1087                 return FALSE;
1088         }
1089         mono_gc_wbarrier_generic_store (method, (MonoObject*) rm);
1090
1091         location = mono_debug_lookup_source_location (jmethod, *native_offset, domain);
1092         if (location)
1093                 *iloffset = location->il_offset;
1094         else
1095                 *iloffset = 0;
1096
1097         if (need_file_info) {
1098                 if (location) {
1099                         mono_gc_wbarrier_generic_store (file, (MonoObject*) mono_string_new (domain, location->source_file));
1100                         *line = location->row;
1101                         *column = location->column;
1102                 } else {
1103                         *file = NULL;
1104                         *line = *column = 0;
1105                 }
1106         }
1107
1108         mono_debug_free_source_location (location);
1109
1110         return TRUE;
1111 }
1112
1113 static MonoClass*
1114 get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
1115 {
1116         MonoError error;
1117         MonoClass *catch_class = ei->data.catch_class;
1118         MonoType *inflated_type;
1119         MonoGenericContext context;
1120
1121         /*MonoJitExceptionInfo::data is an union used by filter and finally clauses too.*/
1122         if (!catch_class || ei->flags != MONO_EXCEPTION_CLAUSE_NONE)
1123                 return NULL;
1124
1125         if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
1126                 return catch_class;
1127         context = get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx));
1128
1129         /* FIXME: we shouldn't inflate but instead put the
1130            type in the rgctx and fetch it from there.  It
1131            might be a good idea to do this lazily, i.e. only
1132            when the exception is actually thrown, so as not to
1133            waste space for exception clauses which might never
1134            be encountered. */
1135         inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
1136         mono_error_assert_ok (&error); /* FIXME don't swallow the error */
1137
1138         catch_class = mono_class_from_mono_type (inflated_type);
1139         mono_metadata_free_type (inflated_type);
1140
1141         return catch_class;
1142 }
1143
1144 /*
1145  * mini_jit_info_table_find_ext:
1146  *
1147  *   Same as mono_jit_info_table_find, but search all the domains of the current thread
1148  * if ADDR is not found in DOMAIN. The domain where the method was found is stored into
1149  * OUT_DOMAIN if it is not NULL.
1150  */
1151 MonoJitInfo*
1152 mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_trampolines, MonoDomain **out_domain)
1153 {
1154         MonoJitInfo *ji;
1155         MonoInternalThread *t = mono_thread_internal_current ();
1156         gpointer *refs;
1157
1158         if (out_domain)
1159                 *out_domain = NULL;
1160
1161         ji = mono_jit_info_table_find_internal (domain, addr, TRUE, allow_trampolines);
1162         if (ji) {
1163                 if (out_domain)
1164                         *out_domain = domain;
1165                 return ji;
1166         }
1167
1168         /* maybe it is shared code, so we also search in the root domain */
1169         if (domain != mono_get_root_domain ()) {
1170                 ji = mono_jit_info_table_find_internal (mono_get_root_domain (), addr, TRUE, allow_trampolines);
1171                 if (ji) {
1172                         if (out_domain)
1173                                 *out_domain = mono_get_root_domain ();
1174                         return ji;
1175                 }
1176         }
1177
1178         if (!t)
1179                 return NULL;
1180
1181         refs = (gpointer *)((t->appdomain_refs) ? *(gpointer *) t->appdomain_refs : NULL);
1182         for (; refs && *refs; refs++) {
1183                 if (*refs != domain && *refs != mono_get_root_domain ()) {
1184                         ji = mono_jit_info_table_find_internal ((MonoDomain*) *refs, addr, TRUE, allow_trampolines);
1185                         if (ji) {
1186                                 if (out_domain)
1187                                         *out_domain = (MonoDomain*) *refs;
1188                                 return ji;
1189                         }
1190                 }
1191         }
1192
1193         return NULL;
1194 }
1195
1196 MonoJitInfo*
1197 mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
1198 {
1199         return mini_jit_info_table_find_ext (domain, addr, FALSE, out_domain);
1200 }
1201
1202 /* Class lazy loading functions */
1203 static GENERATE_GET_CLASS_WITH_CACHE (runtime_compat_attr, System.Runtime.CompilerServices, RuntimeCompatibilityAttribute)
1204
1205 /*
1206  * wrap_non_exception_throws:
1207  *
1208  *   Determine whenever M's assembly has a RuntimeCompatibilityAttribute with the
1209  * WrapNonExceptionThrows flag set.
1210  */
1211 static gboolean
1212 wrap_non_exception_throws (MonoMethod *m)
1213 {
1214         MonoError error;
1215         MonoAssembly *ass = m->klass->image->assembly;
1216         MonoCustomAttrInfo* attrs;
1217         MonoClass *klass;
1218         int i;
1219         gboolean val = FALSE;
1220
1221         g_assert (ass);
1222         if (ass->wrap_non_exception_throws_inited)
1223                 return ass->wrap_non_exception_throws;
1224
1225         klass = mono_class_get_runtime_compat_attr_class ();
1226
1227         attrs = mono_custom_attrs_from_assembly_checked (ass, &error);
1228         mono_error_cleanup (&error); /* FIXME don't swallow the error */
1229         if (attrs) {
1230                 for (i = 0; i < attrs->num_attrs; ++i) {
1231                         MonoCustomAttrEntry *attr = &attrs->attrs [i];
1232                         const gchar *p;
1233                         int num_named, named_type, name_len;
1234                         char *name;
1235
1236                         if (!attr->ctor || attr->ctor->klass != klass)
1237                                 continue;
1238                         /* Decode the RuntimeCompatibilityAttribute. See reflection.c */
1239                         p = (const char*)attr->data;
1240                         g_assert (read16 (p) == 0x0001);
1241                         p += 2;
1242                         num_named = read16 (p);
1243                         if (num_named != 1)
1244                                 continue;
1245                         p += 2;
1246                         named_type = *p;
1247                         p ++;
1248                         /* data_type = *p; */
1249                         p ++;
1250                         /* Property */
1251                         if (named_type != 0x54)
1252                                 continue;
1253                         name_len = mono_metadata_decode_blob_size (p, &p);
1254                         name = (char *)g_malloc (name_len + 1);
1255                         memcpy (name, p, name_len);
1256                         name [name_len] = 0;
1257                         p += name_len;
1258                         g_assert (!strcmp (name, "WrapNonExceptionThrows"));
1259                         g_free (name);
1260                         /* The value is a BOOLEAN */
1261                         val = *p;
1262                 }
1263                 mono_custom_attrs_free (attrs);
1264         }
1265
1266         ass->wrap_non_exception_throws = val;
1267         mono_memory_barrier ();
1268         ass->wrap_non_exception_throws_inited = TRUE;
1269
1270         return val;
1271 }
1272
1273 #ifndef MONO_ARCH_STACK_GROWS_UP
1274 #define DOES_STACK_GROWS_UP 1
1275 #else
1276 #define DOES_STACK_GROWS_UP 0
1277 #endif
1278
1279 #define MAX_UNMANAGED_BACKTRACE 128
1280 static MonoArray*
1281 build_native_trace (void)
1282 {
1283 /* This puppy only makes sense on mobile, IOW, ARM. */
1284 #if defined (HAVE_BACKTRACE_SYMBOLS) && defined (TARGET_ARM)
1285         MonoArray *res;
1286         void *native_trace [MAX_UNMANAGED_BACKTRACE];
1287         int size = backtrace (native_trace, MAX_UNMANAGED_BACKTRACE);
1288         int i;
1289
1290         if (!size)
1291                 return NULL;
1292         res = mono_array_new (mono_domain_get (), mono_defaults.int_class, size);
1293
1294         for (i = 0; i < size; i++)
1295                 mono_array_set (res, gpointer, i, native_trace [i]);
1296         return res;
1297 #else
1298         return NULL;
1299 #endif
1300 }
1301
1302 static void
1303 setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, MonoArray *initial_trace_ips, GList **trace_ips)
1304 {
1305         if (mono_ex && !initial_trace_ips) {
1306                 *trace_ips = g_list_reverse (*trace_ips);
1307                 MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_glist_to_array (*trace_ips, mono_defaults.int_class));
1308                 MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ());
1309                 if (dynamic_methods) {
1310                         /* These methods could go away anytime, so save a reference to them in the exception object */
1311                         GSList *l;
1312                         MonoMList *list = NULL;
1313
1314                         for (l = dynamic_methods; l; l = l->next) {
1315                                 guint32 dis_link;
1316                                 MonoDomain *domain = mono_domain_get ();
1317
1318                                 if (domain->method_to_dyn_method) {
1319                                         mono_domain_lock (domain);
1320                                         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, l->data);
1321                                         mono_domain_unlock (domain);
1322                                         if (dis_link) {
1323                                                 MonoObject *o = mono_gchandle_get_target (dis_link);
1324                                                 if (o) {
1325                                                         list = mono_mlist_prepend (list, o);
1326                                                 }
1327                                         }
1328                                 }
1329                         }
1330
1331                         MONO_OBJECT_SETREF (mono_ex, dynamic_methods, list);
1332                 }
1333         }
1334         g_list_free (*trace_ips);
1335         *trace_ips = NULL;
1336 }
1337
1338 /*
1339  * mono_handle_exception_internal_first_pass:
1340  *
1341  *   The first pass of exception handling. Unwind the stack until a catch clause which can catch
1342  * OBJ is found. Run the index of the filter clause which caught the exception into
1343  * OUT_FILTER_IDX. Return TRUE if the exception is caught, FALSE otherwise.
1344  */
1345 static gboolean
1346 mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception)
1347 {
1348         MonoError error;
1349         MonoDomain *domain = mono_domain_get ();
1350         MonoJitInfo *ji = NULL;
1351         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1352         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
1353         MonoLMF *lmf = mono_get_lmf ();
1354         MonoArray *initial_trace_ips = NULL;
1355         GList *trace_ips = NULL;
1356         GSList *dynamic_methods = NULL;
1357         MonoException *mono_ex;
1358         gboolean stack_overflow = FALSE;
1359         MonoContext initial_ctx;
1360         MonoMethod *method;
1361         int frame_count = 0;
1362         gint32 filter_idx;
1363         int i;
1364         MonoObject *ex_obj;
1365
1366         g_assert (ctx != NULL);
1367
1368         if (obj == (MonoObject *)domain->stack_overflow_ex)
1369                 stack_overflow = TRUE;
1370
1371         mono_ex = (MonoException*)obj;
1372         initial_trace_ips = mono_ex->trace_ips;
1373
1374         if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1375                 mono_ex = (MonoException*)obj;
1376                 initial_trace_ips = mono_ex->trace_ips;
1377         } else {
1378                 mono_error_assert_ok (&error);
1379                 mono_ex = NULL;
1380         }
1381
1382         if (!call_filter)
1383                 call_filter = (int (*) (MonoContext *, void *))mono_get_call_filter ();
1384
1385         g_assert (jit_tls->end_of_stack);
1386         g_assert (jit_tls->abort_func);
1387
1388         if (out_filter_idx)
1389                 *out_filter_idx = -1;
1390         if (out_ji)
1391                 *out_ji = NULL;
1392         if (out_prev_ji)
1393                 *out_prev_ji = NULL;
1394         filter_idx = 0;
1395         initial_ctx = *ctx;
1396
1397         while (1) {
1398                 MonoContext new_ctx;
1399                 guint32 free_stack;
1400                 int clause_index_start = 0;
1401                 gboolean unwind_res = TRUE;
1402                 
1403                 StackFrameInfo frame;
1404
1405                 if (out_prev_ji)
1406                         *out_prev_ji = ji;
1407
1408                 unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1409                 if (unwind_res) {
1410                         if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
1411                                         frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
1412                                         frame.type == FRAME_TYPE_TRAMPOLINE) {
1413                                 *ctx = new_ctx;
1414                                 continue;
1415                         }
1416                         g_assert (frame.type == FRAME_TYPE_MANAGED);
1417                         ji = frame.ji;
1418                 }
1419
1420                 if (!unwind_res) {
1421                         setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
1422                         g_slist_free (dynamic_methods);
1423                         return FALSE;
1424                 }
1425
1426                 frame_count ++;
1427                 method = jinfo_get_method (ji);
1428                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1429
1430                 if (mini_get_debug_options ()->reverse_pinvoke_exceptions && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
1431                         g_error ("A native frame was found while unwinding the stack after an exception.\n"
1432                                          "The native frame called the managed method:\n%s\n",
1433                                          mono_method_full_name (method, TRUE));
1434                 }
1435
1436                 if (method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
1437                         /* 
1438                          * Avoid overwriting the stack trace if the exception is
1439                          * rethrown. Also avoid giant stack traces during a stack
1440                          * overflow.
1441                          */
1442                         if (!initial_trace_ips && (frame_count < 1000)) {
1443                                 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
1444                                 trace_ips = g_list_prepend (trace_ips,
1445                                                                                         get_generic_info_from_stack_frame (ji, ctx));
1446                         }
1447                 }
1448
1449                 if (method->dynamic)
1450                         dynamic_methods = g_slist_prepend (dynamic_methods, method);
1451
1452                 if (stack_overflow) {
1453                         if (DOES_STACK_GROWS_UP)
1454                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1455                         else
1456                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1457                 } else {
1458                         free_stack = 0xffffff;
1459                 }
1460                                 
1461                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1462                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1463                         gboolean filtered = FALSE;
1464
1465                         /* 
1466                          * During stack overflow, wait till the unwinding frees some stack
1467                          * space before running handlers/finalizers.
1468                          */
1469                         if (free_stack <= (64 * 1024))
1470                                 continue;
1471
1472                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1473                                 /* catch block */
1474                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1475
1476                                 /*
1477                                  * Have to unwrap RuntimeWrappedExceptions if the
1478                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1479                                  */
1480                                 if (non_exception && !wrap_non_exception_throws (method))
1481                                         ex_obj = non_exception;
1482                                 else
1483                                         ex_obj = obj;
1484
1485                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1486                                         gboolean is_user_frame = method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD;
1487 #ifndef DISABLE_PERFCOUNTERS
1488                                         mono_perfcounters->exceptions_filters++;
1489 #endif
1490                                         /*
1491                                         Here's the thing, if this is a filter clause done by a wrapper like runtime invoke, we don't want to
1492                                         trim the stackframe since if it returns FALSE we lose information.
1493
1494                                         FIXME Not 100% sure if it's a good idea even with user clauses.
1495                                         */
1496                                         if (is_user_frame)
1497                                                 setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
1498
1499 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1500                                         if (ji->from_llvm)
1501                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1502                                         else
1503                                                 /* Can't pass the ex object in a register yet to filter clauses, because call_filter () might not support it */
1504                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1505 #else
1506                                         g_assert (!ji->from_llvm);
1507                                         /* store the exception object in bp + ei->exvar_offset */
1508                                         *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1509 #endif
1510
1511 #ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
1512                                         /*
1513                                          * Pass the original il clause index to the landing pad so it can
1514                                          * branch to the landing pad associated with the il clause.
1515                                          * This is needed because llvm compiled code assumes that the EH
1516                                          * code always branches to the innermost landing pad.
1517                                          */
1518                                         if (ji->from_llvm)
1519                                                 MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
1520 #endif
1521
1522                                         mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
1523                                         filtered = call_filter (ctx, ei->data.filter);
1524                                         mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
1525                                         if (filtered && out_filter_idx)
1526                                                 *out_filter_idx = filter_idx;
1527                                         if (out_ji)
1528                                                 *out_ji = ji;
1529                                         filter_idx ++;
1530
1531                                         if (filtered) {
1532                                                 if (!is_user_frame)
1533                                                         setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
1534                                                 g_slist_free (dynamic_methods);
1535                                                 /* mono_debugger_agent_handle_exception () needs this */
1536                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1537                                                 return TRUE;
1538                                         }
1539                                 }
1540
1541                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (ex_obj, catch_class, &error)) {
1542                                         setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
1543                                         g_slist_free (dynamic_methods);
1544
1545                                         if (out_ji)
1546                                                 *out_ji = ji;
1547
1548                                         /* mono_debugger_agent_handle_exception () needs this */
1549                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1550                                         return TRUE;
1551                                 }
1552                                 mono_error_cleanup (&error);
1553                         }
1554                 }
1555
1556                 *ctx = new_ctx;
1557         }
1558
1559         g_assert_not_reached ();
1560 }
1561
1562 /**
1563  * mono_handle_exception_internal:
1564  * @ctx: saved processor state
1565  * @obj: the exception object
1566  * @resume: whenever to resume unwinding based on the state in MonoJitTlsData.
1567  */
1568 static gboolean
1569 mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resume, MonoJitInfo **out_ji)
1570 {
1571         MonoError error;
1572         MonoDomain *domain = mono_domain_get ();
1573         MonoJitInfo *ji, *prev_ji;
1574         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1575         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
1576         MonoLMF *lmf = mono_get_lmf ();
1577         MonoException *mono_ex;
1578         gboolean stack_overflow = FALSE;
1579         MonoContext initial_ctx;
1580         MonoMethod *method;
1581         int frame_count = 0;
1582         gint32 filter_idx, first_filter_idx = 0;
1583         int i;
1584         MonoObject *ex_obj;
1585         MonoObject *non_exception = NULL;
1586
1587         g_assert (ctx != NULL);
1588         if (!obj) {
1589                 MonoException *ex = mono_get_exception_null_reference ();
1590                 MONO_OBJECT_SETREF (ex, message, mono_string_new (domain, "Object reference not set to an instance of an object"));
1591                 obj = (MonoObject *)ex;
1592         } 
1593
1594         /*
1595          * Allocate a new exception object instead of the preconstructed ones.
1596          */
1597         if (obj == (MonoObject *)domain->stack_overflow_ex) {
1598                 /*
1599                  * It is not a good idea to try and put even more pressure on the little stack available.
1600                  * obj = mono_get_exception_stack_overflow ();
1601                  */
1602                 stack_overflow = TRUE;
1603         }
1604         else if (obj == (MonoObject *)domain->null_reference_ex) {
1605                 obj = (MonoObject *)mono_get_exception_null_reference ();
1606         }
1607
1608         if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1609                 mono_error_assert_ok (&error);
1610                 non_exception = obj;
1611                 obj = (MonoObject *)mono_get_exception_runtime_wrapped_checked (obj, &error);
1612                 mono_error_assert_ok (&error);
1613         }
1614
1615         mono_ex = (MonoException*)obj;
1616
1617         if (mini_get_debug_options ()->suspend_on_exception) {
1618                 mono_runtime_printf_err ("Exception thrown, suspending...");
1619                 while (1)
1620                         ;
1621         }
1622
1623         if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1624                 mono_ex = (MonoException*)obj;
1625         } else {
1626                 mono_error_assert_ok (&error);
1627                 mono_ex = NULL;
1628         }
1629
1630         if (mono_ex && jit_tls->class_cast_from) {
1631                 if (!strcmp (mono_ex->object.vtable->klass->name, "InvalidCastException")) {
1632                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1633                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1634                         char *msg = g_strdup_printf ("Unable to cast object of type '%s' to type '%s'.", from_name, to_name);
1635                         mono_ex->message = mono_string_new (domain, msg);
1636                         g_free (from_name);
1637                         g_free (to_name);
1638                         g_free (msg);
1639                 }
1640                 if (!strcmp (mono_ex->object.vtable->klass->name, "ArrayTypeMismatchException")) {
1641                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1642                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1643                         char *msg = g_strdup_printf ("Source array of type '%s' cannot be cast to destination array type '%s'.", from_name, to_name);
1644                         mono_ex->message = mono_string_new (domain, msg);
1645                         g_free (from_name);
1646                         g_free (to_name);
1647                         g_free (msg);
1648                 }
1649         }
1650
1651         if (!call_filter)
1652                 call_filter = (int (*)(MonoContext *, void*))mono_get_call_filter ();
1653
1654         g_assert (jit_tls->end_of_stack);
1655         g_assert (jit_tls->abort_func);
1656
1657         /*
1658          * We set orig_ex_ctx_set to TRUE/FALSE around profiler calls to make sure it doesn't
1659          * end up being TRUE on any code path.
1660          */
1661         memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
1662
1663         if (!resume) {
1664                 gboolean res;
1665
1666                 MonoContext ctx_cp = *ctx;
1667                 if (mono_trace_is_enabled ()) {
1668                         MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
1669                         MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
1670                         MonoObject *message;
1671                         const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
1672                         char *msg = NULL;
1673                         if (get_message == NULL) {
1674                                 message = NULL;
1675                         } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
1676                                 message = NULL;
1677                                 msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
1678                         } else {
1679                                 MonoObject *exc = NULL;
1680                                 message = mono_runtime_try_invoke (get_message, obj, NULL, &exc, &error);
1681                                 g_assert (exc == NULL);
1682                                 mono_error_assert_ok (&error);
1683                         }
1684                         if (msg == NULL) {
1685                                 msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
1686                         }
1687                         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);
1688                         g_free (msg);
1689                         if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
1690                                 mono_print_thread_dump_from_ctx (ctx);
1691                 }
1692                 jit_tls->orig_ex_ctx_set = TRUE;
1693                 mono_profiler_exception_thrown (obj);
1694                 jit_tls->orig_ex_ctx_set = FALSE;
1695
1696                 res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
1697
1698                 if (!res) {
1699                         if (mini_get_debug_options ()->break_on_exc)
1700                                 G_BREAKPOINT ();
1701                         mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL);
1702
1703                         if (mini_get_debug_options ()->suspend_on_unhandled) {
1704                                 mono_runtime_printf_err ("Unhandled exception, suspending...");
1705                                 while (1)
1706                                         ;
1707                         }
1708
1709                         // FIXME: This runs managed code so it might cause another stack overflow when
1710                         // we are handling a stack overflow
1711                         mono_unhandled_exception (obj);
1712                 } else {
1713                         gboolean unhandled = FALSE;
1714
1715                         /*
1716                          * The exceptions caught by the mono_runtime_invoke_checked () calls
1717                          * in the threadpool needs to be treated as unhandled (#669836).
1718                          *
1719                          * FIXME: The check below is hackish, but its hard to distinguish
1720                          * these runtime invoke calls from others in the runtime.
1721                          */
1722                         if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
1723                                 if (prev_ji && jinfo_get_method (prev_ji) == mono_defaults.threadpool_perform_wait_callback_method)
1724                                         unhandled = TRUE;
1725                         }
1726
1727                         if (unhandled)
1728                                 mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL);
1729                         else
1730                                 mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, &ctx_cp);
1731                 }
1732         }
1733
1734         if (out_ji)
1735                 *out_ji = NULL;
1736         filter_idx = 0;
1737         initial_ctx = *ctx;
1738
1739         while (1) {
1740                 MonoContext new_ctx;
1741                 guint32 free_stack;
1742                 int clause_index_start = 0;
1743                 gboolean unwind_res = TRUE;
1744                 
1745                 if (resume) {
1746                         resume = FALSE;
1747                         ji = jit_tls->resume_state.ji;
1748                         new_ctx = jit_tls->resume_state.new_ctx;
1749                         clause_index_start = jit_tls->resume_state.clause_index;
1750                         lmf = jit_tls->resume_state.lmf;
1751                         first_filter_idx = jit_tls->resume_state.first_filter_idx;
1752                         filter_idx = jit_tls->resume_state.filter_idx;
1753                 } else {
1754                         StackFrameInfo frame;
1755
1756                         unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1757                         if (unwind_res) {
1758                                 if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
1759                                                 frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
1760                                                 frame.type == FRAME_TYPE_TRAMPOLINE) {
1761                                         *ctx = new_ctx;
1762                                         continue;
1763                                 }
1764                                 g_assert (frame.type == FRAME_TYPE_MANAGED);
1765                                 ji = frame.ji;
1766                         }
1767                 }
1768
1769                 if (!unwind_res) {
1770                         *(mono_get_lmf_addr ()) = lmf;
1771
1772                         jit_tls->abort_func (obj);
1773                         g_assert_not_reached ();
1774                 }
1775
1776                 method = jinfo_get_method (ji);
1777                 frame_count ++;
1778                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1779
1780                 if (stack_overflow) {
1781                         if (DOES_STACK_GROWS_UP)
1782                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1783                         else
1784                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1785                 } else {
1786                         free_stack = 0xffffff;
1787                 }
1788                                 
1789                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1790                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1791                         gboolean filtered = FALSE;
1792
1793                         /* 
1794                          * During stack overflow, wait till the unwinding frees some stack
1795                          * space before running handlers/finalizers.
1796                          */
1797                         if (free_stack <= (64 * 1024))
1798                                 continue;
1799
1800                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1801                                 /* catch block */
1802                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1803
1804                                 /*
1805                                  * Have to unwrap RuntimeWrappedExceptions if the
1806                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1807                                  */
1808                                 if (non_exception && !wrap_non_exception_throws (method))
1809                                         ex_obj = non_exception;
1810                                 else
1811                                         ex_obj = obj;
1812
1813                                 if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
1814 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1815                                         MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1816 #else
1817                                         g_assert (!ji->from_llvm);
1818                                         /* store the exception object in bp + ei->exvar_offset */
1819                                         *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1820 #endif
1821                                 }
1822
1823 #ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
1824                                 if (ji->from_llvm)
1825                                         MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
1826 #endif
1827
1828                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1829                                         /* 
1830                                          * Filter clauses should only be run in the 
1831                                          * first pass of exception handling.
1832                                          */
1833                                         filtered = (filter_idx == first_filter_idx);
1834                                         filter_idx ++;
1835                                 }
1836
1837                                 mono_error_init (&error);
1838                                 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
1839                                      mono_object_isinst_checked (ex_obj, catch_class, &error)) || filtered) {
1840                                         /*
1841                                          * This guards against the situation that we abort a thread that is executing a finally clause
1842                                          * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
1843                                          * check for this situation here and resume interruption if we are below the guarded block.
1844                                          */
1845                                         if (G_UNLIKELY (jit_tls->handler_block_return_address)) {
1846                                                 gboolean is_outside = FALSE;
1847                                                 gpointer prot_bp = MONO_CONTEXT_GET_BP (&jit_tls->handler_block_context);
1848                                                 gpointer catch_bp = MONO_CONTEXT_GET_BP (ctx);
1849                                                 //FIXME make this stack direction aware
1850                                                 if (catch_bp > prot_bp) {
1851                                                         is_outside = TRUE;
1852                                                 } else if (catch_bp == prot_bp) {
1853                                                         /* Can be either try { try { } catch {} } finally {} or try { try { } finally {} } catch {}
1854                                                          * So we check if the catch handler_start is protected by the guarded handler protected region
1855                                                          *
1856                                                          * Assumptions:
1857                                                          *      If there is an outstanding guarded_block return address, it means the current thread must be aborted.
1858                                                          *      This is the only way to reach out the guarded block as other cases are handled by the trampoline.
1859                                                          *      There aren't any further finally/fault handler blocks down the stack over this exception.
1860                                                          *   This must be ensured by the code that installs the guard trampoline.
1861                                                          */
1862                                                         g_assert (ji == mini_jit_info_table_find (domain, (char *)MONO_CONTEXT_GET_IP (&jit_tls->handler_block_context), NULL));
1863
1864                                                         if (!is_address_protected (ji, jit_tls->handler_block, ei->handler_start)) {
1865                                                                 is_outside = TRUE;
1866                                                         }
1867                                                 }
1868                                                 if (is_outside) {
1869                                                         jit_tls->handler_block_return_address = NULL;
1870                                                         jit_tls->handler_block = NULL;
1871                                                         mono_thread_resume_interruption (); /*We ignore the exception here, it will be raised later*/
1872                                                 }
1873                                         }
1874
1875                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1876                                                 g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1877                                         jit_tls->orig_ex_ctx_set = TRUE;
1878                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1879                                         jit_tls->orig_ex_ctx_set = FALSE;
1880                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1881                                         mono_set_lmf (lmf);
1882 #ifndef DISABLE_PERFCOUNTERS
1883                                         mono_perfcounters->exceptions_depth += frame_count;
1884 #endif
1885                                         if (obj == (MonoObject *)domain->stack_overflow_ex)
1886                                                 jit_tls->handling_stack_ovf = FALSE;
1887
1888                                         return 0;
1889                                 }
1890                                 mono_error_cleanup (&error);
1891                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
1892                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1893                                                 g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1894                                         jit_tls->orig_ex_ctx_set = TRUE;
1895                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1896                                         jit_tls->orig_ex_ctx_set = FALSE;
1897                                         call_filter (ctx, ei->handler_start);
1898                                 }
1899                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
1900                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1901                                                 g_print ("EXCEPTION: finally 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 #ifndef DISABLE_PERFCOUNTERS
1906                                         mono_perfcounters->exceptions_finallys++;
1907 #endif
1908                                         mono_set_lmf (lmf);
1909                                         if (ji->from_llvm) {
1910                                                 /* 
1911                                                  * LLVM compiled finally handlers follow the design
1912                                                  * of the c++ ehabi, i.e. they call a resume function
1913                                                  * at the end instead of returning to the caller.
1914                                                  * So save the exception handling state,
1915                                                  * mono_resume_unwind () will call us again to continue
1916                                                  * the unwinding.
1917                                                  */
1918                                                 jit_tls->resume_state.ex_obj = obj;
1919                                                 jit_tls->resume_state.ji = ji;
1920                                                 jit_tls->resume_state.clause_index = i + 1;
1921                                                 jit_tls->resume_state.ctx = *ctx;
1922                                                 jit_tls->resume_state.new_ctx = new_ctx;
1923                                                 jit_tls->resume_state.lmf = lmf;
1924                                                 jit_tls->resume_state.first_filter_idx = first_filter_idx;
1925                                                 jit_tls->resume_state.filter_idx = filter_idx;
1926                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1927                                                 return 0;
1928                                         } else {
1929                                                 call_filter (ctx, ei->handler_start);
1930                                         }
1931                                 }
1932                         }
1933                 }
1934
1935                 jit_tls->orig_ex_ctx_set = TRUE;
1936                 mono_profiler_exception_method_leave (method);
1937                 jit_tls->orig_ex_ctx_set = FALSE;
1938
1939                 *ctx = new_ctx;
1940         }
1941
1942         g_assert_not_reached ();
1943 }
1944
1945 /**
1946  * mono_debugger_run_finally:
1947  * @start_ctx: saved processor state
1948  *
1949  * This method is called by the Mono Debugger to call all `finally' clauses of the
1950  * current stack frame.  It's used when the user issues a `return' command to make
1951  * the current stack frame return.  After returning from this method, the debugger
1952  * unwinds the stack one frame and gives control back to the user.
1953  *
1954  * NOTE: This method is only used when running inside the Mono Debugger.
1955  */
1956 void
1957 mono_debugger_run_finally (MonoContext *start_ctx)
1958 {
1959         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1960         MonoDomain *domain = mono_domain_get ();
1961         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
1962         MonoLMF *lmf = mono_get_lmf ();
1963         MonoContext ctx, new_ctx;
1964         MonoJitInfo *ji, rji;
1965         int i;
1966
1967         ctx = *start_ctx;
1968
1969         ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
1970         if (!ji || ji == (gpointer)-1)
1971                 return;
1972
1973         if (!call_filter)
1974                 call_filter = (int (*)(MonoContext *, void *))mono_get_call_filter ();
1975
1976         for (i = 0; i < ji->num_clauses; i++) {
1977                 MonoJitExceptionInfo *ei = &ji->clauses [i];
1978
1979                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
1980                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
1981                         call_filter (&ctx, ei->handler_start);
1982                 }
1983         }
1984 }
1985
1986 /**
1987  * mono_handle_exception:
1988  * @ctx: saved processor state
1989  * @obj: the exception object
1990  */
1991 gboolean
1992 mono_handle_exception (MonoContext *ctx, MonoObject *obj)
1993 {
1994 #ifndef DISABLE_PERFCOUNTERS
1995         mono_perfcounters->exceptions_thrown++;
1996 #endif
1997
1998         return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
1999 }
2000
2001 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2002
2003 #ifndef MONO_ARCH_USE_SIGACTION
2004 #error "Can't use sigaltstack without sigaction"
2005 #endif
2006
2007 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
2008
2009 void
2010 mono_setup_altstack (MonoJitTlsData *tls)
2011 {
2012         size_t stsize = 0;
2013         stack_t sa;
2014         guint8 *staddr = NULL;
2015
2016         if (mono_running_on_valgrind ())
2017                 return;
2018
2019         mono_thread_info_get_stack_bounds (&staddr, &stsize);
2020
2021         g_assert (staddr);
2022
2023         tls->end_of_stack = staddr + stsize;
2024         tls->stack_size = stsize;
2025
2026         /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
2027
2028         tls->stack_ovf_guard_base = staddr + mono_pagesize ();
2029         tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
2030
2031         g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
2032
2033         if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
2034                 /* mprotect can fail for the main thread stack */
2035                 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);
2036                 g_assert (gaddr == tls->stack_ovf_guard_base);
2037                 tls->stack_ovf_valloced = TRUE;
2038         }
2039
2040         /* Setup an alternate signal stack */
2041         tls->signal_stack = mono_valloc (0, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON);
2042         tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2043
2044         g_assert (tls->signal_stack);
2045
2046         sa.ss_sp = tls->signal_stack;
2047         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2048         sa.ss_flags = 0;
2049         g_assert (sigaltstack (&sa, NULL) == 0);
2050
2051         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);
2052 }
2053
2054 void
2055 mono_free_altstack (MonoJitTlsData *tls)
2056 {
2057         stack_t sa;
2058         int err;
2059
2060         sa.ss_sp = tls->signal_stack;
2061         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2062         sa.ss_flags = SS_DISABLE;
2063         err = sigaltstack  (&sa, NULL);
2064         g_assert (err == 0);
2065
2066         if (tls->signal_stack)
2067                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE);
2068         if (tls->stack_ovf_valloced)
2069                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size);
2070         else
2071                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
2072 }
2073
2074 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2075
2076 void
2077 mono_setup_altstack (MonoJitTlsData *tls)
2078 {
2079 }
2080
2081 void
2082 mono_free_altstack (MonoJitTlsData *tls)
2083 {
2084 }
2085
2086 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2087
2088 static gboolean
2089 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
2090 {
2091         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
2092         /* we need to leave some room for throwing the exception */
2093         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
2094                 unprotect_size -= mono_pagesize ();
2095         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
2096          * is sufficient stack
2097          */
2098         //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);
2099         if (unprotect_size)
2100                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
2101         return unprotect_size == jit_tls->stack_ovf_guard_size;
2102 }
2103
2104 static G_GNUC_UNUSED void
2105 try_more_restore (void)
2106 {
2107         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
2108         if (try_restore_stack_protection (jit_tls, 500))
2109                 jit_tls->restore_stack_prot = NULL;
2110 }
2111
2112 static G_GNUC_UNUSED void
2113 restore_stack_protection (void)
2114 {
2115         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
2116         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
2117         /* if we can't restore the stack protection, keep a callback installed so
2118          * we'll try to restore as much stack as we can at each return from unmanaged
2119          * code.
2120          */
2121         if (try_restore_stack_protection (jit_tls, 4096))
2122                 jit_tls->restore_stack_prot = NULL;
2123         else
2124                 jit_tls->restore_stack_prot = try_more_restore_tramp;
2125         /* here we also throw a stack overflow exception */
2126         ex->trace_ips = NULL;
2127         ex->stack_trace = NULL;
2128         mono_raise_exception (ex);
2129 }
2130
2131 gpointer
2132 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
2133 {
2134         void (*func)(void) = (void (*)(void))tramp_data;
2135         func ();
2136         return NULL;
2137 }
2138
2139 gboolean
2140 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr)
2141 {
2142         if (mono_llvm_only)
2143                 return FALSE;
2144
2145         /* we got a stack overflow in the soft-guard pages
2146          * There are two cases:
2147          * 1) managed code caused the overflow: we unprotect the soft-guard page
2148          * and let the arch-specific code trigger the exception handling mechanism
2149          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
2150          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
2151          * and hope we can continue with those enabled, at least until the hard-guard page
2152          * is hit. The alternative to continuing here is to just print a message and abort.
2153          * We may add in the future the code to protect the pages again in the codepath
2154          * when we return from unmanaged to managed code.
2155          */
2156         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2157                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2158                 /* we unprotect the minimum amount we can */
2159                 guint32 guard_size;
2160                 gboolean handled = FALSE;
2161
2162                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2163                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2164                         guard_size -= mono_pagesize ();
2165                 }
2166                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2167                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2168                 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);
2169 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2170                 if (ji) {
2171                         mono_arch_handle_altstack_exception (ctx, siginfo, fault_addr, TRUE);
2172                         handled = TRUE;
2173                 }
2174 #endif
2175                 if (!handled) {
2176                         /* We print a message: after this even managed stack overflows
2177                          * may crash the runtime
2178                          */
2179                         mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2180                         if (!jit_tls->handling_stack_ovf) {
2181                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2182                                 jit_tls->handling_stack_ovf = 1;
2183                         } else {
2184                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2185                         }
2186                 }
2187                 return TRUE;
2188         }
2189         return FALSE;
2190 }
2191
2192 typedef struct {
2193         MonoMethod *omethod;
2194         int count;
2195 } PrintOverflowUserData;
2196
2197 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2198 static gboolean
2199 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2200 {
2201         MonoMethod *method = NULL;
2202         PrintOverflowUserData *user_data = (PrintOverflowUserData *)data;
2203         gchar *location;
2204
2205         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2206                 method = jinfo_get_method (frame->ji);
2207
2208         if (method) {
2209                 if (user_data->count == 0) {
2210                         /* The first frame is in its prolog, so a line number cannot be computed */
2211                         user_data->count ++;
2212                         return FALSE;
2213                 }
2214
2215                 /* If this is a one method overflow, skip the other instances */
2216                 if (method == user_data->omethod)
2217                         return FALSE;
2218
2219                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2220                 mono_runtime_printf_err ("  %s", location);
2221                 g_free (location);
2222
2223                 if (user_data->count == 1) {
2224                         mono_runtime_printf_err ("  <...>");
2225                         user_data->omethod = method;
2226                 } else {
2227                         user_data->omethod = NULL;
2228                 }
2229
2230                 user_data->count ++;
2231         } else
2232                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2233
2234         return FALSE;
2235 }
2236 #endif
2237
2238 void
2239 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2240 {
2241 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2242         PrintOverflowUserData ud;
2243         MonoContext mctx;
2244 #endif
2245
2246         /* we don't do much now, but we can warn the user with a useful message */
2247         mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2248
2249 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2250         mono_sigctx_to_monoctx (ctx, &mctx);
2251                         
2252         mono_runtime_printf_err ("Stacktrace:");
2253
2254         memset (&ud, 0, sizeof (ud));
2255
2256         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2257 #else
2258         if (ji && !ji->is_trampoline && jinfo_get_method (ji))
2259                 mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
2260         else
2261                 mono_runtime_printf_err ("At <unmanaged>.");
2262 #endif
2263
2264         _exit (1);
2265 }
2266
2267 static gboolean
2268 print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2269 {
2270         MonoMethod *method = NULL;
2271
2272         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2273                 method = jinfo_get_method (frame->ji);
2274
2275         if (method) {
2276                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2277                 mono_runtime_printf_err ("  %s", location);
2278                 g_free (location);
2279         } else
2280                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2281
2282         return FALSE;
2283 }
2284
2285 static G_GNUC_UNUSED gboolean
2286 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2287 {
2288         GString *p = (GString*)data;
2289         MonoMethod *method = NULL;
2290
2291         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2292                 method = jinfo_get_method (frame->ji);
2293
2294         if (method && frame->domain) {
2295                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
2296                 g_string_append_printf (p, "  %s\n", location);
2297                 g_free (location);
2298         } else
2299                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2300
2301         return FALSE;
2302 }
2303
2304 #ifndef MONO_CROSS_COMPILE
2305
2306 static gboolean handling_sigsegv = FALSE;
2307
2308 /*
2309  * mono_handle_native_sigsegv:
2310  *
2311  *   Handle a SIGSEGV received while in native code by printing diagnostic 
2312  * information and aborting.
2313  */
2314 void
2315 mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2316 {
2317 #ifdef MONO_ARCH_USE_SIGACTION
2318         struct sigaction sa;
2319 #endif
2320         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
2321         const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
2322
2323         if (handling_sigsegv)
2324                 return;
2325
2326         if (mini_get_debug_options ()->suspend_on_sigsegv) {
2327                 mono_runtime_printf_err ("Received SIGSEGV, suspending...");
2328 #ifdef HOST_WIN32
2329                 while (1)
2330                         ;
2331 #else
2332                 while (1) {
2333                         sleep (1);
2334                 }
2335 #endif
2336         }
2337
2338         /* To prevent infinite loops when the stack walk causes a crash */
2339         handling_sigsegv = TRUE;
2340
2341         /* !jit_tls means the thread was not registered with the runtime */
2342         if (jit_tls && mono_thread_internal_current ()) {
2343                 mono_runtime_printf_err ("Stacktrace:\n");
2344
2345                 /* FIXME: Is MONO_UNWIND_LOOKUP_IL_OFFSET correct here? */
2346                 mono_walk_stack (print_stack_frame_to_stderr, MONO_UNWIND_LOOKUP_IL_OFFSET, NULL);
2347         }
2348
2349 #ifdef HAVE_BACKTRACE_SYMBOLS
2350  {
2351         void *array [256];
2352         char **names;
2353         int i, size;
2354
2355         mono_runtime_printf_err ("\nNative stacktrace:\n");
2356
2357         size = backtrace (array, 256);
2358         names = backtrace_symbols (array, size);
2359         for (i =0; i < size; ++i) {
2360                 mono_runtime_printf_err ("\t%s", names [i]);
2361         }
2362         free (names);
2363
2364         /* Try to get more meaningful information using gdb */
2365
2366 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2367         if (!mini_get_debug_options ()->no_gdb_backtrace) {
2368                 /* From g_spawn_command_line_sync () in eglib */
2369                 pid_t pid;
2370                 int status;
2371                 pid_t crashed_pid = getpid ();
2372
2373                 //pid = fork ();
2374                 /*
2375                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2376                  * it will deadlock. Call the syscall directly instead.
2377                  */
2378                 pid = mono_runtime_syscall_fork ();
2379 #if defined (HAVE_PRCTL) && defined(PR_SET_PTRACER)
2380                 if (pid > 0) {
2381                         // Allow gdb to attach to the process even if ptrace_scope sysctl variable is set to
2382                         // a value other than 0 (the most permissive ptrace scope). Most modern Linux
2383                         // distributions set the scope to 1 which allows attaching only to direct children of
2384                         // the current process
2385                         prctl (PR_SET_PTRACER, pid, 0, 0, 0);
2386                 }
2387 #endif
2388                 if (pid == 0) {
2389                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2390
2391                         mono_gdb_render_native_backtraces (crashed_pid);
2392                         exit (1);
2393                 }
2394
2395                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2396                 waitpid (pid, &status, 0);
2397         }
2398 #endif
2399  }
2400 #else
2401         mono_exception_native_unwind (ctx, info);
2402 #endif
2403
2404         /*
2405          * A SIGSEGV indicates something went very wrong so we can no longer depend
2406          * on anything working. So try to print out lots of diagnostics, starting 
2407          * with ones which have a greater chance of working.
2408          */
2409         mono_runtime_printf_err (
2410                          "\n"
2411                          "=================================================================\n"
2412                          "Got a %s while executing native code. This usually indicates\n"
2413                          "a fatal error in the mono runtime or one of the native libraries \n"
2414                          "used by your application.\n"
2415                          "=================================================================\n",
2416                         signal_str);
2417
2418
2419 #ifdef MONO_ARCH_USE_SIGACTION
2420
2421         /* Remove our SIGABRT handler */
2422         sa.sa_handler = SIG_DFL;
2423         sigemptyset (&sa.sa_mask);
2424         sa.sa_flags = 0;
2425
2426         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2427
2428 #endif
2429
2430         if (!mono_do_crash_chaining) {
2431                 /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2432 #if defined (PLATFORM_ANDROID)
2433                 exit (-1);
2434 #else
2435                 abort ();
2436 #endif
2437         }
2438 }
2439
2440 #else
2441
2442 void
2443 mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2444 {
2445         g_assert_not_reached ();
2446 }
2447
2448 #endif /* !MONO_CROSS_COMPILE */
2449
2450 static void
2451 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2452 {
2453         MonoInternalThread *thread = mono_thread_internal_current ();
2454 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2455         MonoContext ctx;
2456 #endif
2457         GString* text;
2458         char *name;
2459 #ifndef HOST_WIN32
2460         char *wapi_desc;
2461 #endif
2462         GError *error = NULL;
2463
2464         if (!thread)
2465                 return;
2466
2467         text = g_string_new (0);
2468         if (thread->name) {
2469                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2470                 g_assert (!error);
2471                 g_string_append_printf (text, "\n\"%s\"", name);
2472                 g_free (name);
2473         }
2474         else if (thread->threadpool_thread)
2475                 g_string_append (text, "\n\"<threadpool thread>\"");
2476         else
2477                 g_string_append (text, "\n\"<unnamed thread>\"");
2478
2479 #ifndef HOST_WIN32
2480         wapi_desc = wapi_current_thread_desc ();
2481         g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
2482         free (wapi_desc);
2483 #endif
2484
2485 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2486         if (start_ctx) {
2487                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2488         } else if (!sigctx)
2489                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2490         else
2491                 mono_sigctx_to_monoctx (sigctx, &ctx);
2492
2493         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2494 #else
2495         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2496 #endif
2497
2498         mono_runtime_printf ("%s", text->str);
2499
2500 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2501         OutputDebugStringA(text->str);
2502 #endif
2503
2504         g_string_free (text, TRUE);
2505         mono_runtime_stdout_fflush ();
2506 }
2507
2508 /*
2509  * mono_print_thread_dump:
2510  *
2511  *   Print information about the current thread to stdout.
2512  * SIGCTX can be NULL, allowing this to be called from gdb.
2513  */
2514 void
2515 mono_print_thread_dump (void *sigctx)
2516 {
2517         mono_print_thread_dump_internal (sigctx, NULL);
2518 }
2519
2520 void
2521 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2522 {
2523         mono_print_thread_dump_internal (NULL, ctx);
2524 }
2525
2526 /*
2527  * mono_resume_unwind:
2528  *
2529  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2530  * unwinding.
2531  */
2532 void
2533 mono_resume_unwind (MonoContext *ctx)
2534 {
2535         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
2536         MonoContext new_ctx;
2537
2538         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2539         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2540         new_ctx = *ctx;
2541
2542         mono_handle_exception_internal (&new_ctx, (MonoObject *)jit_tls->resume_state.ex_obj, TRUE, NULL);
2543
2544         mono_restore_context (&new_ctx);
2545 }
2546
2547 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2548
2549 typedef struct {
2550         MonoJitInfo *ji;
2551         MonoContext ctx;
2552         MonoJitExceptionInfo *ei;
2553 } FindHandlerBlockData;
2554
2555 static gboolean
2556 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2557 {
2558         int i;
2559         gpointer ip;
2560         FindHandlerBlockData *pdata = (FindHandlerBlockData *)data;
2561         MonoJitInfo *ji = frame->ji;
2562
2563         if (!ji)
2564                 return FALSE;
2565
2566         ip = MONO_CONTEXT_GET_IP (ctx);
2567
2568         for (i = 0; i < ji->num_clauses; ++i) {
2569                 MonoJitExceptionInfo *ei = ji->clauses + i;
2570                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2571                         continue;
2572                 /*If ip points to the first instruction it means the handler block didn't start
2573                  so we can leave its execution to the EH machinery*/
2574                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2575                         pdata->ji = ji;
2576                         pdata->ei = ei;
2577                         pdata->ctx = *ctx;
2578                         break;
2579                 }
2580         }
2581         return FALSE;
2582 }
2583
2584
2585 static gpointer
2586 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2587 {
2588         int i;
2589         MonoJitExceptionInfo *clause = NULL;
2590         gpointer ip;
2591
2592         ip = MONO_CONTEXT_GET_IP (ctx);
2593
2594         for (i = 0; i < ji->num_clauses; ++i) {
2595                 clause = &ji->clauses [i];
2596                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2597                         continue;
2598                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2599                         break;
2600         }
2601
2602         /*no matching finally */
2603         if (i == ji->num_clauses)
2604                 return NULL;
2605
2606         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2607         if (ip == clause->handler_start)
2608                 return NULL;
2609
2610         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2611 }
2612
2613 /*
2614  * Finds the bottom handler block running and install a block guard if needed.
2615  * FIXME add full-aot support.
2616  */
2617 gboolean
2618 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2619 {
2620         FindHandlerBlockData data = { 0 };
2621         MonoJitTlsData *jit_tls = (MonoJitTlsData *)ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2622         gpointer resume_ip;
2623
2624         /* FIXME */
2625         if (mono_aot_only)
2626                 return FALSE;
2627
2628         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2629          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2630          */
2631         if (!jit_tls || jit_tls->handler_block_return_address)
2632                 return FALSE;
2633
2634         /* Do an async safe stack walk */
2635         mono_thread_info_set_is_async_context (TRUE);
2636         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data);
2637         mono_thread_info_set_is_async_context (FALSE);
2638
2639         if (!data.ji)
2640                 return FALSE;
2641
2642         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2643
2644         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2645         if (resume_ip == NULL)
2646                 return FALSE;
2647
2648         jit_tls->handler_block_return_address = resume_ip;
2649         jit_tls->handler_block = data.ei;
2650
2651         return TRUE;
2652 }
2653
2654 #else
2655 gboolean
2656 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2657 {
2658         return FALSE;
2659 }
2660
2661 #endif
2662
2663 void
2664 mono_set_cast_details (MonoClass *from, MonoClass *to)
2665 {
2666         MonoJitTlsData *jit_tls = NULL;
2667
2668         if (mini_get_debug_options ()->better_cast_details) {
2669                 jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
2670                 jit_tls->class_cast_from = from;
2671                 jit_tls->class_cast_to = to;
2672         }
2673 }
2674
2675
2676 /*returns false if the thread is not attached*/
2677 gboolean
2678 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
2679 {
2680 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2681         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2682         if (!thread) {
2683                 ctx->valid = FALSE;
2684                 G_BREAKPOINT ();
2685                 return FALSE;
2686         }
2687
2688         if (sigctx) {
2689                 mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
2690
2691                 ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2692                 ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2693                 ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2694         }
2695         else {
2696                 mono_thread_state_init (ctx);
2697         }
2698
2699         if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF])
2700                 return FALSE;
2701
2702         ctx->valid = TRUE;
2703         return TRUE;
2704 #else
2705         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
2706         return FALSE;
2707 #endif
2708 }
2709
2710 void
2711 mono_thread_state_init (MonoThreadUnwindState *ctx)
2712 {
2713         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2714
2715 #if defined(MONO_CROSS_COMPILE)
2716         ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
2717 #elif MONO_ARCH_HAS_MONO_CONTEXT
2718         MONO_CONTEXT_GET_CURRENT (ctx->ctx);
2719 #else
2720         g_error ("Use a null sigctx requires a working mono-context");
2721 #endif
2722
2723         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2724         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2725         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
2726         ctx->valid = TRUE;
2727 }
2728
2729
2730 gboolean
2731 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
2732 {
2733         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2734         if (!thread) {
2735                 ctx->valid = FALSE;
2736                 return FALSE;
2737         }
2738
2739         ctx->ctx = *mctx;
2740         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2741         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2742         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2743         ctx->valid = TRUE;
2744         return TRUE;
2745 }
2746
2747 /*returns false if the thread is not attached*/
2748 gboolean
2749 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
2750 {
2751         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2752         MONO_ARCH_CONTEXT_DEF
2753
2754         mono_arch_flush_register_windows ();
2755
2756         if (!thread || !thread->jit_data) {
2757                 ctx->valid = FALSE;
2758                 return FALSE;
2759         }
2760 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
2761         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
2762 #else
2763         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
2764 #endif
2765                 
2766         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2767         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2768         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2769         ctx->valid = TRUE;
2770         return TRUE;
2771 }
2772
2773 static void
2774 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
2775 {
2776         mono_handle_exception (ctx, (MonoObject *)exc);
2777         mono_restore_context (ctx);
2778 }
2779
2780 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
2781 void
2782 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
2783 {
2784 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
2785         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
2786         jit_tls->ex_ctx = *ctx;
2787
2788         mono_arch_setup_async_callback (ctx, async_cb, user_data);
2789 #else
2790         g_error ("This target doesn't support mono_arch_setup_async_callback");
2791 #endif
2792 }
2793
2794 void
2795 mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
2796 {
2797         unhandled_exception_hook = func;
2798         unhandled_exception_hook_data = user_data;
2799 }
2800
2801 void
2802 mono_invoke_unhandled_exception_hook (MonoObject *exc)
2803 {
2804         if (unhandled_exception_hook) {
2805                 unhandled_exception_hook (exc, unhandled_exception_hook_data);
2806         } else {
2807                 MonoObject *other = NULL;
2808                 MonoString *str = mono_object_to_string (exc, &other);
2809                 char *msg = NULL;
2810                 
2811                 if (str)
2812                         msg = mono_string_to_utf8 (str);
2813                 else if (other) {
2814                         char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
2815                         char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);
2816
2817                         msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
2818                                 original_backtrace, nested_backtrace);
2819
2820                         g_free (original_backtrace);
2821                         g_free (nested_backtrace);
2822                 } else {
2823                         msg = g_strdup ("Nested exception trying to figure out what went wrong");
2824                 }
2825                 mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
2826                 g_free (msg);
2827 #if defined(HOST_IOS)
2828                 g_assertion_message ("Terminating runtime due to unhandled exception");
2829 #else
2830                 exit (mono_environment_exitcode_get ());
2831 #endif
2832         }
2833
2834         g_assert_not_reached ();
2835 }
2836
2837 /*
2838  * mono_restore_context:
2839  *
2840  *   Call the architecture specific restore context function.
2841  */
2842 void
2843 mono_restore_context (MonoContext *ctx)
2844 {
2845         static void (*restore_context) (MonoContext *);
2846
2847         if (!restore_context)
2848                 restore_context = (void (*)(MonoContext *))mono_get_restore_context ();
2849         restore_context (ctx);
2850         g_assert_not_reached ();
2851 }
2852
2853 /*
2854  * mono_jinfo_get_unwind_info:
2855  *
2856  *   Return the unwind info for JI.
2857  */
2858 guint8*
2859 mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
2860 {
2861         if (ji->from_aot)
2862                 return mono_aot_get_unwind_info (ji, unwind_info_len);
2863         else
2864                 return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len);
2865 }
2866
2867 int
2868 mono_jinfo_get_epilog_size (MonoJitInfo *ji)
2869 {
2870         MonoArchEHJitInfo *info;
2871
2872         info = mono_jit_info_get_arch_eh_info (ji);
2873         g_assert (info);
2874
2875         return info->epilog_size;
2876 }
2877
2878 /*
2879  * LLVM/Bitcode exception handling.
2880  */
2881
2882 static void
2883 throw_exception (MonoObject *ex, gboolean rethrow)
2884 {
2885         MonoError error;
2886         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
2887         MonoException *mono_ex;
2888
2889         if (!mono_object_isinst_checked (ex, mono_defaults.exception_class, &error)) {
2890                 mono_error_assert_ok (&error);
2891                 mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error);
2892                 mono_error_assert_ok (&error);
2893         }
2894         else
2895                 mono_ex = (MonoException*)ex;
2896
2897         // Note: Not pinned
2898         jit_tls->thrown_exc = mono_gchandle_new ((MonoObject*)mono_ex, FALSE);
2899
2900         if (!rethrow) {
2901 #ifdef MONO_ARCH_HAVE_UNWIND_BACKTRACE
2902                 GList *l, *ips = NULL;
2903                 GList *trace;
2904
2905                 _Unwind_Backtrace (build_stack_trace, &ips);
2906                 /* The list contains ip-gshared info pairs */
2907                 trace = NULL;
2908                 ips = g_list_reverse (ips);
2909                 for (l = ips; l; l = l->next) {
2910                         trace = g_list_append (trace, l->data);
2911                         trace = g_list_append (trace, NULL);
2912                 }
2913                 MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_glist_to_array (trace, mono_defaults.int_class));
2914                 g_list_free (l);
2915                 g_list_free (trace);
2916 #endif
2917         }
2918
2919         mono_llvm_cpp_throw_exception ();
2920 }
2921
2922 void
2923 mono_llvm_throw_exception (MonoObject *ex)
2924 {
2925         throw_exception (ex, FALSE);
2926 }
2927
2928 void
2929 mono_llvm_rethrow_exception (MonoObject *ex)
2930 {
2931         throw_exception (ex, TRUE);
2932 }
2933
2934 void
2935 mono_llvm_raise_exception (MonoException *e)
2936 {
2937         mono_llvm_throw_exception ((MonoObject*)e);
2938 }
2939
2940 void
2941 mono_llvm_throw_corlib_exception (guint32 ex_token_index)
2942 {
2943         guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
2944         MonoException *ex;
2945
2946         ex = mono_exception_from_token (mono_defaults.exception_class->image, ex_token);
2947
2948         mono_llvm_throw_exception ((MonoObject*)ex);
2949 }
2950
2951 /*
2952  * mono_llvm_resume_exception:
2953  *
2954  *   Resume exception propagation.
2955  */
2956 void
2957 mono_llvm_resume_exception (void)
2958 {
2959         mono_llvm_cpp_throw_exception ();
2960 }
2961
2962 /*
2963  * mono_llvm_load_exception:
2964  *
2965  *   Return the currently thrown exception.
2966  */
2967 MonoObject *
2968 mono_llvm_load_exception (void)
2969 {
2970         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
2971
2972         MonoException *mono_ex = (MonoException*)mono_gchandle_get_target (jit_tls->thrown_exc);
2973
2974         if (mono_ex->trace_ips) {
2975                 GList *trace_ips = NULL;
2976                 gpointer ip = __builtin_return_address (0);
2977
2978                 size_t upper = mono_array_length (mono_ex->trace_ips);
2979
2980                 for (int i = 0; i < upper; i+= 2) {
2981                         gpointer curr_ip = mono_array_get (mono_ex->trace_ips, gpointer, i);
2982                         gpointer curr_info = mono_array_get (mono_ex->trace_ips, gpointer, i + 1);
2983                         trace_ips = g_list_append (trace_ips, curr_ip);
2984                         trace_ips = g_list_append (trace_ips, curr_info);
2985
2986                         if (ip == curr_ip)
2987                                 break;
2988                 }
2989
2990                 // FIXME: Does this work correctly for rethrows?
2991                 // We may be discarding useful information
2992                 // when this gets GC'ed
2993                 MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_glist_to_array (trace_ips, mono_defaults.int_class));
2994                 g_list_free (trace_ips);
2995
2996                 // FIXME:
2997                 //MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex));
2998         } else {
2999                 MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_array_new (mono_domain_get (), mono_defaults.int_class, 0));
3000                 MONO_OBJECT_SETREF (mono_ex, stack_trace, mono_array_new (mono_domain_get (), mono_defaults.stack_frame_class, 0));
3001         }
3002
3003         return &mono_ex->object;
3004 }
3005
3006 /*
3007  * mono_llvm_clear_exception:
3008  *
3009  *   Mark the currently thrown exception as handled.
3010  */
3011 void
3012 mono_llvm_clear_exception (void)
3013 {
3014         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3015         mono_gchandle_free (jit_tls->thrown_exc);
3016         jit_tls->thrown_exc = 0;
3017
3018         mono_memory_barrier ();
3019 }
3020
3021 /*
3022  * mono_llvm_match_exception:
3023  *
3024  *   Return the innermost clause containing REGION_START-REGION_END which can handle
3025  * the current exception.
3026  */
3027 gint32
3028 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj)
3029 {
3030                         MonoError error;
3031         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3032         MonoObject *exc;
3033         gint32 index = -1;
3034
3035         g_assert (jit_tls->thrown_exc);
3036         exc = mono_gchandle_get_target (jit_tls->thrown_exc);
3037         for (int i = 0; i < jinfo->num_clauses; i++) {
3038                 MonoJitExceptionInfo *ei = &jinfo->clauses [i];
3039                 MonoClass *catch_class;
3040
3041                 if (! (ei->try_offset == region_start && ei->try_offset + ei->try_len == region_end) )
3042                         continue;
3043
3044                 catch_class = ei->data.catch_class;
3045                 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) {
3046                         MonoGenericContext context;
3047                         MonoType *inflated_type;
3048
3049                         g_assert (rgctx || this_obj);
3050                         context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
3051                         inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
3052                         mono_error_assert_ok (&error); /* FIXME don't swallow the error */
3053
3054                         catch_class = mono_class_from_mono_type (inflated_type);
3055                         mono_metadata_free_type (inflated_type);
3056                 }
3057
3058                 // FIXME: Handle edge cases handled in get_exception_catch_class
3059                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (exc, catch_class, &error)) {
3060                         index = ei->clause_index;
3061                         break;
3062                 } else
3063                         mono_error_assert_ok (&error);
3064                 
3065                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3066                         g_assert_not_reached ();
3067                 }
3068         }
3069
3070         return index;
3071 }
3072
3073 #ifdef ENABLE_LLVM
3074 _Unwind_Reason_Code 
3075 mono_debug_personality (int a, _Unwind_Action b,
3076 uint64_t c, struct _Unwind_Exception *d, struct _Unwind_Context *e)
3077 {
3078         g_assert_not_reached ();
3079 }
3080 #else
3081 void
3082 mono_debug_personality (void);
3083
3084 void
3085 mono_debug_personality (void)
3086 {
3087         g_assert_not_reached ();
3088 }
3089 #endif