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