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