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