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