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