[arm] respect thumb mode in mixed mode unwinding
[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
1074         if (mono_llvm_only) {
1075                 GSList *l, *ips;
1076
1077                 if (async)
1078                         return;
1079
1080                 ips = get_unwind_backtrace ();
1081                 for (l = ips; l; l = l->next) {
1082                         guint8 *ip = (guint8*)l->data;
1083                         memset (&frame, 0, sizeof (StackFrameInfo));
1084                         frame.ji = mini_jit_info_table_find (domain, (char*)ip, &frame.domain);
1085                         if (!frame.ji || frame.ji->is_trampoline)
1086                                 continue;
1087                         frame.type = FRAME_TYPE_MANAGED;
1088                         frame.method = jinfo_get_method (frame.ji);
1089                         // FIXME: Cannot lookup the actual method
1090                         frame.actual_method = frame.method;
1091                         if (frame.type == FRAME_TYPE_MANAGED) {
1092                                 if (!frame.method->wrapper_type || frame.method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
1093                                         frame.managed = TRUE;
1094                         }
1095                         frame.native_offset = ip - (guint8*)frame.ji->code_start;
1096                         frame.il_offset = -1;
1097
1098                         if (func (&frame, NULL, user_data))
1099                                 break;
1100                 }
1101                 g_free (ips);
1102                 return;
1103         }
1104
1105         g_assert (start_ctx);
1106         g_assert (domain);
1107         g_assert (jit_tls);
1108         /*The LMF will be null if the target have no managed frames.*/
1109         /* g_assert (lmf); */
1110
1111         if (async)
1112                 g_assert (unwind_options == MONO_UNWIND_NONE);
1113
1114         memcpy (&ctx, start_ctx, sizeof (MonoContext));
1115         memset (reg_locations, 0, sizeof (reg_locations));
1116
1117         while (MONO_CONTEXT_GET_SP (&ctx) < jit_tls->end_of_stack) {
1118                 frame.lmf = lmf;
1119                 res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, get_reg_locations ? new_reg_locations : NULL, &frame);
1120                 if (!res)
1121                         return;
1122
1123                 if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji && !frame.ji->is_trampoline) {
1124                         MonoDebugSourceLocation *source;
1125
1126                         source = mono_debug_lookup_source_location (jinfo_get_method (frame.ji), frame.native_offset, domain);
1127                         if (source) {
1128                                 il_offset = source->il_offset;
1129                         } else {
1130                                 SeqPoint sp;
1131                                 if (mono_find_prev_seq_point_for_native_offset (domain, jinfo_get_method (frame.ji), frame.native_offset, NULL, &sp))
1132                                         il_offset = sp.il_offset;
1133                                 else
1134                                         il_offset = -1;
1135                         }
1136                         mono_debug_free_source_location (source);
1137                 } else
1138                         il_offset = -1;
1139
1140                 frame.il_offset = il_offset;
1141
1142                 if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji && !frame.ji->is_trampoline) {
1143                         frame.actual_method = get_method_from_stack_frame (frame.ji, get_generic_info_from_stack_frame (frame.ji, &ctx));
1144                 } else {
1145                         frame.actual_method = frame.method;
1146                 }
1147
1148                 if (get_reg_locations)
1149                         frame.reg_locations = reg_locations;
1150
1151                 if (func (&frame, &ctx, user_data))
1152                         return;
1153
1154                 if (get_reg_locations) {
1155                         for (i = 0; i < MONO_MAX_IREGS; ++i)
1156                                 if (new_reg_locations [i])
1157                                         reg_locations [i] = new_reg_locations [i];
1158                 }
1159                 
1160                 ctx = new_ctx;
1161         }
1162 }
1163
1164 MonoBoolean
1165 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
1166                           MonoReflectionMethod **method, 
1167                           gint32 *iloffset, gint32 *native_offset,
1168                           MonoString **file, gint32 *line, gint32 *column)
1169 {
1170         MonoError error;
1171         MonoDomain *domain = mono_domain_get ();
1172         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1173         MonoLMF *lmf = mono_get_lmf ();
1174         MonoJitInfo *ji = NULL;
1175         MonoContext ctx, new_ctx;
1176         MonoDebugSourceLocation *location;
1177         MonoMethod *jmethod = NULL, *actual_method;
1178         StackFrameInfo frame;
1179         gboolean res;
1180         Unwinder unwinder;
1181         int il_offset = -1;
1182
1183         MONO_ARCH_CONTEXT_DEF;
1184
1185         if (mono_llvm_only) {
1186                 GSList *l, *ips;
1187                 MonoDomain *frame_domain;
1188                 guint8 *frame_ip = NULL;
1189
1190                 /* FIXME: Generalize this code with an interface which returns an array of StackFrame structures */
1191                 jmethod = NULL;
1192                 ips = get_unwind_backtrace ();
1193                 for (l = ips; l && skip >= 0; l = l->next) {
1194                         guint8 *ip = (guint8*)l->data;
1195
1196                         frame_ip = ip;
1197
1198                         ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &frame_domain);
1199                         if (!ji || ji->is_trampoline)
1200                                 continue;
1201
1202                         /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */
1203                         jmethod = jinfo_get_method (ji);
1204                         if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE)
1205                                 continue;
1206                         skip--;
1207                 }
1208                 g_slist_free (ips);
1209                 if (!jmethod || !l)
1210                         return FALSE;
1211                 /* No way to resolve generic instances */
1212                 actual_method = jmethod;
1213                 *native_offset = frame_ip - (guint8*)ji->code_start;
1214         } else {
1215                 mono_arch_flush_register_windows ();
1216
1217 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
1218                 MONO_INIT_CONTEXT_FROM_CURRENT (&ctx);
1219 #else
1220                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, ves_icall_get_frame_info);
1221 #endif
1222
1223                 unwinder_init (&unwinder);
1224
1225                 new_ctx = ctx;
1226                 do {
1227                         ctx = new_ctx;
1228                         res = unwinder_unwind_frame (&unwinder, domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1229                         if (!res)
1230                                 return FALSE;
1231                         switch (frame.type) {
1232                         case FRAME_TYPE_MANAGED_TO_NATIVE:
1233                         case FRAME_TYPE_DEBUGGER_INVOKE:
1234                         case FRAME_TYPE_TRAMPOLINE:
1235                         case FRAME_TYPE_INTERP_TO_MANAGED:
1236                                 continue;
1237                         case FRAME_TYPE_INTERP:
1238                                 skip--;
1239                                 break;
1240                         default:
1241                                 ji = frame.ji;
1242                                 *native_offset = frame.native_offset;
1243
1244                                 /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */
1245                                 jmethod = jinfo_get_method (ji);
1246                                 if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE)
1247                                         continue;
1248                                 skip--;
1249                                 break;
1250                         }
1251                 } while (skip >= 0);
1252
1253                 if (frame.type == FRAME_TYPE_INTERP) {
1254                         jmethod = frame.method;
1255                         actual_method = frame.actual_method;
1256                         *native_offset = frame.native_offset;
1257                 } else {
1258                         actual_method = get_method_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, &ctx));
1259                 }
1260         }
1261
1262         MonoReflectionMethod *rm = mono_method_get_object_checked (domain, actual_method, NULL, &error);
1263         if (!mono_error_ok (&error)) {
1264                 mono_error_set_pending_exception (&error);
1265                 return FALSE;
1266         }
1267         mono_gc_wbarrier_generic_store (method, (MonoObject*) rm);
1268
1269         if (il_offset != -1) {
1270                 location = mono_debug_lookup_source_location_by_il (jmethod, il_offset, domain);
1271         } else {
1272                 location = mono_debug_lookup_source_location (jmethod, *native_offset, domain);
1273         }
1274         if (location)
1275                 *iloffset = location->il_offset;
1276         else
1277                 *iloffset = 0;
1278
1279         if (need_file_info) {
1280                 if (location) {
1281                         MonoString *filename = mono_string_new_checked (domain, location->source_file, &error);
1282                         if (!is_ok (&error)) {
1283                                 mono_error_set_pending_exception (&error);
1284                                 return FALSE;
1285                         }
1286                         mono_gc_wbarrier_generic_store (file, (MonoObject*)filename);
1287                         *line = location->row;
1288                         *column = location->column;
1289                 } else {
1290                         *file = NULL;
1291                         *line = *column = 0;
1292                 }
1293         }
1294
1295         mono_debug_free_source_location (location);
1296
1297         return TRUE;
1298 }
1299
1300 static MonoClass*
1301 get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
1302 {
1303         MonoError error;
1304         MonoClass *catch_class = ei->data.catch_class;
1305         MonoType *inflated_type;
1306         MonoGenericContext context;
1307
1308         /*MonoJitExceptionInfo::data is an union used by filter and finally clauses too.*/
1309         if (!catch_class || ei->flags != MONO_EXCEPTION_CLAUSE_NONE)
1310                 return NULL;
1311
1312         if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
1313                 return catch_class;
1314         context = get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx));
1315
1316         /* FIXME: we shouldn't inflate but instead put the
1317            type in the rgctx and fetch it from there.  It
1318            might be a good idea to do this lazily, i.e. only
1319            when the exception is actually thrown, so as not to
1320            waste space for exception clauses which might never
1321            be encountered. */
1322         inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
1323         mono_error_assert_ok (&error); /* FIXME don't swallow the error */
1324
1325         catch_class = mono_class_from_mono_type (inflated_type);
1326         mono_metadata_free_type (inflated_type);
1327
1328         return catch_class;
1329 }
1330
1331 /*
1332  * mini_jit_info_table_find_ext:
1333  *
1334  *   Same as mono_jit_info_table_find, but search all the domains of the current thread
1335  * if ADDR is not found in DOMAIN. The domain where the method was found is stored into
1336  * OUT_DOMAIN if it is not NULL.
1337  */
1338 MonoJitInfo*
1339 mini_jit_info_table_find_ext (MonoDomain *domain, char *addr, gboolean allow_trampolines, MonoDomain **out_domain)
1340 {
1341         MonoJitInfo *ji;
1342         MonoInternalThread *t = mono_thread_internal_current ();
1343         gpointer *refs;
1344
1345         if (out_domain)
1346                 *out_domain = NULL;
1347
1348         ji = mono_jit_info_table_find_internal (domain, addr, TRUE, allow_trampolines);
1349         if (ji) {
1350                 if (out_domain)
1351                         *out_domain = domain;
1352                 return ji;
1353         }
1354
1355         /* maybe it is shared code, so we also search in the root domain */
1356         if (domain != mono_get_root_domain ()) {
1357                 ji = mono_jit_info_table_find_internal (mono_get_root_domain (), addr, TRUE, allow_trampolines);
1358                 if (ji) {
1359                         if (out_domain)
1360                                 *out_domain = mono_get_root_domain ();
1361                         return ji;
1362                 }
1363         }
1364
1365         if (!t)
1366                 return NULL;
1367
1368         refs = (gpointer *)((t->appdomain_refs) ? *(gpointer *) t->appdomain_refs : NULL);
1369         for (; refs && *refs; refs++) {
1370                 if (*refs != domain && *refs != mono_get_root_domain ()) {
1371                         ji = mono_jit_info_table_find_internal ((MonoDomain*) *refs, addr, TRUE, allow_trampolines);
1372                         if (ji) {
1373                                 if (out_domain)
1374                                         *out_domain = (MonoDomain*) *refs;
1375                                 return ji;
1376                         }
1377                 }
1378         }
1379
1380         return NULL;
1381 }
1382
1383 MonoJitInfo*
1384 mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
1385 {
1386         return mini_jit_info_table_find_ext (domain, addr, FALSE, out_domain);
1387 }
1388
1389 /* Class lazy loading functions */
1390 static GENERATE_GET_CLASS_WITH_CACHE (runtime_compat_attr, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute")
1391
1392 /*
1393  * wrap_non_exception_throws:
1394  *
1395  *   Determine whenever M's assembly has a RuntimeCompatibilityAttribute with the
1396  * WrapNonExceptionThrows flag set.
1397  */
1398 static gboolean
1399 wrap_non_exception_throws (MonoMethod *m)
1400 {
1401         MonoError error;
1402         MonoAssembly *ass = m->klass->image->assembly;
1403         MonoCustomAttrInfo* attrs;
1404         MonoClass *klass;
1405         int i;
1406         gboolean val = FALSE;
1407
1408         g_assert (ass);
1409         if (ass->wrap_non_exception_throws_inited)
1410                 return ass->wrap_non_exception_throws;
1411
1412         klass = mono_class_get_runtime_compat_attr_class ();
1413
1414         attrs = mono_custom_attrs_from_assembly_checked (ass, FALSE, &error);
1415         mono_error_cleanup (&error); /* FIXME don't swallow the error */
1416         if (attrs) {
1417                 for (i = 0; i < attrs->num_attrs; ++i) {
1418                         MonoCustomAttrEntry *attr = &attrs->attrs [i];
1419                         const gchar *p;
1420                         int num_named, named_type, name_len;
1421                         char *name;
1422
1423                         if (!attr->ctor || attr->ctor->klass != klass)
1424                                 continue;
1425                         /* Decode the RuntimeCompatibilityAttribute. See reflection.c */
1426                         p = (const char*)attr->data;
1427                         g_assert (read16 (p) == 0x0001);
1428                         p += 2;
1429                         num_named = read16 (p);
1430                         if (num_named != 1)
1431                                 continue;
1432                         p += 2;
1433                         named_type = *p;
1434                         p ++;
1435                         /* data_type = *p; */
1436                         p ++;
1437                         /* Property */
1438                         if (named_type != 0x54)
1439                                 continue;
1440                         name_len = mono_metadata_decode_blob_size (p, &p);
1441                         name = (char *)g_malloc (name_len + 1);
1442                         memcpy (name, p, name_len);
1443                         name [name_len] = 0;
1444                         p += name_len;
1445                         g_assert (!strcmp (name, "WrapNonExceptionThrows"));
1446                         g_free (name);
1447                         /* The value is a BOOLEAN */
1448                         val = *p;
1449                 }
1450                 mono_custom_attrs_free (attrs);
1451         }
1452
1453         ass->wrap_non_exception_throws = val;
1454         mono_memory_barrier ();
1455         ass->wrap_non_exception_throws_inited = TRUE;
1456
1457         return val;
1458 }
1459
1460 #define MAX_UNMANAGED_BACKTRACE 128
1461 static MonoArray*
1462 build_native_trace (MonoError *error)
1463 {
1464         error_init (error);
1465 /* This puppy only makes sense on mobile, IOW, ARM. */
1466 #if defined (HAVE_BACKTRACE_SYMBOLS) && defined (TARGET_ARM)
1467         MonoArray *res;
1468         void *native_trace [MAX_UNMANAGED_BACKTRACE];
1469         int size = -1;
1470         MONO_ENTER_GC_SAFE;
1471         size = backtrace (native_trace, MAX_UNMANAGED_BACKTRACE);
1472         MONO_EXIT_GC_SAFE;
1473         int i;
1474
1475         if (!size)
1476                 return NULL;
1477         res = mono_array_new_checked (mono_domain_get (), mono_defaults.int_class, size, error);
1478         return_val_if_nok (error, NULL);
1479
1480         for (i = 0; i < size; i++)
1481                 mono_array_set (res, gpointer, i, native_trace [i]);
1482         return res;
1483 #else
1484         return NULL;
1485 #endif
1486 }
1487
1488 static void
1489 setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, GList **trace_ips)
1490 {
1491         if (mono_ex) {
1492                 *trace_ips = g_list_reverse (*trace_ips);
1493                 MonoError error;
1494                 MonoArray *ips_arr = mono_glist_to_array (*trace_ips, mono_defaults.int_class, &error);
1495                 mono_error_assert_ok (&error);
1496                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
1497                 MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace (&error));
1498                 mono_error_assert_ok (&error);
1499                 if (dynamic_methods) {
1500                         /* These methods could go away anytime, so save a reference to them in the exception object */
1501                         GSList *l;
1502                         MonoMList *list = NULL;
1503
1504                         for (l = dynamic_methods; l; l = l->next) {
1505                                 guint32 dis_link;
1506                                 MonoDomain *domain = mono_domain_get ();
1507
1508                                 if (domain->method_to_dyn_method) {
1509                                         mono_domain_lock (domain);
1510                                         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, l->data);
1511                                         mono_domain_unlock (domain);
1512                                         if (dis_link) {
1513                                                 MonoObject *o = mono_gchandle_get_target (dis_link);
1514                                                 if (o) {
1515                                                         list = mono_mlist_prepend_checked (list, o, &error);
1516                                                         mono_error_assert_ok (&error);
1517                                                 }
1518                                         }
1519                                 }
1520                         }
1521
1522                         MONO_OBJECT_SETREF (mono_ex, dynamic_methods, list);
1523                 }
1524         }
1525         g_list_free (*trace_ips);
1526         *trace_ips = NULL;
1527 }
1528
1529 /*
1530  * mono_handle_exception_internal_first_pass:
1531  *
1532  *   The first pass of exception handling. Unwind the stack until a catch clause which can catch
1533  * OBJ is found. Run the index of the filter clause which caught the exception into
1534  * OUT_FILTER_IDX. Return TRUE if the exception is caught, FALSE otherwise.
1535  */
1536 static gboolean
1537 mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception)
1538 {
1539         MonoError error;
1540         MonoDomain *domain = mono_domain_get ();
1541         MonoJitInfo *ji = NULL;
1542         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1543         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1544         MonoLMF *lmf = mono_get_lmf ();
1545         GList *trace_ips = NULL;
1546         GSList *dynamic_methods = NULL;
1547         MonoException *mono_ex;
1548         gboolean stack_overflow = FALSE;
1549         MonoContext initial_ctx;
1550         MonoMethod *method;
1551         int frame_count = 0;
1552         gint32 filter_idx;
1553         int i;
1554         MonoObject *ex_obj;
1555         Unwinder unwinder;
1556         gboolean in_interp;
1557
1558         g_assert (ctx != NULL);
1559
1560         if (obj == (MonoObject *)domain->stack_overflow_ex)
1561                 stack_overflow = TRUE;
1562
1563         mono_ex = (MonoException*)obj;
1564         MonoArray *initial_trace_ips = mono_ex->trace_ips;
1565         if (initial_trace_ips) {
1566                 int len = mono_array_length (initial_trace_ips) >> 1;
1567
1568                 for (i = 0; i < (len - 1); i++) {
1569                         gpointer ip = mono_array_get (initial_trace_ips, gpointer, i * 2 + 0);
1570                         gpointer generic_info = mono_array_get (initial_trace_ips, gpointer, i * 2 + 1);
1571                         trace_ips = g_list_prepend (trace_ips, ip);
1572                         trace_ips = g_list_prepend (trace_ips, generic_info);
1573                 }
1574         }
1575
1576         if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1577                 mono_error_assert_ok (&error);
1578                 mono_ex = NULL;
1579         }
1580
1581         if (!call_filter)
1582                 call_filter = (int (*) (MonoContext *, void *))mono_get_call_filter ();
1583
1584         g_assert (jit_tls->end_of_stack);
1585         g_assert (jit_tls->abort_func);
1586
1587         if (out_filter_idx)
1588                 *out_filter_idx = -1;
1589         if (out_ji)
1590                 *out_ji = NULL;
1591         if (out_prev_ji)
1592                 *out_prev_ji = NULL;
1593         filter_idx = 0;
1594         initial_ctx = *ctx;
1595
1596         unwinder_init (&unwinder);
1597
1598         while (1) {
1599                 MonoContext new_ctx;
1600                 guint32 free_stack;
1601                 int clause_index_start = 0;
1602                 gboolean unwind_res = TRUE;
1603                 
1604                 StackFrameInfo frame;
1605
1606                 if (out_prev_ji)
1607                         *out_prev_ji = ji;
1608
1609                 unwind_res = unwinder_unwind_frame (&unwinder, domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1610                 if (!unwind_res) {
1611                         setup_stack_trace (mono_ex, dynamic_methods, &trace_ips);
1612                         g_slist_free (dynamic_methods);
1613                         return FALSE;
1614                 }
1615
1616                 switch (frame.type) {
1617                 case FRAME_TYPE_DEBUGGER_INVOKE:
1618                 case FRAME_TYPE_MANAGED_TO_NATIVE:
1619                 case FRAME_TYPE_TRAMPOLINE:
1620                 case FRAME_TYPE_INTERP_TO_MANAGED:
1621                         *ctx = new_ctx;
1622                         continue;
1623                 case FRAME_TYPE_INTERP:
1624                 case FRAME_TYPE_MANAGED:
1625                         break;
1626                 default:
1627                         g_assert_not_reached ();
1628                         break;
1629                 }
1630
1631                 in_interp = frame.type == FRAME_TYPE_INTERP;
1632                 ji = frame.ji;
1633
1634                 gpointer ip;
1635                 if (in_interp)
1636                         ip = (guint16*)ji->code_start + frame.native_offset;
1637                 else
1638                         ip = MONO_CONTEXT_GET_IP (ctx);
1639
1640                 frame_count ++;
1641                 method = jinfo_get_method (ji);
1642                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1643
1644                 if (mini_get_debug_options ()->reverse_pinvoke_exceptions && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
1645                         g_error ("A native frame was found while unwinding the stack after an exception.\n"
1646                                          "The native frame called the managed method:\n%s\n",
1647                                          mono_method_full_name (method, TRUE));
1648                 }
1649
1650                 if (method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
1651                         // avoid giant stack traces during a stack overflow
1652                         if (frame_count < 1000) {
1653                                 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
1654                                 trace_ips = g_list_prepend (trace_ips, get_generic_info_from_stack_frame (ji, ctx));
1655                         }
1656                 }
1657
1658                 if (method->dynamic)
1659                         dynamic_methods = g_slist_prepend (dynamic_methods, method);
1660
1661                 if (stack_overflow) {
1662                         if (MONO_ARCH_STACK_GROWS_UP)
1663                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1664                         else
1665                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1666                 } else {
1667                         free_stack = 0xffffff;
1668                 }
1669                                 
1670                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1671                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1672                         gboolean filtered = FALSE;
1673
1674                         /* 
1675                          * During stack overflow, wait till the unwinding frees some stack
1676                          * space before running handlers/finalizers.
1677                          */
1678                         if (free_stack <= (64 * 1024))
1679                                 continue;
1680
1681                         if (is_address_protected (ji, ei, ip)) {
1682                                 /* catch block */
1683                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1684
1685                                 /*
1686                                  * Have to unwrap RuntimeWrappedExceptions if the
1687                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1688                                  */
1689                                 if (non_exception && !wrap_non_exception_throws (method))
1690                                         ex_obj = non_exception;
1691                                 else
1692                                         ex_obj = obj;
1693
1694                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1695 #ifndef DISABLE_PERFCOUNTERS
1696                                         mono_perfcounters->exceptions_filters++;
1697 #endif
1698
1699 #ifndef MONO_CROSS_COMPILE
1700 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1701                                         if (ji->from_llvm)
1702                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1703                                         else
1704                                                 /* Can't pass the ex object in a register yet to filter clauses, because call_filter () might not support it */
1705                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1706 #else
1707                                         g_assert (!ji->from_llvm);
1708                                         /* store the exception object in bp + ei->exvar_offset */
1709                                         *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1710 #endif
1711 #endif
1712
1713 #ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
1714                                         /*
1715                                          * Pass the original il clause index to the landing pad so it can
1716                                          * branch to the landing pad associated with the il clause.
1717                                          * This is needed because llvm compiled code assumes that the EH
1718                                          * code always branches to the innermost landing pad.
1719                                          */
1720                                         if (ji->from_llvm)
1721                                                 MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
1722 #endif
1723
1724                                         mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
1725                                         filtered = call_filter (ctx, ei->data.filter);
1726                                         mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
1727                                         if (filtered && out_filter_idx)
1728                                                 *out_filter_idx = filter_idx;
1729                                         if (out_ji)
1730                                                 *out_ji = ji;
1731                                         filter_idx ++;
1732
1733                                         if (filtered) {
1734                                                 setup_stack_trace (mono_ex, dynamic_methods, &trace_ips);
1735                                                 g_slist_free (dynamic_methods);
1736                                                 /* mono_debugger_agent_handle_exception () needs this */
1737                                                 mini_set_abort_threshold (ctx);
1738                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1739                                                 return TRUE;
1740                                         }
1741                                 }
1742
1743                                 MonoError isinst_error;
1744                                 error_init (&isinst_error);
1745                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (ex_obj, catch_class, &error)) {
1746                                         setup_stack_trace (mono_ex, dynamic_methods, &trace_ips);
1747                                         g_slist_free (dynamic_methods);
1748
1749                                         if (out_ji)
1750                                                 *out_ji = ji;
1751
1752                                         /* mono_debugger_agent_handle_exception () needs this */
1753                                         if (!in_interp)
1754                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1755                                         return TRUE;
1756                                 }
1757                                 mono_error_cleanup (&isinst_error);
1758                         }
1759                 }
1760
1761                 *ctx = new_ctx;
1762         }
1763
1764         g_assert_not_reached ();
1765 }
1766
1767 /**
1768  * mono_handle_exception_internal:
1769  * \param ctx saved processor state
1770  * \param obj the exception object
1771  * \param resume whenever to resume unwinding based on the state in \c MonoJitTlsData.
1772  */
1773 static gboolean
1774 mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resume, MonoJitInfo **out_ji)
1775 {
1776         MonoError error;
1777         MonoDomain *domain = mono_domain_get ();
1778         MonoJitInfo *ji, *prev_ji;
1779         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1780         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1781         MonoLMF *lmf = mono_get_lmf ();
1782         MonoException *mono_ex;
1783         gboolean stack_overflow = FALSE;
1784         MonoContext initial_ctx;
1785         MonoMethod *method;
1786         int frame_count = 0;
1787         gint32 filter_idx, first_filter_idx = 0;
1788         int i;
1789         MonoObject *ex_obj;
1790         MonoObject *non_exception = NULL;
1791         Unwinder unwinder;
1792         gboolean in_interp;
1793
1794         g_assert (ctx != NULL);
1795         if (!obj) {
1796                 MonoException *ex = mono_get_exception_null_reference ();
1797                 MonoString *msg = mono_string_new_checked (domain, "Object reference not set to an instance of an object", &error);
1798                 mono_error_assert_ok (&error);
1799                 MONO_OBJECT_SETREF (ex, message, msg);
1800                 obj = (MonoObject *)ex;
1801         } 
1802
1803         /*
1804          * Allocate a new exception object instead of the preconstructed ones.
1805          */
1806         if (obj == (MonoObject *)domain->stack_overflow_ex) {
1807                 /*
1808                  * It is not a good idea to try and put even more pressure on the little stack available.
1809                  * obj = mono_get_exception_stack_overflow ();
1810                  */
1811                 stack_overflow = TRUE;
1812         }
1813         else if (obj == (MonoObject *)domain->null_reference_ex) {
1814                 obj = (MonoObject *)mono_get_exception_null_reference ();
1815         }
1816
1817         if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1818                 mono_error_assert_ok (&error);
1819                 non_exception = obj;
1820                 obj = (MonoObject *)mono_get_exception_runtime_wrapped_checked (obj, &error);
1821                 mono_error_assert_ok (&error);
1822         }
1823
1824         mono_ex = (MonoException*)obj;
1825
1826         if (mini_get_debug_options ()->suspend_on_exception) {
1827                 mono_runtime_printf_err ("Exception thrown, suspending...");
1828                 while (1)
1829                         ;
1830         }
1831
1832         if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1833                 mono_ex = (MonoException*)obj;
1834         } else {
1835                 mono_error_assert_ok (&error);
1836                 mono_ex = NULL;
1837         }
1838
1839         if (mono_ex && jit_tls->class_cast_from) {
1840                 if (!strcmp (mono_ex->object.vtable->klass->name, "InvalidCastException")) {
1841                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1842                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1843                         char *msg = g_strdup_printf ("Unable to cast object of type '%s' to type '%s'.", from_name, to_name);
1844                         mono_ex->message = mono_string_new_checked (domain, msg, &error);
1845                         g_free (from_name);
1846                         g_free (to_name);
1847                         if (!is_ok (&error)) {
1848                                 mono_runtime_printf_err ("Error creating class cast exception message '%s'\n", msg);
1849                                 mono_error_assert_ok (&error);
1850                         }
1851                         g_free (msg);
1852                 }
1853                 if (!strcmp (mono_ex->object.vtable->klass->name, "ArrayTypeMismatchException")) {
1854                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1855                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1856                         char *msg = g_strdup_printf ("Source array of type '%s' cannot be cast to destination array type '%s'.", from_name, to_name);
1857                         mono_ex->message = mono_string_new_checked (domain, msg, &error);
1858                         g_free (from_name);
1859                         g_free (to_name);
1860                         if (!is_ok (&error)) {
1861                                 mono_runtime_printf_err ("Error creating array type mismatch exception message '%s'\n", msg);
1862                                 mono_error_assert_ok (&error);
1863                         }
1864                         g_free (msg);
1865                 }
1866         }
1867
1868         if (!call_filter)
1869                 call_filter = (int (*)(MonoContext *, void*))mono_get_call_filter ();
1870
1871         g_assert (jit_tls->end_of_stack);
1872         g_assert (jit_tls->abort_func);
1873
1874         /*
1875          * We set orig_ex_ctx_set to TRUE/FALSE around profiler calls to make sure it doesn't
1876          * end up being TRUE on any code path.
1877          */
1878         memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
1879
1880         if (!resume) {
1881                 gboolean res;
1882
1883                 MonoContext ctx_cp = *ctx;
1884                 if (mono_trace_is_enabled ()) {
1885                         MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
1886                         MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
1887                         MonoObject *message;
1888                         const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
1889                         char *msg = NULL;
1890                         if (get_message == NULL) {
1891                                 message = NULL;
1892                         } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
1893                                 message = NULL;
1894                                 msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
1895                         } else {
1896                                 MonoObject *exc = NULL;
1897                                 message = mono_runtime_try_invoke (get_message, obj, NULL, &exc, &error);
1898                                 g_assert (exc == NULL);
1899                                 mono_error_assert_ok (&error);
1900                         }
1901                         if (msg == NULL) {
1902                                 if (message) {
1903                                         msg = mono_string_to_utf8_checked ((MonoString *) message, &error);
1904                                         if (!is_ok (&error)) {
1905                                                 mono_error_cleanup (&error);
1906                                                 msg = g_strdup ("(error while display System.Exception.Message property)");
1907                                         }
1908                                 } else {
1909                                         msg = g_strdup ("(System.Exception.Message property not available)");
1910                                 }
1911                         }
1912                         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);
1913                         g_free (msg);
1914                         if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
1915                                 mono_print_thread_dump_from_ctx (ctx);
1916                 }
1917                 jit_tls->orig_ex_ctx_set = TRUE;
1918                 mono_profiler_exception_thrown (obj);
1919                 jit_tls->orig_ex_ctx_set = FALSE;
1920
1921                 res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
1922
1923                 if (!res) {
1924                         if (mini_get_debug_options ()->break_on_exc)
1925                                 G_BREAKPOINT ();
1926                         mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL);
1927
1928                         if (mini_get_debug_options ()->suspend_on_unhandled) {
1929                                 mono_runtime_printf_err ("Unhandled exception, suspending...");
1930                                 while (1)
1931                                         ;
1932                         }
1933
1934                         // FIXME: This runs managed code so it might cause another stack overflow when
1935                         // we are handling a stack overflow
1936                         mini_set_abort_threshold (ctx);
1937                         mono_unhandled_exception (obj);
1938                 } else {
1939                         gboolean unhandled = FALSE;
1940
1941                         /*
1942                          * The exceptions caught by the mono_runtime_invoke_checked () calls
1943                          * in the threadpool needs to be treated as unhandled (#669836).
1944                          *
1945                          * FIXME: The check below is hackish, but its hard to distinguish
1946                          * these runtime invoke calls from others in the runtime.
1947                          */
1948                         if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
1949                                 if (prev_ji && jinfo_get_method (prev_ji) == mono_defaults.threadpool_perform_wait_callback_method)
1950                                         unhandled = TRUE;
1951                         }
1952
1953                         if (unhandled)
1954                                 mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL);
1955                         else
1956                                 mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, &ctx_cp);
1957                 }
1958         }
1959
1960         if (out_ji)
1961                 *out_ji = NULL;
1962         filter_idx = 0;
1963         initial_ctx = *ctx;
1964
1965         unwinder_init (&unwinder);
1966
1967         while (1) {
1968                 MonoContext new_ctx;
1969                 guint32 free_stack;
1970                 int clause_index_start = 0;
1971                 gboolean unwind_res = TRUE;
1972                 StackFrameInfo frame;
1973                 gpointer ip;
1974                 
1975                 if (resume) {
1976                         resume = FALSE;
1977                         ji = jit_tls->resume_state.ji;
1978                         new_ctx = jit_tls->resume_state.new_ctx;
1979                         clause_index_start = jit_tls->resume_state.clause_index;
1980                         lmf = jit_tls->resume_state.lmf;
1981                         first_filter_idx = jit_tls->resume_state.first_filter_idx;
1982                         filter_idx = jit_tls->resume_state.filter_idx;
1983                         in_interp = FALSE;
1984                 } else {
1985                         unwind_res = unwinder_unwind_frame (&unwinder, domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1986                         if (!unwind_res) {
1987                                 *(mono_get_lmf_addr ()) = lmf;
1988
1989                                 jit_tls->abort_func (obj);
1990                                 g_assert_not_reached ();
1991                         }
1992                         switch (frame.type) {
1993                         case FRAME_TYPE_DEBUGGER_INVOKE:
1994                         case FRAME_TYPE_MANAGED_TO_NATIVE:
1995                         case FRAME_TYPE_TRAMPOLINE:
1996                                 *ctx = new_ctx;
1997                                 continue;
1998                         case FRAME_TYPE_INTERP_TO_MANAGED:
1999                                 continue;
2000                         case FRAME_TYPE_INTERP:
2001                         case FRAME_TYPE_MANAGED:
2002                                 break;
2003                         default:
2004                                 g_assert_not_reached ();
2005                                 break;
2006                         }
2007                         in_interp = frame.type == FRAME_TYPE_INTERP;
2008                         ji = frame.ji;
2009                 }
2010
2011                 if (in_interp)
2012                         ip = (guint16*)ji->code_start + frame.native_offset;
2013                 else
2014                         ip = MONO_CONTEXT_GET_IP (ctx);
2015
2016                 method = jinfo_get_method (ji);
2017                 frame_count ++;
2018                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
2019
2020                 if (stack_overflow) {
2021                         if (MONO_ARCH_STACK_GROWS_UP)
2022                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
2023                         else
2024                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
2025                 } else {
2026                         free_stack = 0xffffff;
2027                 }
2028                                 
2029                 for (i = clause_index_start; i < ji->num_clauses; i++) {
2030                         MonoJitExceptionInfo *ei = &ji->clauses [i];
2031                         gboolean filtered = FALSE;
2032
2033                         /* 
2034                          * During stack overflow, wait till the unwinding frees some stack
2035                          * space before running handlers/finalizers.
2036                          */
2037                         if (free_stack <= (64 * 1024))
2038                                 continue;
2039
2040                         if (is_address_protected (ji, ei, ip)) {
2041                                 /* catch block */
2042                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
2043
2044                                 /*
2045                                  * Have to unwrap RuntimeWrappedExceptions if the
2046                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
2047                                  */
2048                                 if (non_exception && !wrap_non_exception_throws (method))
2049                                         ex_obj = non_exception;
2050                                 else
2051                                         ex_obj = obj;
2052
2053                                 if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
2054 #ifndef MONO_CROSS_COMPILE
2055 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
2056                                         MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
2057 #else
2058                                         g_assert (!ji->from_llvm);
2059                                         /* store the exception object in bp + ei->exvar_offset */
2060                                         *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
2061 #endif
2062 #endif
2063                                 }
2064
2065 #ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
2066                                 if (ji->from_llvm)
2067                                         MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
2068 #endif
2069
2070                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
2071                                         /* 
2072                                          * Filter clauses should only be run in the 
2073                                          * first pass of exception handling.
2074                                          */
2075                                         filtered = (filter_idx == first_filter_idx);
2076                                         filter_idx ++;
2077                                 }
2078
2079                                 error_init (&error);
2080                                 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
2081                                      mono_object_isinst_checked (ex_obj, catch_class, &error)) || filtered) {
2082                                         /*
2083                                          * This guards against the situation that we abort a thread that is executing a finally clause
2084                                          * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
2085                                          * check for this situation here and resume interruption if we are below the guarded block.
2086                                          */
2087                                         if (G_UNLIKELY (jit_tls->handler_block_return_address)) {
2088                                                 gboolean is_outside = FALSE;
2089                                                 gpointer prot_bp = MONO_CONTEXT_GET_BP (&jit_tls->handler_block_context);
2090                                                 gpointer catch_bp = MONO_CONTEXT_GET_BP (ctx);
2091                                                 //FIXME make this stack direction aware
2092                                                 if (catch_bp > prot_bp) {
2093                                                         is_outside = TRUE;
2094                                                 } else if (catch_bp == prot_bp) {
2095                                                         /* Can be either try { try { } catch {} } finally {} or try { try { } finally {} } catch {}
2096                                                          * So we check if the catch handler_start is protected by the guarded handler protected region
2097                                                          *
2098                                                          * Assumptions:
2099                                                          *      If there is an outstanding guarded_block return address, it means the current thread must be aborted.
2100                                                          *      This is the only way to reach out the guarded block as other cases are handled by the trampoline.
2101                                                          *      There aren't any further finally/fault handler blocks down the stack over this exception.
2102                                                          *   This must be ensured by the code that installs the guard trampoline.
2103                                                          */
2104                                                         g_assert (ji == mini_jit_info_table_find (domain, (char *)MONO_CONTEXT_GET_IP (&jit_tls->handler_block_context), NULL));
2105
2106                                                         if (!is_address_protected (ji, jit_tls->handler_block, ei->handler_start)) {
2107                                                                 is_outside = TRUE;
2108                                                         }
2109                                                 }
2110                                                 if (is_outside) {
2111                                                         jit_tls->handler_block_return_address = NULL;
2112                                                         jit_tls->handler_block = NULL;
2113                                                         mono_thread_resume_interruption (TRUE); /*We ignore the exception here, it will be raised later*/
2114                                                 }
2115                                         }
2116
2117                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
2118                                                 g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
2119                                         jit_tls->orig_ex_ctx_set = TRUE;
2120                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
2121                                         jit_tls->orig_ex_ctx_set = FALSE;
2122                                         mini_set_abort_threshold (ctx);
2123
2124                                         if (in_interp) {
2125                                                 /*
2126                                                  * ctx->pc points into the interpreter, after the call which transitioned to
2127                                                  * JITted code. Store the unwind state into the
2128                                                  * interpeter state, then resume, the interpreter will unwind itself until
2129                                                  * it reaches the target frame and will continue execution from there.
2130                                                  * The resuming is kinda hackish, from the native code standpoint, it looks
2131                                                  * like the call which transitioned to JITted code has succeeded, but the
2132                                                  * return value register etc. is not set, so we have to be careful.
2133                                                  */
2134                                                 mono_interp_set_resume_state (mono_ex, &frame, ei->handler_start);
2135                                                 /* Undo the IP adjustment done by mono_arch_unwind_frame () */
2136 #if defined(TARGET_AMD64)
2137                                                 ctx->gregs [AMD64_RIP] ++;
2138 #elif defined(TARGET_ARM)
2139                                                 ctx->pc ++;
2140                                                 if (mono_arm_thumb_supported ())
2141                                                         ctx->pc |= 1;
2142 #elif defined(TARGET_ARM64)
2143                                                 ctx->pc ++;
2144 #else
2145                                                 NOT_IMPLEMENTED;
2146 #endif
2147                                         } else {
2148                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
2149                                         }
2150                                         mono_set_lmf (lmf);
2151 #ifndef DISABLE_PERFCOUNTERS
2152                                         mono_perfcounters->exceptions_depth += frame_count;
2153 #endif
2154                                         if (obj == (MonoObject *)domain->stack_overflow_ex)
2155                                                 jit_tls->handling_stack_ovf = FALSE;
2156
2157                                         return 0;
2158                                 }
2159                                 mono_error_cleanup (&error);
2160                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
2161                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
2162                                                 g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
2163                                         jit_tls->orig_ex_ctx_set = TRUE;
2164                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
2165                                         jit_tls->orig_ex_ctx_set = FALSE;
2166                                         mini_set_abort_threshold (ctx);
2167                                         call_filter (ctx, ei->handler_start);
2168                                 }
2169                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
2170                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
2171                                                 g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
2172                                         jit_tls->orig_ex_ctx_set = TRUE;
2173                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
2174                                         jit_tls->orig_ex_ctx_set = FALSE;
2175 #ifndef DISABLE_PERFCOUNTERS
2176                                         mono_perfcounters->exceptions_finallys++;
2177 #endif
2178                                         mono_set_lmf (lmf);
2179                                         if (ji->from_llvm) {
2180                                                 /* 
2181                                                  * LLVM compiled finally handlers follow the design
2182                                                  * of the c++ ehabi, i.e. they call a resume function
2183                                                  * at the end instead of returning to the caller.
2184                                                  * So save the exception handling state,
2185                                                  * mono_resume_unwind () will call us again to continue
2186                                                  * the unwinding.
2187                                                  */
2188                                                 jit_tls->resume_state.ex_obj = obj;
2189                                                 jit_tls->resume_state.ji = ji;
2190                                                 jit_tls->resume_state.clause_index = i + 1;
2191                                                 jit_tls->resume_state.ctx = *ctx;
2192                                                 jit_tls->resume_state.new_ctx = new_ctx;
2193                                                 jit_tls->resume_state.lmf = lmf;
2194                                                 jit_tls->resume_state.first_filter_idx = first_filter_idx;
2195                                                 jit_tls->resume_state.filter_idx = filter_idx;
2196                                                 mini_set_abort_threshold (ctx);
2197                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
2198                                                 return 0;
2199                                         } else {
2200                                                 mini_set_abort_threshold (ctx);
2201                                                 if (in_interp)
2202                                                         mono_interp_run_finally (&frame, i, ei->handler_start);
2203                                                 else
2204                                                         call_filter (ctx, ei->handler_start);
2205                                         }
2206                                 }
2207                         }
2208                 }
2209
2210                 jit_tls->orig_ex_ctx_set = TRUE;
2211                 mono_profiler_exception_method_leave (method);
2212                 jit_tls->orig_ex_ctx_set = FALSE;
2213
2214                 *ctx = new_ctx;
2215         }
2216
2217         g_assert_not_reached ();
2218 }
2219
2220 /**
2221  * mono_debugger_run_finally:
2222  * \param start_ctx saved processor state
2223  * This method is called by the Mono Debugger to call all \c finally clauses of the
2224  * current stack frame.  It's used when the user issues a \c return command to make
2225  * the current stack frame return.  After returning from this method, the debugger
2226  * unwinds the stack one frame and gives control back to the user.
2227  * NOTE: This method is only used when running inside the Mono Debugger.
2228  */
2229 void
2230 mono_debugger_run_finally (MonoContext *start_ctx)
2231 {
2232         static int (*call_filter) (MonoContext *, gpointer) = NULL;
2233         MonoDomain *domain = mono_domain_get ();
2234         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2235         MonoLMF *lmf = mono_get_lmf ();
2236         MonoContext ctx, new_ctx;
2237         MonoJitInfo *ji, rji;
2238         int i;
2239
2240         ctx = *start_ctx;
2241
2242         ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
2243         if (!ji || ji == (gpointer)-1)
2244                 return;
2245
2246         if (!call_filter)
2247                 call_filter = (int (*)(MonoContext *, void *))mono_get_call_filter ();
2248
2249         for (i = 0; i < ji->num_clauses; i++) {
2250                 MonoJitExceptionInfo *ei = &ji->clauses [i];
2251
2252                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
2253                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
2254                         call_filter (&ctx, ei->handler_start);
2255                 }
2256         }
2257 }
2258
2259 /**
2260  * mono_handle_exception:
2261  * \param ctx saved processor state
2262  * \param obj the exception object
2263  */
2264 gboolean
2265 mono_handle_exception (MonoContext *ctx, MonoObject *obj)
2266 {
2267         MONO_REQ_GC_UNSAFE_MODE;
2268
2269 #ifndef DISABLE_PERFCOUNTERS
2270         mono_perfcounters->exceptions_thrown++;
2271 #endif
2272
2273         return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
2274 }
2275
2276 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2277
2278 #ifndef MONO_ARCH_USE_SIGACTION
2279 #error "Can't use sigaltstack without sigaction"
2280 #endif
2281
2282 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
2283
2284 void
2285 mono_setup_altstack (MonoJitTlsData *tls)
2286 {
2287         size_t stsize = 0;
2288         stack_t sa;
2289         guint8 *staddr = NULL;
2290
2291         if (mono_running_on_valgrind ())
2292                 return;
2293
2294         mono_thread_info_get_stack_bounds (&staddr, &stsize);
2295
2296         g_assert (staddr);
2297
2298         tls->end_of_stack = staddr + stsize;
2299         tls->stack_size = stsize;
2300
2301         /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
2302
2303         tls->stack_ovf_guard_base = staddr + mono_pagesize ();
2304         tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
2305
2306         g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
2307
2308         if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
2309                 /* mprotect can fail for the main thread stack */
2310                 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);
2311                 g_assert (gaddr == tls->stack_ovf_guard_base);
2312                 tls->stack_ovf_valloced = TRUE;
2313         }
2314
2315         /* Setup an alternate signal stack */
2316         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);
2317         tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2318
2319         g_assert (tls->signal_stack);
2320
2321         sa.ss_sp = tls->signal_stack;
2322         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2323         sa.ss_flags = 0;
2324         g_assert (sigaltstack (&sa, NULL) == 0);
2325
2326         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);
2327 }
2328
2329 void
2330 mono_free_altstack (MonoJitTlsData *tls)
2331 {
2332         stack_t sa;
2333         int err;
2334
2335         sa.ss_sp = tls->signal_stack;
2336         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2337         sa.ss_flags = SS_DISABLE;
2338         err = sigaltstack  (&sa, NULL);
2339         g_assert (err == 0);
2340
2341         if (tls->signal_stack)
2342                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MEM_ACCOUNT_EXCEPTIONS);
2343         if (tls->stack_ovf_valloced)
2344                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MEM_ACCOUNT_EXCEPTIONS);
2345         else
2346                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
2347 }
2348
2349 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2350
2351 void
2352 mono_setup_altstack (MonoJitTlsData *tls)
2353 {
2354 }
2355
2356 void
2357 mono_free_altstack (MonoJitTlsData *tls)
2358 {
2359 }
2360
2361 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2362
2363 static gboolean
2364 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
2365 {
2366         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
2367         /* we need to leave some room for throwing the exception */
2368         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
2369                 unprotect_size -= mono_pagesize ();
2370         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
2371          * is sufficient stack
2372          */
2373         //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);
2374         if (unprotect_size)
2375                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
2376         return unprotect_size == jit_tls->stack_ovf_guard_size;
2377 }
2378
2379 static G_GNUC_UNUSED void
2380 try_more_restore (void)
2381 {
2382         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2383         if (try_restore_stack_protection (jit_tls, 500))
2384                 jit_tls->restore_stack_prot = NULL;
2385 }
2386
2387 static G_GNUC_UNUSED void
2388 restore_stack_protection (void)
2389 {
2390         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2391         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
2392         /* if we can't restore the stack protection, keep a callback installed so
2393          * we'll try to restore as much stack as we can at each return from unmanaged
2394          * code.
2395          */
2396         if (try_restore_stack_protection (jit_tls, 4096))
2397                 jit_tls->restore_stack_prot = NULL;
2398         else
2399                 jit_tls->restore_stack_prot = try_more_restore_tramp;
2400         /* here we also throw a stack overflow exception */
2401         ex->trace_ips = NULL;
2402         ex->stack_trace = NULL;
2403         mono_raise_exception (ex);
2404 }
2405
2406 gpointer
2407 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
2408 {
2409         MONO_REQ_GC_UNSAFE_MODE;
2410
2411         void (*func)(void) = (void (*)(void))tramp_data;
2412         func ();
2413         return NULL;
2414 }
2415
2416 gboolean
2417 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr)
2418 {
2419         if (mono_llvm_only)
2420                 return FALSE;
2421
2422         /* we got a stack overflow in the soft-guard pages
2423          * There are two cases:
2424          * 1) managed code caused the overflow: we unprotect the soft-guard page
2425          * and let the arch-specific code trigger the exception handling mechanism
2426          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
2427          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
2428          * and hope we can continue with those enabled, at least until the hard-guard page
2429          * is hit. The alternative to continuing here is to just print a message and abort.
2430          * We may add in the future the code to protect the pages again in the codepath
2431          * when we return from unmanaged to managed code.
2432          */
2433         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2434                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2435                 /* we unprotect the minimum amount we can */
2436                 guint32 guard_size;
2437                 gboolean handled = FALSE;
2438
2439                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2440                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2441                         guard_size -= mono_pagesize ();
2442                 }
2443                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2444                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2445                 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);
2446 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2447                 if (ji) {
2448                         mono_arch_handle_altstack_exception (ctx, siginfo, fault_addr, TRUE);
2449                         handled = TRUE;
2450                 }
2451 #endif
2452                 if (!handled) {
2453                         /* We print a message: after this even managed stack overflows
2454                          * may crash the runtime
2455                          */
2456                         mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2457                         if (!jit_tls->handling_stack_ovf) {
2458                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2459                                 jit_tls->handling_stack_ovf = 1;
2460                         } else {
2461                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2462                         }
2463                 }
2464                 return TRUE;
2465         }
2466         return FALSE;
2467 }
2468
2469 typedef struct {
2470         MonoMethod *omethod;
2471         int count;
2472 } PrintOverflowUserData;
2473
2474 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2475 static gboolean
2476 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2477 {
2478         MonoMethod *method = NULL;
2479         PrintOverflowUserData *user_data = (PrintOverflowUserData *)data;
2480         gchar *location;
2481
2482         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2483                 method = jinfo_get_method (frame->ji);
2484
2485         if (method) {
2486                 if (user_data->count == 0) {
2487                         /* The first frame is in its prolog, so a line number cannot be computed */
2488                         user_data->count ++;
2489                         return FALSE;
2490                 }
2491
2492                 /* If this is a one method overflow, skip the other instances */
2493                 if (method == user_data->omethod)
2494                         return FALSE;
2495
2496                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2497                 mono_runtime_printf_err ("  %s", location);
2498                 g_free (location);
2499
2500                 if (user_data->count == 1) {
2501                         mono_runtime_printf_err ("  <...>");
2502                         user_data->omethod = method;
2503                 } else {
2504                         user_data->omethod = NULL;
2505                 }
2506
2507                 user_data->count ++;
2508         } else
2509                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2510
2511         return FALSE;
2512 }
2513 #endif
2514
2515 void
2516 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2517 {
2518 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2519         PrintOverflowUserData ud;
2520         MonoContext mctx;
2521 #endif
2522
2523         /* we don't do much now, but we can warn the user with a useful message */
2524         mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2525
2526 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2527         mono_sigctx_to_monoctx (ctx, &mctx);
2528                         
2529         mono_runtime_printf_err ("Stacktrace:");
2530
2531         memset (&ud, 0, sizeof (ud));
2532
2533         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2534 #else
2535         if (ji && !ji->is_trampoline && jinfo_get_method (ji))
2536                 mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
2537         else
2538                 mono_runtime_printf_err ("At <unmanaged>.");
2539 #endif
2540
2541         _exit (1);
2542 }
2543
2544 static gboolean
2545 print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2546 {
2547         MonoMethod *method = NULL;
2548
2549         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2550                 method = jinfo_get_method (frame->ji);
2551
2552         if (method) {
2553                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2554                 mono_runtime_printf_err ("  %s", location);
2555                 g_free (location);
2556         } else
2557                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2558
2559         return FALSE;
2560 }
2561
2562 static G_GNUC_UNUSED gboolean
2563 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2564 {
2565         GString *p = (GString*)data;
2566         MonoMethod *method = NULL;
2567
2568         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2569                 method = jinfo_get_method (frame->ji);
2570
2571         if (method && frame->domain) {
2572                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
2573                 g_string_append_printf (p, "  %s\n", location);
2574                 g_free (location);
2575         } else
2576                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2577
2578         return FALSE;
2579 }
2580
2581 #ifndef MONO_CROSS_COMPILE
2582
2583 static void print_process_map (void)
2584 {
2585 #ifdef __linux__
2586         FILE *fp = fopen ("/proc/self/maps", "r");
2587         char line [256];
2588
2589         if (fp == NULL) {
2590                 mono_runtime_printf_err ("no /proc/self/maps, not on linux?\n");
2591                 return;
2592         }
2593
2594         mono_runtime_printf_err ("/proc/self/maps:");
2595
2596         while (fgets (line, sizeof (line), fp)) {
2597                 // strip newline
2598                 size_t len = strlen (line) - 1;
2599                 if (len >= 0 && line [len] == '\n')
2600                         line [len] = '\0';
2601
2602                 mono_runtime_printf_err ("%s", line);
2603         }
2604
2605         fclose (fp);
2606 #else
2607         /* do nothing */
2608 #endif
2609 }
2610
2611 static gboolean handling_sigsegv = FALSE;
2612
2613 /*
2614  * mono_handle_native_crash:
2615  *
2616  *   Handle a native crash (e.g. SIGSEGV) while in native code by
2617  *   printing diagnostic information and aborting.
2618  */
2619 void
2620 mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2621 {
2622 #ifdef MONO_ARCH_USE_SIGACTION
2623         struct sigaction sa;
2624 #endif
2625         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2626
2627         gboolean is_sigsegv = !strcmp ("SIGSEGV", signal);
2628
2629         if (handling_sigsegv && is_sigsegv)
2630                 return;
2631
2632         if (mini_get_debug_options ()->suspend_on_native_crash) {
2633                 mono_runtime_printf_err ("Received %s, suspending...", signal);
2634 #ifdef HOST_WIN32
2635                 while (1)
2636                         ;
2637 #else
2638                 while (1) {
2639                         sleep (1);
2640                 }
2641 #endif
2642         }
2643
2644         /* To prevent infinite loops when the stack walk causes a crash */
2645         if (is_sigsegv)
2646                 handling_sigsegv = TRUE;
2647
2648         /* !jit_tls means the thread was not registered with the runtime */
2649         if (jit_tls && mono_thread_internal_current ()) {
2650                 mono_runtime_printf_err ("Stacktrace:\n");
2651
2652                 /* FIXME: Is MONO_UNWIND_LOOKUP_IL_OFFSET correct here? */
2653                 mono_walk_stack (print_stack_frame_to_stderr, MONO_UNWIND_LOOKUP_IL_OFFSET, NULL);
2654         }
2655
2656         print_process_map ();
2657
2658 #ifdef HAVE_BACKTRACE_SYMBOLS
2659  {
2660         void *array [256];
2661         char **names;
2662         int i, size;
2663
2664         mono_runtime_printf_err ("\nNative stacktrace:\n");
2665
2666         size = backtrace (array, 256);
2667         names = backtrace_symbols (array, size);
2668         for (i =0; i < size; ++i) {
2669                 mono_runtime_printf_err ("\t%s", names [i]);
2670         }
2671         g_free (names);
2672
2673         /* Try to get more meaningful information using gdb */
2674
2675 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2676         if (!mini_get_debug_options ()->no_gdb_backtrace) {
2677                 /* From g_spawn_command_line_sync () in eglib */
2678                 pid_t pid;
2679                 int status;
2680                 pid_t crashed_pid = getpid ();
2681
2682                 /*
2683                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2684                  * it will deadlock. Call the syscall directly instead.
2685                  */
2686 #if defined(PLATFORM_ANDROID)
2687                 /* SYS_fork is defined to be __NR_fork which is not defined in some ndk versions */
2688                 g_assert_not_reached ();
2689 #elif !defined(PLATFORM_MACOSX) && defined(SYS_fork)
2690                 pid = (pid_t) syscall (SYS_fork);
2691 #elif defined(PLATFORM_MACOSX) && HAVE_FORK
2692                 pid = (pid_t) fork ();
2693 #else
2694                 g_assert_not_reached ();
2695 #endif
2696
2697 #if defined (HAVE_PRCTL) && defined(PR_SET_PTRACER)
2698                 if (pid > 0) {
2699                         // Allow gdb to attach to the process even if ptrace_scope sysctl variable is set to
2700                         // a value other than 0 (the most permissive ptrace scope). Most modern Linux
2701                         // distributions set the scope to 1 which allows attaching only to direct children of
2702                         // the current process
2703                         prctl (PR_SET_PTRACER, pid, 0, 0, 0);
2704                 }
2705 #endif
2706                 if (pid == 0) {
2707                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2708
2709                         mono_gdb_render_native_backtraces (crashed_pid);
2710                         exit (1);
2711                 }
2712
2713                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2714                 waitpid (pid, &status, 0);
2715         }
2716 #endif
2717  }
2718 #else
2719 #ifdef PLATFORM_ANDROID
2720         /* set DUMPABLE for this process so debuggerd can attach with ptrace(2), see:
2721          * https://android.googlesource.com/platform/bionic/+/151da681000c07da3c24cd30a3279b1ca017f452/linker/debugger.cpp#206
2722          * this has changed on later versions of Android.  Also, we don't want to
2723          * set this on start-up as DUMPABLE has security implications. */
2724         prctl (PR_SET_DUMPABLE, 1);
2725
2726         mono_runtime_printf_err ("\nNo native Android stacktrace (see debuggerd output).\n");
2727 #endif
2728 #endif
2729
2730         /*
2731          * A SIGSEGV indicates something went very wrong so we can no longer depend
2732          * on anything working. So try to print out lots of diagnostics, starting 
2733          * with ones which have a greater chance of working.
2734          */
2735         mono_runtime_printf_err (
2736                          "\n"
2737                          "=================================================================\n"
2738                          "Got a %s while executing native code. This usually indicates\n"
2739                          "a fatal error in the mono runtime or one of the native libraries \n"
2740                          "used by your application.\n"
2741                          "=================================================================\n",
2742                         signal);
2743
2744 #ifdef MONO_ARCH_USE_SIGACTION
2745         sa.sa_handler = SIG_DFL;
2746         sigemptyset (&sa.sa_mask);
2747         sa.sa_flags = 0;
2748
2749         /* Remove our SIGABRT handler */
2750         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2751
2752         /* On some systems we get a SIGILL when calling abort (), because it might
2753          * fail to raise SIGABRT */
2754         g_assert (sigaction (SIGILL, &sa, NULL) != -1);
2755 #endif
2756
2757         if (!mono_do_crash_chaining) {
2758                 /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2759 #if defined (PLATFORM_ANDROID)
2760                 exit (-1);
2761 #else
2762                 abort ();
2763 #endif
2764         }
2765 }
2766
2767 #else
2768
2769 void
2770 mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2771 {
2772         g_assert_not_reached ();
2773 }
2774
2775 #endif /* !MONO_CROSS_COMPILE */
2776
2777 static void
2778 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2779 {
2780         MonoInternalThread *thread = mono_thread_internal_current ();
2781 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2782         MonoContext ctx;
2783 #endif
2784         GString* text;
2785         char *name;
2786         GError *error = NULL;
2787
2788         if (!thread)
2789                 return;
2790
2791         text = g_string_new (0);
2792         if (thread->name) {
2793                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2794                 g_assert (!error);
2795                 g_string_append_printf (text, "\n\"%s\"", name);
2796                 g_free (name);
2797         }
2798         else if (thread->threadpool_thread)
2799                 g_string_append (text, "\n\"<threadpool thread>\"");
2800         else
2801                 g_string_append (text, "\n\"<unnamed thread>\"");
2802
2803         g_string_append_printf (text, " tid=0x%p this=0x%p ", (gpointer)(gsize)thread->tid, thread);
2804         mono_thread_internal_describe (thread, text);
2805         g_string_append (text, "\n");
2806
2807 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2808         if (start_ctx) {
2809                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2810         } else if (!sigctx)
2811                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2812         else
2813                 mono_sigctx_to_monoctx (sigctx, &ctx);
2814
2815         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2816 #else
2817         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2818 #endif
2819
2820         mono_runtime_printf ("%s", text->str);
2821
2822 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2823         OutputDebugStringA(text->str);
2824 #endif
2825
2826         g_string_free (text, TRUE);
2827         mono_runtime_stdout_fflush ();
2828 }
2829
2830 /**
2831  * mono_print_thread_dump:
2832  *
2833  * Print information about the current thread to stdout.
2834  * \p sigctx can be NULL, allowing this to be called from gdb.
2835  */
2836 void
2837 mono_print_thread_dump (void *sigctx)
2838 {
2839         mono_print_thread_dump_internal (sigctx, NULL);
2840 }
2841
2842 void
2843 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2844 {
2845         mono_print_thread_dump_internal (NULL, ctx);
2846 }
2847
2848 /*
2849  * mono_resume_unwind:
2850  *
2851  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2852  * unwinding.
2853  */
2854 void
2855 mono_resume_unwind (MonoContext *ctx)
2856 {
2857         MONO_REQ_GC_UNSAFE_MODE;
2858
2859         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2860         MonoContext new_ctx;
2861
2862         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2863         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2864         new_ctx = *ctx;
2865
2866         mono_handle_exception_internal (&new_ctx, (MonoObject *)jit_tls->resume_state.ex_obj, TRUE, NULL);
2867
2868         mono_restore_context (&new_ctx);
2869 }
2870
2871 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2872
2873 typedef struct {
2874         MonoJitInfo *ji;
2875         MonoContext ctx;
2876         MonoJitExceptionInfo *ei;
2877 } FindHandlerBlockData;
2878
2879 static gboolean
2880 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2881 {
2882         int i;
2883         gpointer ip;
2884         FindHandlerBlockData *pdata = (FindHandlerBlockData *)data;
2885         MonoJitInfo *ji = frame->ji;
2886
2887         if (!ji)
2888                 return FALSE;
2889
2890         ip = MONO_CONTEXT_GET_IP (ctx);
2891
2892         for (i = 0; i < ji->num_clauses; ++i) {
2893                 MonoJitExceptionInfo *ei = ji->clauses + i;
2894                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2895                         continue;
2896                 /*If ip points to the first instruction it means the handler block didn't start
2897                  so we can leave its execution to the EH machinery*/
2898                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2899                         pdata->ji = ji;
2900                         pdata->ei = ei;
2901                         pdata->ctx = *ctx;
2902                         break;
2903                 }
2904         }
2905         return FALSE;
2906 }
2907
2908
2909 static gpointer
2910 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2911 {
2912         int i;
2913         MonoJitExceptionInfo *clause = NULL;
2914         gpointer ip;
2915
2916         ip = MONO_CONTEXT_GET_IP (ctx);
2917
2918         for (i = 0; i < ji->num_clauses; ++i) {
2919                 clause = &ji->clauses [i];
2920                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2921                         continue;
2922                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2923                         break;
2924         }
2925
2926         /*no matching finally */
2927         if (i == ji->num_clauses)
2928                 return NULL;
2929
2930         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2931         if (ip == clause->handler_start)
2932                 return NULL;
2933
2934         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2935 }
2936
2937 /*
2938  * Finds the bottom handler block running and install a block guard if needed.
2939  */
2940 gboolean
2941 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2942 {
2943         FindHandlerBlockData data = { 0 };
2944         MonoJitTlsData *jit_tls = (MonoJitTlsData *)ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2945         gpointer resume_ip;
2946
2947 #ifndef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT
2948         if (mono_aot_only)
2949                 return FALSE;
2950 #endif
2951
2952         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2953          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2954          */
2955         if (!jit_tls || jit_tls->handler_block_return_address)
2956                 return FALSE;
2957
2958         /* Do an async safe stack walk */
2959         mono_thread_info_set_is_async_context (TRUE);
2960         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data);
2961         mono_thread_info_set_is_async_context (FALSE);
2962
2963         if (!data.ji)
2964                 return FALSE;
2965
2966         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2967
2968         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2969         if (resume_ip == NULL)
2970                 return FALSE;
2971
2972         jit_tls->handler_block_return_address = resume_ip;
2973         jit_tls->handler_block = data.ei;
2974
2975         return TRUE;
2976 }
2977
2978 static gboolean
2979 mono_current_thread_has_handle_block_guard (void)
2980 {
2981         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2982         return jit_tls && jit_tls->handler_block_return_address != NULL;
2983 }
2984
2985 #else
2986 gboolean
2987 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2988 {
2989         return FALSE;
2990 }
2991
2992 static gboolean
2993 mono_current_thread_has_handle_block_guard (void)
2994 {
2995         return FALSE;
2996 }
2997
2998 #endif
2999
3000 void
3001 mono_set_cast_details (MonoClass *from, MonoClass *to)
3002 {
3003         MonoJitTlsData *jit_tls = NULL;
3004
3005         if (mini_get_debug_options ()->better_cast_details) {
3006                 jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
3007                 jit_tls->class_cast_from = from;
3008                 jit_tls->class_cast_to = to;
3009         }
3010 }
3011
3012
3013 /*returns false if the thread is not attached*/
3014 gboolean
3015 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
3016 {
3017 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
3018         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
3019         if (!thread) {
3020                 ctx->valid = FALSE;
3021                 return FALSE;
3022         }
3023
3024         if (sigctx) {
3025                 mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
3026
3027                 ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
3028                 ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
3029                 ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
3030         }
3031         else {
3032                 mono_thread_state_init (ctx);
3033         }
3034
3035         if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF])
3036                 return FALSE;
3037
3038         ctx->valid = TRUE;
3039         return TRUE;
3040 #else
3041         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
3042         return FALSE;
3043 #endif
3044 }
3045
3046 void
3047 mono_thread_state_init (MonoThreadUnwindState *ctx)
3048 {
3049         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
3050
3051 #if defined(MONO_CROSS_COMPILE)
3052         ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
3053 #elif MONO_ARCH_HAS_MONO_CONTEXT
3054         MONO_CONTEXT_GET_CURRENT (ctx->ctx);
3055 #else
3056         g_error ("Use a null sigctx requires a working mono-context");
3057 #endif
3058
3059         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
3060         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
3061         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
3062         ctx->valid = TRUE;
3063 }
3064
3065
3066 gboolean
3067 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
3068 {
3069         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
3070         if (!thread) {
3071                 ctx->valid = FALSE;
3072                 return FALSE;
3073         }
3074
3075         ctx->ctx = *mctx;
3076         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
3077         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
3078         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
3079         ctx->valid = TRUE;
3080         return TRUE;
3081 }
3082
3083 /*returns false if the thread is not attached*/
3084 gboolean
3085 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
3086 {
3087         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
3088         MONO_ARCH_CONTEXT_DEF
3089
3090         mono_arch_flush_register_windows ();
3091
3092         if (!thread || !thread->jit_data) {
3093                 ctx->valid = FALSE;
3094                 return FALSE;
3095         }
3096 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
3097         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
3098 #else
3099         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
3100 #endif
3101                 
3102         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
3103         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
3104         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
3105         ctx->valid = TRUE;
3106         return TRUE;
3107 }
3108
3109 static void
3110 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
3111 {
3112         mono_handle_exception (ctx, (MonoObject *)exc);
3113         mono_restore_context (ctx);
3114 }
3115
3116 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
3117 void
3118 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
3119 {
3120 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
3121         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
3122         jit_tls->ex_ctx = *ctx;
3123
3124         mono_arch_setup_async_callback (ctx, async_cb, user_data);
3125 #else
3126         g_error ("This target doesn't support mono_arch_setup_async_callback");
3127 #endif
3128 }
3129
3130 /*
3131  * mono_restore_context:
3132  *
3133  *   Call the architecture specific restore context function.
3134  */
3135 void
3136 mono_restore_context (MonoContext *ctx)
3137 {
3138         static void (*restore_context) (MonoContext *);
3139
3140         if (!restore_context)
3141                 restore_context = (void (*)(MonoContext *))mono_get_restore_context ();
3142         restore_context (ctx);
3143         g_assert_not_reached ();
3144 }
3145
3146 /*
3147  * mono_jinfo_get_unwind_info:
3148  *
3149  *   Return the unwind info for JI.
3150  */
3151 guint8*
3152 mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
3153 {
3154         if (ji->has_unwind_info) {
3155                 /* The address/length in the MonoJitInfo structure itself */
3156                 MonoUnwindJitInfo *info = mono_jit_info_get_unwind_info (ji);
3157                 *unwind_info_len = info->unw_info_len;
3158                 return info->unw_info;
3159         } else if (ji->from_aot)
3160                 return mono_aot_get_unwind_info (ji, unwind_info_len);
3161         else
3162                 return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len);
3163 }
3164
3165 int
3166 mono_jinfo_get_epilog_size (MonoJitInfo *ji)
3167 {
3168         MonoArchEHJitInfo *info;
3169
3170         info = mono_jit_info_get_arch_eh_info (ji);
3171         g_assert (info);
3172
3173         return info->epilog_size;
3174 }
3175
3176 /*
3177  * LLVM/Bitcode exception handling.
3178  */
3179
3180 static void
3181 throw_exception (MonoObject *ex, gboolean rethrow)
3182 {
3183         MONO_REQ_GC_UNSAFE_MODE;
3184
3185         MonoError error;
3186         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3187         MonoException *mono_ex;
3188
3189         if (!mono_object_isinst_checked (ex, mono_defaults.exception_class, &error)) {
3190                 mono_error_assert_ok (&error);
3191                 mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error);
3192                 mono_error_assert_ok (&error);
3193                 jit_tls->thrown_non_exc = mono_gchandle_new (ex, FALSE);
3194         }
3195         else
3196                 mono_ex = (MonoException*)ex;
3197
3198         // Note: Not pinned
3199         jit_tls->thrown_exc = mono_gchandle_new ((MonoObject*)mono_ex, FALSE);
3200
3201         if (!rethrow) {
3202 #ifdef MONO_ARCH_HAVE_UNWIND_BACKTRACE
3203                 GList *l, *ips = NULL;
3204                 GList *trace;
3205
3206                 _Unwind_Backtrace (build_stack_trace, &ips);
3207                 /* The list contains ip-gshared info pairs */
3208                 trace = NULL;
3209                 ips = g_list_reverse (ips);
3210                 for (l = ips; l; l = l->next) {
3211                         trace = g_list_append (trace, l->data);
3212                         trace = g_list_append (trace, NULL);
3213                 }
3214                 MonoArray *ips_arr = mono_glist_to_array (trace, mono_defaults.int_class, &error);
3215                 mono_error_assert_ok (&error);
3216                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
3217                 g_list_free (l);
3218                 g_list_free (trace);
3219 #endif
3220         }
3221
3222         mono_llvm_cpp_throw_exception ();
3223 }
3224
3225 void
3226 mono_llvm_throw_exception (MonoObject *ex)
3227 {
3228         throw_exception (ex, FALSE);
3229 }
3230
3231 void
3232 mono_llvm_rethrow_exception (MonoObject *ex)
3233 {
3234         throw_exception (ex, TRUE);
3235 }
3236
3237 void
3238 mono_llvm_raise_exception (MonoException *e)
3239 {
3240         mono_llvm_throw_exception ((MonoObject*)e);
3241 }
3242
3243 void
3244 mono_llvm_throw_corlib_exception (guint32 ex_token_index)
3245 {
3246         guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
3247         MonoException *ex;
3248
3249         ex = mono_exception_from_token (mono_defaults.exception_class->image, ex_token);
3250
3251         mono_llvm_throw_exception ((MonoObject*)ex);
3252 }
3253
3254 /*
3255  * mono_llvm_resume_exception:
3256  *
3257  *   Resume exception propagation.
3258  */
3259 void
3260 mono_llvm_resume_exception (void)
3261 {
3262         mono_llvm_cpp_throw_exception ();
3263 }
3264
3265 /*
3266  * mono_llvm_load_exception:
3267  *
3268  *   Return the currently thrown exception.
3269  */
3270 MonoObject *
3271 mono_llvm_load_exception (void)
3272 {
3273         MonoError error;
3274         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3275
3276         MonoException *mono_ex = (MonoException*)mono_gchandle_get_target (jit_tls->thrown_exc);
3277
3278         if (mono_ex->trace_ips) {
3279                 GList *trace_ips = NULL;
3280                 gpointer ip = __builtin_return_address (0);
3281
3282                 size_t upper = mono_array_length (mono_ex->trace_ips);
3283
3284                 for (int i = 0; i < upper; i+= 2) {
3285                         gpointer curr_ip = mono_array_get (mono_ex->trace_ips, gpointer, i);
3286                         gpointer curr_info = mono_array_get (mono_ex->trace_ips, gpointer, i + 1);
3287                         trace_ips = g_list_append (trace_ips, curr_ip);
3288                         trace_ips = g_list_append (trace_ips, curr_info);
3289
3290                         if (ip == curr_ip)
3291                                 break;
3292                 }
3293
3294                 // FIXME: Does this work correctly for rethrows?
3295                 // We may be discarding useful information
3296                 // when this gets GC'ed
3297                 MonoArray *ips_arr = mono_glist_to_array (trace_ips, mono_defaults.int_class, &error);
3298                 mono_error_assert_ok (&error);
3299                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
3300                 g_list_free (trace_ips);
3301
3302                 // FIXME:
3303                 //MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex));
3304         } else {
3305                 MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_array_new_checked (mono_domain_get (), mono_defaults.int_class, 0, &error));
3306                 mono_error_assert_ok (&error);
3307                 MONO_OBJECT_SETREF (mono_ex, stack_trace, mono_array_new_checked (mono_domain_get (), mono_defaults.stack_frame_class, 0, &error));
3308                 mono_error_assert_ok (&error);
3309         }
3310
3311         return &mono_ex->object;
3312 }
3313
3314 /*
3315  * mono_llvm_clear_exception:
3316  *
3317  *   Mark the currently thrown exception as handled.
3318  */
3319 void
3320 mono_llvm_clear_exception (void)
3321 {
3322         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3323         mono_gchandle_free (jit_tls->thrown_exc);
3324         jit_tls->thrown_exc = 0;
3325         if (jit_tls->thrown_non_exc)
3326                 mono_gchandle_free (jit_tls->thrown_non_exc);
3327         jit_tls->thrown_non_exc = 0;
3328
3329         mono_memory_barrier ();
3330 }
3331
3332 /*
3333  * mono_llvm_match_exception:
3334  *
3335  *   Return the innermost clause containing REGION_START-REGION_END which can handle
3336  * the current exception.
3337  */
3338 gint32
3339 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj)
3340 {
3341         MonoError error;
3342         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3343         MonoObject *exc;
3344         gint32 index = -1;
3345
3346         g_assert (jit_tls->thrown_exc);
3347         exc = mono_gchandle_get_target (jit_tls->thrown_exc);
3348         if (jit_tls->thrown_non_exc) {
3349                 /*
3350                  * Have to unwrap RuntimeWrappedExceptions if the
3351                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
3352                  */
3353                 if (!wrap_non_exception_throws (jinfo_get_method (jinfo)))
3354                         exc = mono_gchandle_get_target (jit_tls->thrown_non_exc);
3355         }
3356
3357         for (int i = 0; i < jinfo->num_clauses; i++) {
3358                 MonoJitExceptionInfo *ei = &jinfo->clauses [i];
3359                 MonoClass *catch_class;
3360
3361                 if (! (ei->try_offset == region_start && ei->try_offset + ei->try_len == region_end) )
3362                         continue;
3363
3364                 catch_class = ei->data.catch_class;
3365                 if (mono_class_is_open_constructed_type (&catch_class->byval_arg)) {
3366                         MonoGenericContext context;
3367                         MonoType *inflated_type;
3368
3369                         g_assert (rgctx || this_obj);
3370                         context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
3371                         inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
3372                         mono_error_assert_ok (&error); /* FIXME don't swallow the error */
3373
3374                         catch_class = mono_class_from_mono_type (inflated_type);
3375                         mono_metadata_free_type (inflated_type);
3376                 }
3377
3378                 // FIXME: Handle edge cases handled in get_exception_catch_class
3379                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (exc, catch_class, &error)) {
3380                         index = ei->clause_index;
3381                         break;
3382                 } else
3383                         mono_error_assert_ok (&error);
3384                 
3385                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3386                         g_assert_not_reached ();
3387                 }
3388         }
3389
3390         return index;
3391 }
3392
3393 #ifdef ENABLE_LLVM
3394 _Unwind_Reason_Code 
3395 mono_debug_personality (int a, _Unwind_Action b,
3396 uint64_t c, struct _Unwind_Exception *d, struct _Unwind_Context *e)
3397 {
3398         g_assert_not_reached ();
3399 }
3400 #else
3401 void
3402 mono_debug_personality (void);
3403
3404 void
3405 mono_debug_personality (void)
3406 {
3407         g_assert_not_reached ();
3408 }
3409 #endif
3410
3411 #ifndef ENABLE_INTERPRETER
3412 /* Stubs of interpreter functions */
3413 void
3414 mono_interp_set_resume_state (MonoException *ex, StackFrameInfo *frame, gpointer handler_ip)
3415 {
3416         g_assert_not_reached ();
3417 }
3418
3419 void
3420 mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip)
3421 {
3422         g_assert_not_reached ();
3423 }
3424
3425 void
3426 mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_data)
3427 {
3428         g_assert_not_reached ();
3429 }
3430
3431 gboolean
3432 mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame)
3433 {
3434         g_assert_not_reached ();
3435         return FALSE;
3436 }
3437 #endif