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