d73c4c8e462dd16dfa9dca540fe95066f2823734
[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                                         mini_set_abort_threshold (ctx);
2190                                         call_filter (ctx, ei->handler_start);
2191                                 }
2192                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
2193                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
2194                                                 g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
2195                                         jit_tls->orig_ex_ctx_set = TRUE;
2196                                         MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
2197                                         jit_tls->orig_ex_ctx_set = FALSE;
2198 #ifndef DISABLE_PERFCOUNTERS
2199                                         mono_perfcounters->exceptions_finallys++;
2200 #endif
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                 jit_tls->orig_ex_ctx_set = TRUE;
2234                 MONO_PROFILER_RAISE (method_exception_leave, (method, ex_obj));
2235                 jit_tls->orig_ex_ctx_set = FALSE;
2236
2237                 *ctx = new_ctx;
2238         }
2239
2240         g_assert_not_reached ();
2241 }
2242
2243 /**
2244  * mono_debugger_run_finally:
2245  * \param start_ctx saved processor state
2246  * This method is called by the Mono Debugger to call all \c finally clauses of the
2247  * current stack frame.  It's used when the user issues a \c return command to make
2248  * the current stack frame return.  After returning from this method, the debugger
2249  * unwinds the stack one frame and gives control back to the user.
2250  * NOTE: This method is only used when running inside the Mono Debugger.
2251  */
2252 void
2253 mono_debugger_run_finally (MonoContext *start_ctx)
2254 {
2255         static int (*call_filter) (MonoContext *, gpointer) = NULL;
2256         MonoDomain *domain = mono_domain_get ();
2257         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2258         MonoLMF *lmf = mono_get_lmf ();
2259         MonoContext ctx, new_ctx;
2260         MonoJitInfo *ji, rji;
2261         int i;
2262
2263         ctx = *start_ctx;
2264
2265         ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
2266         if (!ji || ji == (gpointer)-1)
2267                 return;
2268
2269         if (!call_filter)
2270                 call_filter = (int (*)(MonoContext *, void *))mono_get_call_filter ();
2271
2272         for (i = 0; i < ji->num_clauses; i++) {
2273                 MonoJitExceptionInfo *ei = &ji->clauses [i];
2274
2275                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
2276                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
2277                         call_filter (&ctx, ei->handler_start);
2278                 }
2279         }
2280 }
2281
2282 /**
2283  * mono_handle_exception:
2284  * \param ctx saved processor state
2285  * \param obj the exception object
2286  *
2287  *   Handle the exception OBJ starting from the state CTX. Modify CTX to point to the handler clause if the exception is caught, and
2288  * return TRUE.
2289  */
2290 gboolean
2291 mono_handle_exception (MonoContext *ctx, MonoObject *obj)
2292 {
2293         MONO_REQ_GC_UNSAFE_MODE;
2294
2295 #ifndef DISABLE_PERFCOUNTERS
2296         mono_perfcounters->exceptions_thrown++;
2297 #endif
2298
2299         return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
2300 }
2301
2302 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2303
2304 #ifndef MONO_ARCH_USE_SIGACTION
2305 #error "Can't use sigaltstack without sigaction"
2306 #endif
2307
2308 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
2309
2310 void
2311 mono_setup_altstack (MonoJitTlsData *tls)
2312 {
2313         size_t stsize = 0;
2314         stack_t sa;
2315         guint8 *staddr = NULL;
2316
2317         if (mono_running_on_valgrind ())
2318                 return;
2319
2320         mono_thread_info_get_stack_bounds (&staddr, &stsize);
2321
2322         g_assert (staddr);
2323
2324         tls->end_of_stack = staddr + stsize;
2325         tls->stack_size = stsize;
2326
2327         /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
2328
2329         tls->stack_ovf_guard_base = staddr + mono_pagesize ();
2330         tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
2331
2332         g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
2333
2334         if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
2335                 /* mprotect can fail for the main thread stack */
2336                 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);
2337                 g_assert (gaddr == tls->stack_ovf_guard_base);
2338                 tls->stack_ovf_valloced = TRUE;
2339         }
2340
2341         /* Setup an alternate signal stack */
2342         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);
2343         tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2344
2345         g_assert (tls->signal_stack);
2346
2347         sa.ss_sp = tls->signal_stack;
2348         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2349         sa.ss_flags = 0;
2350         g_assert (sigaltstack (&sa, NULL) == 0);
2351
2352         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);
2353 }
2354
2355 void
2356 mono_free_altstack (MonoJitTlsData *tls)
2357 {
2358         stack_t sa;
2359         int err;
2360
2361         sa.ss_sp = tls->signal_stack;
2362         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2363         sa.ss_flags = SS_DISABLE;
2364         err = sigaltstack  (&sa, NULL);
2365         g_assert (err == 0);
2366
2367         if (tls->signal_stack)
2368                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MEM_ACCOUNT_EXCEPTIONS);
2369         if (tls->stack_ovf_valloced)
2370                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MEM_ACCOUNT_EXCEPTIONS);
2371         else
2372                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
2373 }
2374
2375 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2376
2377 void
2378 mono_setup_altstack (MonoJitTlsData *tls)
2379 {
2380 }
2381
2382 void
2383 mono_free_altstack (MonoJitTlsData *tls)
2384 {
2385 }
2386
2387 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2388
2389 static gboolean
2390 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
2391 {
2392         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
2393         /* we need to leave some room for throwing the exception */
2394         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
2395                 unprotect_size -= mono_pagesize ();
2396         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
2397          * is sufficient stack
2398          */
2399         //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);
2400         if (unprotect_size)
2401                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
2402         return unprotect_size == jit_tls->stack_ovf_guard_size;
2403 }
2404
2405 static G_GNUC_UNUSED void
2406 try_more_restore (void)
2407 {
2408         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2409         if (try_restore_stack_protection (jit_tls, 500))
2410                 jit_tls->restore_stack_prot = NULL;
2411 }
2412
2413 static G_GNUC_UNUSED void
2414 restore_stack_protection (void)
2415 {
2416         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2417         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
2418         /* if we can't restore the stack protection, keep a callback installed so
2419          * we'll try to restore as much stack as we can at each return from unmanaged
2420          * code.
2421          */
2422         if (try_restore_stack_protection (jit_tls, 4096))
2423                 jit_tls->restore_stack_prot = NULL;
2424         else
2425                 jit_tls->restore_stack_prot = try_more_restore_tramp;
2426         /* here we also throw a stack overflow exception */
2427         ex->trace_ips = NULL;
2428         ex->stack_trace = NULL;
2429         mono_raise_exception (ex);
2430 }
2431
2432 gpointer
2433 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
2434 {
2435         MONO_REQ_GC_UNSAFE_MODE;
2436
2437         void (*func)(void) = (void (*)(void))tramp_data;
2438         func ();
2439         return NULL;
2440 }
2441
2442 gboolean
2443 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr)
2444 {
2445         if (mono_llvm_only)
2446                 return FALSE;
2447
2448         /* we got a stack overflow in the soft-guard pages
2449          * There are two cases:
2450          * 1) managed code caused the overflow: we unprotect the soft-guard page
2451          * and let the arch-specific code trigger the exception handling mechanism
2452          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
2453          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
2454          * and hope we can continue with those enabled, at least until the hard-guard page
2455          * is hit. The alternative to continuing here is to just print a message and abort.
2456          * We may add in the future the code to protect the pages again in the codepath
2457          * when we return from unmanaged to managed code.
2458          */
2459         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2460                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2461                 /* we unprotect the minimum amount we can */
2462                 guint32 guard_size;
2463                 gboolean handled = FALSE;
2464
2465                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2466                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2467                         guard_size -= mono_pagesize ();
2468                 }
2469                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2470                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2471                 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);
2472 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2473                 if (ji) {
2474                         mono_arch_handle_altstack_exception (ctx, siginfo, fault_addr, TRUE);
2475                         handled = TRUE;
2476                 }
2477 #endif
2478                 if (!handled) {
2479                         /* We print a message: after this even managed stack overflows
2480                          * may crash the runtime
2481                          */
2482                         mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2483                         if (!jit_tls->handling_stack_ovf) {
2484                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2485                                 jit_tls->handling_stack_ovf = 1;
2486                         } else {
2487                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2488                         }
2489                 }
2490                 return TRUE;
2491         }
2492         return FALSE;
2493 }
2494
2495 typedef struct {
2496         MonoMethod *omethod;
2497         int count;
2498 } PrintOverflowUserData;
2499
2500 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2501 static gboolean
2502 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2503 {
2504         MonoMethod *method = NULL;
2505         PrintOverflowUserData *user_data = (PrintOverflowUserData *)data;
2506         gchar *location;
2507
2508         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2509                 method = jinfo_get_method (frame->ji);
2510
2511         if (method) {
2512                 if (user_data->count == 0) {
2513                         /* The first frame is in its prolog, so a line number cannot be computed */
2514                         user_data->count ++;
2515                         return FALSE;
2516                 }
2517
2518                 /* If this is a one method overflow, skip the other instances */
2519                 if (method == user_data->omethod)
2520                         return FALSE;
2521
2522                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2523                 mono_runtime_printf_err ("  %s", location);
2524                 g_free (location);
2525
2526                 if (user_data->count == 1) {
2527                         mono_runtime_printf_err ("  <...>");
2528                         user_data->omethod = method;
2529                 } else {
2530                         user_data->omethod = NULL;
2531                 }
2532
2533                 user_data->count ++;
2534         } else
2535                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2536
2537         return FALSE;
2538 }
2539 #endif
2540
2541 void
2542 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2543 {
2544 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2545         PrintOverflowUserData ud;
2546         MonoContext mctx;
2547 #endif
2548
2549         /* we don't do much now, but we can warn the user with a useful message */
2550         mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2551
2552 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2553         mono_sigctx_to_monoctx (ctx, &mctx);
2554                         
2555         mono_runtime_printf_err ("Stacktrace:");
2556
2557         memset (&ud, 0, sizeof (ud));
2558
2559         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2560 #else
2561         if (ji && !ji->is_trampoline && jinfo_get_method (ji))
2562                 mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
2563         else
2564                 mono_runtime_printf_err ("At <unmanaged>.");
2565 #endif
2566
2567         _exit (1);
2568 }
2569
2570 static gboolean
2571 print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2572 {
2573         MonoMethod *method = NULL;
2574
2575         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2576                 method = jinfo_get_method (frame->ji);
2577
2578         if (method) {
2579                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2580                 mono_runtime_printf_err ("  %s", location);
2581                 g_free (location);
2582         } else
2583                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2584
2585         return FALSE;
2586 }
2587
2588 static G_GNUC_UNUSED gboolean
2589 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2590 {
2591         GString *p = (GString*)data;
2592         MonoMethod *method = NULL;
2593
2594         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2595                 method = jinfo_get_method (frame->ji);
2596
2597         if (method && frame->domain) {
2598                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
2599                 g_string_append_printf (p, "  %s\n", location);
2600                 g_free (location);
2601         } else
2602                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2603
2604         return FALSE;
2605 }
2606
2607 #ifndef MONO_CROSS_COMPILE
2608
2609 static void print_process_map (void)
2610 {
2611 #ifdef __linux__
2612         FILE *fp = fopen ("/proc/self/maps", "r");
2613         char line [256];
2614
2615         if (fp == NULL) {
2616                 mono_runtime_printf_err ("no /proc/self/maps, not on linux?\n");
2617                 return;
2618         }
2619
2620         mono_runtime_printf_err ("/proc/self/maps:");
2621
2622         while (fgets (line, sizeof (line), fp)) {
2623                 // strip newline
2624                 size_t len = strlen (line) - 1;
2625                 if (len >= 0 && line [len] == '\n')
2626                         line [len] = '\0';
2627
2628                 mono_runtime_printf_err ("%s", line);
2629         }
2630
2631         fclose (fp);
2632 #else
2633         /* do nothing */
2634 #endif
2635 }
2636
2637 static gboolean handle_crash_loop = FALSE;
2638
2639 /*
2640  * mono_handle_native_crash:
2641  *
2642  *   Handle a native crash (e.g. SIGSEGV) while in native code by
2643  *   printing diagnostic information and aborting.
2644  */
2645 void
2646 mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2647 {
2648 #ifdef MONO_ARCH_USE_SIGACTION
2649         struct sigaction sa;
2650 #endif
2651         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2652
2653         if (handle_crash_loop)
2654                 return;
2655
2656         if (mini_get_debug_options ()->suspend_on_native_crash) {
2657                 mono_runtime_printf_err ("Received %s, suspending...", signal);
2658 #ifdef HOST_WIN32
2659                 while (1)
2660                         ;
2661 #else
2662                 while (1) {
2663                         sleep (1);
2664                 }
2665 #endif
2666         }
2667
2668         /* prevent infinite loops in crash handling */
2669         handle_crash_loop = TRUE;
2670
2671         /* !jit_tls means the thread was not registered with the runtime */
2672         if (jit_tls && mono_thread_internal_current ()) {
2673                 mono_runtime_printf_err ("Stacktrace:\n");
2674
2675                 /* FIXME: Is MONO_UNWIND_LOOKUP_IL_OFFSET correct here? */
2676                 mono_walk_stack (print_stack_frame_to_stderr, MONO_UNWIND_LOOKUP_IL_OFFSET, NULL);
2677         }
2678
2679         print_process_map ();
2680
2681 #ifdef HAVE_BACKTRACE_SYMBOLS
2682  {
2683         void *array [256];
2684         char **names;
2685         int i, size;
2686
2687         mono_runtime_printf_err ("\nNative stacktrace:\n");
2688
2689         size = backtrace (array, 256);
2690         names = backtrace_symbols (array, size);
2691         for (i =0; i < size; ++i) {
2692                 mono_runtime_printf_err ("\t%s", names [i]);
2693         }
2694         g_free (names);
2695
2696         /* Try to get more meaningful information using gdb */
2697
2698 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2699         if (!mini_get_debug_options ()->no_gdb_backtrace) {
2700                 /* From g_spawn_command_line_sync () in eglib */
2701                 pid_t pid;
2702                 int status;
2703                 pid_t crashed_pid = getpid ();
2704
2705                 /*
2706                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2707                  * it will deadlock. Call the syscall directly instead.
2708                  */
2709 #if defined(PLATFORM_ANDROID)
2710                 /* SYS_fork is defined to be __NR_fork which is not defined in some ndk versions */
2711                 g_assert_not_reached ();
2712 #elif !defined(PLATFORM_MACOSX) && defined(SYS_fork)
2713                 pid = (pid_t) syscall (SYS_fork);
2714 #elif defined(PLATFORM_MACOSX) && HAVE_FORK
2715                 pid = (pid_t) fork ();
2716 #else
2717                 g_assert_not_reached ();
2718 #endif
2719
2720 #if defined (HAVE_PRCTL) && defined(PR_SET_PTRACER)
2721                 if (pid > 0) {
2722                         // Allow gdb to attach to the process even if ptrace_scope sysctl variable is set to
2723                         // a value other than 0 (the most permissive ptrace scope). Most modern Linux
2724                         // distributions set the scope to 1 which allows attaching only to direct children of
2725                         // the current process
2726                         prctl (PR_SET_PTRACER, pid, 0, 0, 0);
2727                 }
2728 #endif
2729                 if (pid == 0) {
2730                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2731
2732                         mono_gdb_render_native_backtraces (crashed_pid);
2733                         exit (1);
2734                 }
2735
2736                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2737                 waitpid (pid, &status, 0);
2738         }
2739 #endif
2740  }
2741 #else
2742 #ifdef PLATFORM_ANDROID
2743         /* set DUMPABLE for this process so debuggerd can attach with ptrace(2), see:
2744          * https://android.googlesource.com/platform/bionic/+/151da681000c07da3c24cd30a3279b1ca017f452/linker/debugger.cpp#206
2745          * this has changed on later versions of Android.  Also, we don't want to
2746          * set this on start-up as DUMPABLE has security implications. */
2747         prctl (PR_SET_DUMPABLE, 1);
2748
2749         mono_runtime_printf_err ("\nNo native Android stacktrace (see debuggerd output).\n");
2750 #endif
2751 #endif
2752
2753         /*
2754          * A SIGSEGV indicates something went very wrong so we can no longer depend
2755          * on anything working. So try to print out lots of diagnostics, starting 
2756          * with ones which have a greater chance of working.
2757          */
2758         mono_runtime_printf_err (
2759                          "\n"
2760                          "=================================================================\n"
2761                          "Got a %s while executing native code. This usually indicates\n"
2762                          "a fatal error in the mono runtime or one of the native libraries \n"
2763                          "used by your application.\n"
2764                          "=================================================================\n",
2765                         signal);
2766
2767 #ifdef MONO_ARCH_USE_SIGACTION
2768         sa.sa_handler = SIG_DFL;
2769         sigemptyset (&sa.sa_mask);
2770         sa.sa_flags = 0;
2771
2772         /* Remove our SIGABRT handler */
2773         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2774
2775         /* On some systems we get a SIGILL when calling abort (), because it might
2776          * fail to raise SIGABRT */
2777         g_assert (sigaction (SIGILL, &sa, NULL) != -1);
2778 #endif
2779
2780         if (!mono_do_crash_chaining) {
2781                 /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2782 #if defined (PLATFORM_ANDROID)
2783                 exit (-1);
2784 #else
2785                 abort ();
2786 #endif
2787         }
2788 }
2789
2790 #else
2791
2792 void
2793 mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2794 {
2795         g_assert_not_reached ();
2796 }
2797
2798 #endif /* !MONO_CROSS_COMPILE */
2799
2800 static void
2801 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2802 {
2803         MonoInternalThread *thread = mono_thread_internal_current ();
2804 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2805         MonoContext ctx;
2806 #endif
2807         GString* text;
2808         char *name;
2809         GError *error = NULL;
2810
2811         if (!thread)
2812                 return;
2813
2814         text = g_string_new (0);
2815         if (thread->name) {
2816                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2817                 g_assert (!error);
2818                 g_string_append_printf (text, "\n\"%s\"", name);
2819                 g_free (name);
2820         }
2821         else if (thread->threadpool_thread)
2822                 g_string_append (text, "\n\"<threadpool thread>\"");
2823         else
2824                 g_string_append (text, "\n\"<unnamed thread>\"");
2825
2826         g_string_append_printf (text, " tid=0x%p this=0x%p ", (gpointer)(gsize)thread->tid, thread);
2827         mono_thread_internal_describe (thread, text);
2828         g_string_append (text, "\n");
2829
2830 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2831         if (start_ctx) {
2832                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2833         } else if (!sigctx)
2834                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2835         else
2836                 mono_sigctx_to_monoctx (sigctx, &ctx);
2837
2838         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2839 #else
2840         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2841 #endif
2842
2843         mono_runtime_printf ("%s", text->str);
2844
2845 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2846         OutputDebugStringA(text->str);
2847 #endif
2848
2849         g_string_free (text, TRUE);
2850         mono_runtime_stdout_fflush ();
2851 }
2852
2853 /**
2854  * mono_print_thread_dump:
2855  *
2856  * Print information about the current thread to stdout.
2857  * \p sigctx can be NULL, allowing this to be called from gdb.
2858  */
2859 void
2860 mono_print_thread_dump (void *sigctx)
2861 {
2862         mono_print_thread_dump_internal (sigctx, NULL);
2863 }
2864
2865 void
2866 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2867 {
2868         mono_print_thread_dump_internal (NULL, ctx);
2869 }
2870
2871 /*
2872  * mono_resume_unwind:
2873  *
2874  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2875  * unwinding.
2876  */
2877 void
2878 mono_resume_unwind (MonoContext *ctx)
2879 {
2880         MONO_REQ_GC_UNSAFE_MODE;
2881
2882         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2883         MonoContext new_ctx;
2884
2885         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2886         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2887         new_ctx = *ctx;
2888
2889         mono_handle_exception_internal (&new_ctx, (MonoObject *)jit_tls->resume_state.ex_obj, TRUE, NULL);
2890
2891         mono_restore_context (&new_ctx);
2892 }
2893
2894 typedef struct {
2895         MonoJitInfo *ji;
2896         MonoContext ctx;
2897         MonoJitExceptionInfo *ei;
2898 } FindHandlerBlockData;
2899
2900 static gboolean
2901 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2902 {
2903         int i;
2904         gpointer ip;
2905         FindHandlerBlockData *pdata = (FindHandlerBlockData *)data;
2906         MonoJitInfo *ji = frame->ji;
2907
2908         if (!ji)
2909                 return FALSE;
2910
2911         ip = MONO_CONTEXT_GET_IP (ctx);
2912
2913         for (i = 0; i < ji->num_clauses; ++i) {
2914                 MonoJitExceptionInfo *ei = ji->clauses + i;
2915                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2916                         continue;
2917                 /*If ip points to the first instruction it means the handler block didn't start
2918                  so we can leave its execution to the EH machinery*/
2919                 if (ei->handler_start <= ip && ip < ei->data.handler_end) {
2920                         pdata->ji = ji;
2921                         pdata->ei = ei;
2922                         pdata->ctx = *ctx;
2923                         break;
2924                 }
2925         }
2926         return FALSE;
2927 }
2928
2929
2930 static void
2931 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2932 {
2933         int i;
2934         MonoJitExceptionInfo *clause = NULL;
2935         gpointer ip;
2936         guint8 *bp;
2937
2938         ip = MONO_CONTEXT_GET_IP (ctx);
2939
2940         for (i = 0; i < ji->num_clauses; ++i) {
2941                 clause = &ji->clauses [i];
2942                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2943                         continue;
2944                 if (clause->handler_start <= ip && clause->data.handler_end > ip)
2945                         break;
2946         }
2947
2948         /*no matching finally */
2949         if (i == ji->num_clauses)
2950                 return;
2951
2952         /*Load the spvar*/
2953         bp = (guint8*)MONO_CONTEXT_GET_BP (ctx);
2954         *(bp + clause->exvar_offset) = 1;
2955 }
2956
2957 /*
2958  * Finds the bottom handler block running and install a block guard if needed.
2959  */
2960 static gboolean
2961 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2962 {
2963         FindHandlerBlockData data = { 0 };
2964         MonoJitTlsData *jit_tls = (MonoJitTlsData *)ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2965
2966 #ifndef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT
2967         if (mono_aot_only)
2968                 return FALSE;
2969 #endif
2970
2971         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2972          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2973          */
2974         if (!jit_tls || jit_tls->handler_block)
2975                 return FALSE;
2976
2977         /* Do an async safe stack walk */
2978         mono_thread_info_set_is_async_context (TRUE);
2979         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data);
2980         mono_thread_info_set_is_async_context (FALSE);
2981
2982         if (!data.ji)
2983                 return FALSE;
2984
2985         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2986
2987         install_handler_block_guard (data.ji, &data.ctx);
2988
2989         jit_tls->handler_block = data.ei;
2990
2991         return TRUE;
2992 }
2993
2994 static gboolean
2995 mono_current_thread_has_handle_block_guard (void)
2996 {
2997         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2998         return jit_tls && jit_tls->handler_block != NULL;
2999 }
3000
3001 void
3002 mono_set_cast_details (MonoClass *from, MonoClass *to)
3003 {
3004         MonoJitTlsData *jit_tls = NULL;
3005
3006         if (mini_get_debug_options ()->better_cast_details) {
3007                 jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
3008                 jit_tls->class_cast_from = from;
3009                 jit_tls->class_cast_to = to;
3010         }
3011 }
3012
3013
3014 /*returns false if the thread is not attached*/
3015 gboolean
3016 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
3017 {
3018 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
3019         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
3020         if (!thread) {
3021                 ctx->valid = FALSE;
3022                 return FALSE;
3023         }
3024
3025         if (sigctx) {
3026                 mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
3027
3028                 ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
3029                 ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
3030                 ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
3031         }
3032         else {
3033                 mono_thread_state_init (ctx);
3034         }
3035
3036         if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF])
3037                 return FALSE;
3038
3039         ctx->valid = TRUE;
3040         return TRUE;
3041 #else
3042         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
3043         return FALSE;
3044 #endif
3045 }
3046
3047 void
3048 mono_thread_state_init (MonoThreadUnwindState *ctx)
3049 {
3050         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
3051
3052 #if defined(MONO_CROSS_COMPILE)
3053         ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
3054 #elif MONO_ARCH_HAS_MONO_CONTEXT
3055         MONO_CONTEXT_GET_CURRENT (ctx->ctx);
3056 #else
3057         g_error ("Use a null sigctx requires a working mono-context");
3058 #endif
3059
3060         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
3061         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
3062         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
3063         ctx->valid = TRUE;
3064 }
3065
3066
3067 gboolean
3068 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
3069 {
3070         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
3071         if (!thread) {
3072                 ctx->valid = FALSE;
3073                 return FALSE;
3074         }
3075
3076         ctx->ctx = *mctx;
3077         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
3078         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
3079         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
3080         ctx->valid = TRUE;
3081         return TRUE;
3082 }
3083
3084 /*returns false if the thread is not attached*/
3085 gboolean
3086 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
3087 {
3088         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
3089         MONO_ARCH_CONTEXT_DEF
3090
3091         mono_arch_flush_register_windows ();
3092
3093         if (!thread || !thread->jit_data) {
3094                 ctx->valid = FALSE;
3095                 return FALSE;
3096         }
3097 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
3098         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
3099 #else
3100         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
3101 #endif
3102                 
3103         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
3104         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
3105         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
3106         ctx->valid = TRUE;
3107         return TRUE;
3108 }
3109
3110 static void
3111 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
3112 {
3113         mono_handle_exception (ctx, (MonoObject *)exc);
3114         mono_restore_context (ctx);
3115 }
3116
3117 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
3118 void
3119 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
3120 {
3121 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
3122         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
3123         jit_tls->ex_ctx = *ctx;
3124
3125         mono_arch_setup_async_callback (ctx, async_cb, user_data);
3126 #else
3127         g_error ("This target doesn't support mono_arch_setup_async_callback");
3128 #endif
3129 }
3130
3131 /*
3132  * mono_restore_context:
3133  *
3134  *   Call the architecture specific restore context function.
3135  */
3136 void
3137 mono_restore_context (MonoContext *ctx)
3138 {
3139         static void (*restore_context) (MonoContext *);
3140
3141         if (!restore_context)
3142                 restore_context = (void (*)(MonoContext *))mono_get_restore_context ();
3143         restore_context (ctx);
3144         g_assert_not_reached ();
3145 }
3146
3147 /*
3148  * mono_jinfo_get_unwind_info:
3149  *
3150  *   Return the unwind info for JI.
3151  */
3152 guint8*
3153 mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
3154 {
3155         if (ji->has_unwind_info) {
3156                 /* The address/length in the MonoJitInfo structure itself */
3157                 MonoUnwindJitInfo *info = mono_jit_info_get_unwind_info (ji);
3158                 *unwind_info_len = info->unw_info_len;
3159                 return info->unw_info;
3160         } else if (ji->from_aot)
3161                 return mono_aot_get_unwind_info (ji, unwind_info_len);
3162         else
3163                 return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len);
3164 }
3165
3166 int
3167 mono_jinfo_get_epilog_size (MonoJitInfo *ji)
3168 {
3169         MonoArchEHJitInfo *info;
3170
3171         info = mono_jit_info_get_arch_eh_info (ji);
3172         g_assert (info);
3173
3174         return info->epilog_size;
3175 }
3176
3177 /*
3178  * LLVM/Bitcode exception handling.
3179  */
3180
3181 static void
3182 throw_exception (MonoObject *ex, gboolean rethrow)
3183 {
3184         MONO_REQ_GC_UNSAFE_MODE;
3185
3186         MonoError error;
3187         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3188         MonoException *mono_ex;
3189
3190         if (!mono_object_isinst_checked (ex, mono_defaults.exception_class, &error)) {
3191                 mono_error_assert_ok (&error);
3192                 mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error);
3193                 mono_error_assert_ok (&error);
3194                 jit_tls->thrown_non_exc = mono_gchandle_new (ex, FALSE);
3195         }
3196         else
3197                 mono_ex = (MonoException*)ex;
3198
3199         // Note: Not pinned
3200         jit_tls->thrown_exc = mono_gchandle_new ((MonoObject*)mono_ex, FALSE);
3201
3202         if (!rethrow) {
3203 #ifdef MONO_ARCH_HAVE_UNWIND_BACKTRACE
3204                 GList *l, *ips = NULL;
3205                 GList *trace;
3206
3207                 _Unwind_Backtrace (build_stack_trace, &ips);
3208                 /* The list contains ip-gshared info pairs */
3209                 trace = NULL;
3210                 ips = g_list_reverse (ips);
3211                 for (l = ips; l; l = l->next) {
3212                         trace = g_list_append (trace, l->data);
3213                         trace = g_list_append (trace, NULL);
3214                 }
3215                 MonoArray *ips_arr = mono_glist_to_array (trace, mono_defaults.int_class, &error);
3216                 mono_error_assert_ok (&error);
3217                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
3218                 g_list_free (l);
3219                 g_list_free (trace);
3220 #endif
3221         }
3222
3223         mono_llvm_cpp_throw_exception ();
3224 }
3225
3226 void
3227 mono_llvm_throw_exception (MonoObject *ex)
3228 {
3229         throw_exception (ex, FALSE);
3230 }
3231
3232 void
3233 mono_llvm_rethrow_exception (MonoObject *ex)
3234 {
3235         throw_exception (ex, TRUE);
3236 }
3237
3238 void
3239 mono_llvm_raise_exception (MonoException *e)
3240 {
3241         mono_llvm_throw_exception ((MonoObject*)e);
3242 }
3243
3244 void
3245 mono_llvm_throw_corlib_exception (guint32 ex_token_index)
3246 {
3247         guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
3248         MonoException *ex;
3249
3250         ex = mono_exception_from_token (mono_defaults.exception_class->image, ex_token);
3251
3252         mono_llvm_throw_exception ((MonoObject*)ex);
3253 }
3254
3255 /*
3256  * mono_llvm_resume_exception:
3257  *
3258  *   Resume exception propagation.
3259  */
3260 void
3261 mono_llvm_resume_exception (void)
3262 {
3263         mono_llvm_cpp_throw_exception ();
3264 }
3265
3266 /*
3267  * mono_llvm_load_exception:
3268  *
3269  *   Return the currently thrown exception.
3270  */
3271 MonoObject *
3272 mono_llvm_load_exception (void)
3273 {
3274         MonoError error;
3275         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3276
3277         MonoException *mono_ex = (MonoException*)mono_gchandle_get_target (jit_tls->thrown_exc);
3278
3279         if (mono_ex->trace_ips) {
3280                 GList *trace_ips = NULL;
3281                 gpointer ip = __builtin_return_address (0);
3282
3283                 size_t upper = mono_array_length (mono_ex->trace_ips);
3284
3285                 for (int i = 0; i < upper; i += TRACE_IP_ENTRY_SIZE) {
3286                         gpointer curr_ip = mono_array_get (mono_ex->trace_ips, gpointer, i);
3287                         for (int j = 0; j < TRACE_IP_ENTRY_SIZE; ++j) {
3288                                 gpointer p = mono_array_get (mono_ex->trace_ips, gpointer, i + j);
3289                                 trace_ips = g_list_append (trace_ips, p);
3290                         }
3291                         if (ip == curr_ip)
3292                                 break;
3293                 }
3294
3295                 // FIXME: Does this work correctly for rethrows?
3296                 // We may be discarding useful information
3297                 // when this gets GC'ed
3298                 MonoArray *ips_arr = mono_glist_to_array (trace_ips, mono_defaults.int_class, &error);
3299                 mono_error_assert_ok (&error);
3300                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
3301                 g_list_free (trace_ips);
3302
3303                 // FIXME:
3304                 //MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex));
3305         } else {
3306                 MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_array_new_checked (mono_domain_get (), mono_defaults.int_class, 0, &error));
3307                 mono_error_assert_ok (&error);
3308                 MONO_OBJECT_SETREF (mono_ex, stack_trace, mono_array_new_checked (mono_domain_get (), mono_defaults.stack_frame_class, 0, &error));
3309                 mono_error_assert_ok (&error);
3310         }
3311
3312         return &mono_ex->object;
3313 }
3314
3315 /*
3316  * mono_llvm_clear_exception:
3317  *
3318  *   Mark the currently thrown exception as handled.
3319  */
3320 void
3321 mono_llvm_clear_exception (void)
3322 {
3323         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3324         mono_gchandle_free (jit_tls->thrown_exc);
3325         jit_tls->thrown_exc = 0;
3326         if (jit_tls->thrown_non_exc)
3327                 mono_gchandle_free (jit_tls->thrown_non_exc);
3328         jit_tls->thrown_non_exc = 0;
3329
3330         mono_memory_barrier ();
3331 }
3332
3333 /*
3334  * mono_llvm_match_exception:
3335  *
3336  *   Return the innermost clause containing REGION_START-REGION_END which can handle
3337  * the current exception.
3338  */
3339 gint32
3340 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj)
3341 {
3342         MonoError error;
3343         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3344         MonoObject *exc;
3345         gint32 index = -1;
3346
3347         g_assert (jit_tls->thrown_exc);
3348         exc = mono_gchandle_get_target (jit_tls->thrown_exc);
3349         if (jit_tls->thrown_non_exc) {
3350                 /*
3351                  * Have to unwrap RuntimeWrappedExceptions if the
3352                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
3353                  */
3354                 if (!wrap_non_exception_throws (jinfo_get_method (jinfo)))
3355                         exc = mono_gchandle_get_target (jit_tls->thrown_non_exc);
3356         }
3357
3358         for (int i = 0; i < jinfo->num_clauses; i++) {
3359                 MonoJitExceptionInfo *ei = &jinfo->clauses [i];
3360                 MonoClass *catch_class;
3361
3362                 if (! (ei->try_offset == region_start && ei->try_offset + ei->try_len == region_end) )
3363                         continue;
3364
3365                 catch_class = ei->data.catch_class;
3366                 if (mono_class_is_open_constructed_type (&catch_class->byval_arg)) {
3367                         MonoGenericContext context;
3368                         MonoType *inflated_type;
3369
3370                         g_assert (rgctx || this_obj);
3371                         context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
3372                         inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
3373                         mono_error_assert_ok (&error); /* FIXME don't swallow the error */
3374
3375                         catch_class = mono_class_from_mono_type (inflated_type);
3376                         mono_metadata_free_type (inflated_type);
3377                 }
3378
3379                 // FIXME: Handle edge cases handled in get_exception_catch_class
3380                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (exc, catch_class, &error)) {
3381                         index = ei->clause_index;
3382                         break;
3383                 } else
3384                         mono_error_assert_ok (&error);
3385                 
3386                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3387                         g_assert_not_reached ();
3388                 }
3389         }
3390
3391         return index;
3392 }
3393
3394 #ifdef ENABLE_LLVM
3395 _Unwind_Reason_Code 
3396 mono_debug_personality (int a, _Unwind_Action b,
3397 uint64_t c, struct _Unwind_Exception *d, struct _Unwind_Context *e)
3398 {
3399         g_assert_not_reached ();
3400 }
3401 #else
3402 void
3403 mono_debug_personality (void);
3404
3405 void
3406 mono_debug_personality (void)
3407 {
3408         g_assert_not_reached ();
3409 }
3410 #endif