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