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