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