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