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