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