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