Merge pull request #4248 from Unity-Technologies/boehm-gc-alloc-fixed
[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, GList **trace_ips)
1404 {
1405         if (mono_ex) {
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         GList *trace_ips = NULL;
1460         GSList *dynamic_methods = NULL;
1461         MonoException *mono_ex;
1462         gboolean stack_overflow = FALSE;
1463         MonoContext initial_ctx;
1464         MonoMethod *method;
1465         int frame_count = 0;
1466         gint32 filter_idx;
1467         int i;
1468         MonoObject *ex_obj;
1469
1470         g_assert (ctx != NULL);
1471
1472         if (obj == (MonoObject *)domain->stack_overflow_ex)
1473                 stack_overflow = TRUE;
1474
1475         mono_ex = (MonoException*)obj;
1476         MonoArray *initial_trace_ips = mono_ex->trace_ips;
1477         if (initial_trace_ips) {
1478                 int len = mono_array_length (initial_trace_ips) >> 1;
1479
1480                 for (i = 0; i < (len - 1); i++) {
1481                         gpointer ip = mono_array_get (initial_trace_ips, gpointer, i * 2 + 0);
1482                         gpointer generic_info = mono_array_get (initial_trace_ips, gpointer, i * 2 + 1);
1483                         trace_ips = g_list_prepend (trace_ips, ip);
1484                         trace_ips = g_list_prepend (trace_ips, generic_info);
1485                 }
1486         }
1487
1488         if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1489                 mono_error_assert_ok (&error);
1490                 mono_ex = NULL;
1491         }
1492
1493         if (!call_filter)
1494                 call_filter = (int (*) (MonoContext *, void *))mono_get_call_filter ();
1495
1496         g_assert (jit_tls->end_of_stack);
1497         g_assert (jit_tls->abort_func);
1498
1499         if (out_filter_idx)
1500                 *out_filter_idx = -1;
1501         if (out_ji)
1502                 *out_ji = NULL;
1503         if (out_prev_ji)
1504                 *out_prev_ji = NULL;
1505         filter_idx = 0;
1506         initial_ctx = *ctx;
1507
1508         while (1) {
1509                 MonoContext new_ctx;
1510                 guint32 free_stack;
1511                 int clause_index_start = 0;
1512                 gboolean unwind_res = TRUE;
1513                 
1514                 StackFrameInfo frame;
1515
1516                 if (out_prev_ji)
1517                         *out_prev_ji = ji;
1518
1519                 unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1520                 if (unwind_res) {
1521                         if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
1522                                         frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
1523                                         frame.type == FRAME_TYPE_TRAMPOLINE) {
1524                                 *ctx = new_ctx;
1525                                 continue;
1526                         }
1527                         g_assert (frame.type == FRAME_TYPE_MANAGED);
1528                         ji = frame.ji;
1529                 }
1530
1531                 if (!unwind_res) {
1532                         setup_stack_trace (mono_ex, dynamic_methods, &trace_ips);
1533                         g_slist_free (dynamic_methods);
1534                         return FALSE;
1535                 }
1536
1537                 frame_count ++;
1538                 method = jinfo_get_method (ji);
1539                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1540
1541                 if (mini_get_debug_options ()->reverse_pinvoke_exceptions && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
1542                         g_error ("A native frame was found while unwinding the stack after an exception.\n"
1543                                          "The native frame called the managed method:\n%s\n",
1544                                          mono_method_full_name (method, TRUE));
1545                 }
1546
1547                 if (method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
1548                         // avoid giant stack traces during a stack overflow
1549                         if (frame_count < 1000) {
1550                                 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
1551                                 trace_ips = g_list_prepend (trace_ips, get_generic_info_from_stack_frame (ji, ctx));
1552                         }
1553                 }
1554
1555                 if (method->dynamic)
1556                         dynamic_methods = g_slist_prepend (dynamic_methods, method);
1557
1558                 if (stack_overflow) {
1559                         if (MONO_ARCH_STACK_GROWS_UP)
1560                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1561                         else
1562                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1563                 } else {
1564                         free_stack = 0xffffff;
1565                 }
1566                                 
1567                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1568                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1569                         gboolean filtered = FALSE;
1570
1571                         /* 
1572                          * During stack overflow, wait till the unwinding frees some stack
1573                          * space before running handlers/finalizers.
1574                          */
1575                         if (free_stack <= (64 * 1024))
1576                                 continue;
1577
1578                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1579                                 /* catch block */
1580                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1581
1582                                 /*
1583                                  * Have to unwrap RuntimeWrappedExceptions if the
1584                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1585                                  */
1586                                 if (non_exception && !wrap_non_exception_throws (method))
1587                                         ex_obj = non_exception;
1588                                 else
1589                                         ex_obj = obj;
1590
1591                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1592                                         gboolean is_user_frame = method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD;
1593 #ifndef DISABLE_PERFCOUNTERS
1594                                         mono_perfcounters->exceptions_filters++;
1595 #endif
1596                                         /*
1597                                         Here's the thing, if this is a filter clause done by a wrapper like runtime invoke, we don't want to
1598                                         trim the stackframe since if it returns FALSE we lose information.
1599
1600                                         FIXME Not 100% sure if it's a good idea even with user clauses.
1601                                         */
1602                                         if (is_user_frame)
1603                                                 setup_stack_trace (mono_ex, dynamic_methods, &trace_ips);
1604
1605 #ifndef MONO_CROSS_COMPILE
1606 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1607                                         if (ji->from_llvm)
1608                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1609                                         else
1610                                                 /* Can't pass the ex object in a register yet to filter clauses, because call_filter () might not support it */
1611                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1612 #else
1613                                         g_assert (!ji->from_llvm);
1614                                         /* store the exception object in bp + ei->exvar_offset */
1615                                         *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1616 #endif
1617 #endif
1618
1619 #ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
1620                                         /*
1621                                          * Pass the original il clause index to the landing pad so it can
1622                                          * branch to the landing pad associated with the il clause.
1623                                          * This is needed because llvm compiled code assumes that the EH
1624                                          * code always branches to the innermost landing pad.
1625                                          */
1626                                         if (ji->from_llvm)
1627                                                 MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
1628 #endif
1629
1630                                         mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
1631                                         filtered = call_filter (ctx, ei->data.filter);
1632                                         mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
1633                                         if (filtered && out_filter_idx)
1634                                                 *out_filter_idx = filter_idx;
1635                                         if (out_ji)
1636                                                 *out_ji = ji;
1637                                         filter_idx ++;
1638
1639                                         if (filtered) {
1640                                                 if (!is_user_frame)
1641                                                         setup_stack_trace (mono_ex, dynamic_methods, &trace_ips);
1642                                                 g_slist_free (dynamic_methods);
1643                                                 /* mono_debugger_agent_handle_exception () needs this */
1644                                                 mini_set_abort_threshold (ctx);
1645                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1646                                                 return TRUE;
1647                                         }
1648                                 }
1649
1650                                 MonoError isinst_error;
1651                                 mono_error_init (&isinst_error);
1652                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (ex_obj, catch_class, &error)) {
1653                                         setup_stack_trace (mono_ex, dynamic_methods, &trace_ips);
1654                                         g_slist_free (dynamic_methods);
1655
1656                                         if (out_ji)
1657                                                 *out_ji = ji;
1658
1659                                         /* mono_debugger_agent_handle_exception () needs this */
1660                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1661                                         return TRUE;
1662                                 }
1663                                 mono_error_cleanup (&isinst_error);
1664                         }
1665                 }
1666
1667                 *ctx = new_ctx;
1668         }
1669
1670         g_assert_not_reached ();
1671 }
1672
1673 /**
1674  * mono_handle_exception_internal:
1675  * @ctx: saved processor state
1676  * @obj: the exception object
1677  * @resume: whenever to resume unwinding based on the state in MonoJitTlsData.
1678  */
1679 static gboolean
1680 mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resume, MonoJitInfo **out_ji)
1681 {
1682         MonoError error;
1683         MonoDomain *domain = mono_domain_get ();
1684         MonoJitInfo *ji, *prev_ji;
1685         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1686         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1687         MonoLMF *lmf = mono_get_lmf ();
1688         MonoException *mono_ex;
1689         gboolean stack_overflow = FALSE;
1690         MonoContext initial_ctx;
1691         MonoMethod *method;
1692         int frame_count = 0;
1693         gint32 filter_idx, first_filter_idx = 0;
1694         int i;
1695         MonoObject *ex_obj;
1696         MonoObject *non_exception = NULL;
1697
1698         g_assert (ctx != NULL);
1699         if (!obj) {
1700                 MonoException *ex = mono_get_exception_null_reference ();
1701                 MONO_OBJECT_SETREF (ex, message, mono_string_new (domain, "Object reference not set to an instance of an object"));
1702                 obj = (MonoObject *)ex;
1703         } 
1704
1705         /*
1706          * Allocate a new exception object instead of the preconstructed ones.
1707          */
1708         if (obj == (MonoObject *)domain->stack_overflow_ex) {
1709                 /*
1710                  * It is not a good idea to try and put even more pressure on the little stack available.
1711                  * obj = mono_get_exception_stack_overflow ();
1712                  */
1713                 stack_overflow = TRUE;
1714         }
1715         else if (obj == (MonoObject *)domain->null_reference_ex) {
1716                 obj = (MonoObject *)mono_get_exception_null_reference ();
1717         }
1718
1719         if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1720                 mono_error_assert_ok (&error);
1721                 non_exception = obj;
1722                 obj = (MonoObject *)mono_get_exception_runtime_wrapped_checked (obj, &error);
1723                 mono_error_assert_ok (&error);
1724         }
1725
1726         mono_ex = (MonoException*)obj;
1727
1728         if (mini_get_debug_options ()->suspend_on_exception) {
1729                 mono_runtime_printf_err ("Exception thrown, suspending...");
1730                 while (1)
1731                         ;
1732         }
1733
1734         if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
1735                 mono_ex = (MonoException*)obj;
1736         } else {
1737                 mono_error_assert_ok (&error);
1738                 mono_ex = NULL;
1739         }
1740
1741         if (mono_ex && jit_tls->class_cast_from) {
1742                 if (!strcmp (mono_ex->object.vtable->klass->name, "InvalidCastException")) {
1743                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1744                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1745                         char *msg = g_strdup_printf ("Unable to cast object of type '%s' to type '%s'.", from_name, to_name);
1746                         mono_ex->message = mono_string_new (domain, msg);
1747                         g_free (from_name);
1748                         g_free (to_name);
1749                         g_free (msg);
1750                 }
1751                 if (!strcmp (mono_ex->object.vtable->klass->name, "ArrayTypeMismatchException")) {
1752                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1753                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1754                         char *msg = g_strdup_printf ("Source array of type '%s' cannot be cast to destination array type '%s'.", from_name, to_name);
1755                         mono_ex->message = mono_string_new (domain, msg);
1756                         g_free (from_name);
1757                         g_free (to_name);
1758                         g_free (msg);
1759                 }
1760         }
1761
1762         if (!call_filter)
1763                 call_filter = (int (*)(MonoContext *, void*))mono_get_call_filter ();
1764
1765         g_assert (jit_tls->end_of_stack);
1766         g_assert (jit_tls->abort_func);
1767
1768         /*
1769          * We set orig_ex_ctx_set to TRUE/FALSE around profiler calls to make sure it doesn't
1770          * end up being TRUE on any code path.
1771          */
1772         memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
1773
1774         if (!resume) {
1775                 gboolean res;
1776
1777                 MonoContext ctx_cp = *ctx;
1778                 if (mono_trace_is_enabled ()) {
1779                         MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
1780                         MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
1781                         MonoObject *message;
1782                         const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
1783                         char *msg = NULL;
1784                         if (get_message == NULL) {
1785                                 message = NULL;
1786                         } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
1787                                 message = NULL;
1788                                 msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
1789                         } else {
1790                                 MonoObject *exc = NULL;
1791                                 message = mono_runtime_try_invoke (get_message, obj, NULL, &exc, &error);
1792                                 g_assert (exc == NULL);
1793                                 mono_error_assert_ok (&error);
1794                         }
1795                         if (msg == NULL) {
1796                                 if (message) {
1797                                         msg = mono_string_to_utf8_checked ((MonoString *) message, &error);
1798                                         if (!is_ok (&error)) {
1799                                                 mono_error_cleanup (&error);
1800                                                 msg = g_strdup ("(error while display System.Exception.Message property)");
1801                                         }
1802                                 } else {
1803                                         msg = g_strdup ("(System.Exception.Message property not available)");
1804                                 }
1805                         }
1806                         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);
1807                         g_free (msg);
1808                         if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
1809                                 mono_print_thread_dump_from_ctx (ctx);
1810                 }
1811                 jit_tls->orig_ex_ctx_set = TRUE;
1812                 mono_profiler_exception_thrown (obj);
1813                 jit_tls->orig_ex_ctx_set = FALSE;
1814
1815                 res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
1816
1817                 if (!res) {
1818                         if (mini_get_debug_options ()->break_on_exc)
1819                                 G_BREAKPOINT ();
1820                         mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL);
1821
1822                         if (mini_get_debug_options ()->suspend_on_unhandled) {
1823                                 mono_runtime_printf_err ("Unhandled exception, suspending...");
1824                                 while (1)
1825                                         ;
1826                         }
1827
1828                         // FIXME: This runs managed code so it might cause another stack overflow when
1829                         // we are handling a stack overflow
1830                         mini_set_abort_threshold (ctx);
1831                         mono_unhandled_exception (obj);
1832                 } else {
1833                         gboolean unhandled = FALSE;
1834
1835                         /*
1836                          * The exceptions caught by the mono_runtime_invoke_checked () calls
1837                          * in the threadpool needs to be treated as unhandled (#669836).
1838                          *
1839                          * FIXME: The check below is hackish, but its hard to distinguish
1840                          * these runtime invoke calls from others in the runtime.
1841                          */
1842                         if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
1843                                 if (prev_ji && jinfo_get_method (prev_ji) == mono_defaults.threadpool_perform_wait_callback_method)
1844                                         unhandled = TRUE;
1845                         }
1846
1847                         if (unhandled)
1848                                 mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, NULL);
1849                         else
1850                                 mono_debugger_agent_handle_exception ((MonoException *)obj, ctx, &ctx_cp);
1851                 }
1852         }
1853
1854         if (out_ji)
1855                 *out_ji = NULL;
1856         filter_idx = 0;
1857         initial_ctx = *ctx;
1858
1859         while (1) {
1860                 MonoContext new_ctx;
1861                 guint32 free_stack;
1862                 int clause_index_start = 0;
1863                 gboolean unwind_res = TRUE;
1864                 
1865                 if (resume) {
1866                         resume = FALSE;
1867                         ji = jit_tls->resume_state.ji;
1868                         new_ctx = jit_tls->resume_state.new_ctx;
1869                         clause_index_start = jit_tls->resume_state.clause_index;
1870                         lmf = jit_tls->resume_state.lmf;
1871                         first_filter_idx = jit_tls->resume_state.first_filter_idx;
1872                         filter_idx = jit_tls->resume_state.filter_idx;
1873                 } else {
1874                         StackFrameInfo frame;
1875
1876                         unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1877                         if (unwind_res) {
1878                                 if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE ||
1879                                                 frame.type == FRAME_TYPE_MANAGED_TO_NATIVE ||
1880                                                 frame.type == FRAME_TYPE_TRAMPOLINE) {
1881                                         *ctx = new_ctx;
1882                                         continue;
1883                                 }
1884                                 g_assert (frame.type == FRAME_TYPE_MANAGED);
1885                                 ji = frame.ji;
1886                         }
1887                 }
1888
1889                 if (!unwind_res) {
1890                         *(mono_get_lmf_addr ()) = lmf;
1891
1892                         jit_tls->abort_func (obj);
1893                         g_assert_not_reached ();
1894                 }
1895
1896                 method = jinfo_get_method (ji);
1897                 frame_count ++;
1898                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1899
1900                 if (stack_overflow) {
1901                         if (MONO_ARCH_STACK_GROWS_UP)
1902                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1903                         else
1904                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1905                 } else {
1906                         free_stack = 0xffffff;
1907                 }
1908                                 
1909                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1910                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1911                         gboolean filtered = FALSE;
1912
1913                         /* 
1914                          * During stack overflow, wait till the unwinding frees some stack
1915                          * space before running handlers/finalizers.
1916                          */
1917                         if (free_stack <= (64 * 1024))
1918                                 continue;
1919
1920                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1921                                 /* catch block */
1922                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1923
1924                                 /*
1925                                  * Have to unwrap RuntimeWrappedExceptions if the
1926                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1927                                  */
1928                                 if (non_exception && !wrap_non_exception_throws (method))
1929                                         ex_obj = non_exception;
1930                                 else
1931                                         ex_obj = obj;
1932
1933                                 if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
1934 #ifndef MONO_CROSS_COMPILE
1935 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1936                                         MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1937 #else
1938                                         g_assert (!ji->from_llvm);
1939                                         /* store the exception object in bp + ei->exvar_offset */
1940                                         *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1941 #endif
1942 #endif
1943                                 }
1944
1945 #ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
1946                                 if (ji->from_llvm)
1947                                         MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, ei->clause_index);
1948 #endif
1949
1950                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1951                                         /* 
1952                                          * Filter clauses should only be run in the 
1953                                          * first pass of exception handling.
1954                                          */
1955                                         filtered = (filter_idx == first_filter_idx);
1956                                         filter_idx ++;
1957                                 }
1958
1959                                 mono_error_init (&error);
1960                                 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
1961                                      mono_object_isinst_checked (ex_obj, catch_class, &error)) || filtered) {
1962                                         /*
1963                                          * This guards against the situation that we abort a thread that is executing a finally clause
1964                                          * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
1965                                          * check for this situation here and resume interruption if we are below the guarded block.
1966                                          */
1967                                         if (G_UNLIKELY (jit_tls->handler_block_return_address)) {
1968                                                 gboolean is_outside = FALSE;
1969                                                 gpointer prot_bp = MONO_CONTEXT_GET_BP (&jit_tls->handler_block_context);
1970                                                 gpointer catch_bp = MONO_CONTEXT_GET_BP (ctx);
1971                                                 //FIXME make this stack direction aware
1972                                                 if (catch_bp > prot_bp) {
1973                                                         is_outside = TRUE;
1974                                                 } else if (catch_bp == prot_bp) {
1975                                                         /* Can be either try { try { } catch {} } finally {} or try { try { } finally {} } catch {}
1976                                                          * So we check if the catch handler_start is protected by the guarded handler protected region
1977                                                          *
1978                                                          * Assumptions:
1979                                                          *      If there is an outstanding guarded_block return address, it means the current thread must be aborted.
1980                                                          *      This is the only way to reach out the guarded block as other cases are handled by the trampoline.
1981                                                          *      There aren't any further finally/fault handler blocks down the stack over this exception.
1982                                                          *   This must be ensured by the code that installs the guard trampoline.
1983                                                          */
1984                                                         g_assert (ji == mini_jit_info_table_find (domain, (char *)MONO_CONTEXT_GET_IP (&jit_tls->handler_block_context), NULL));
1985
1986                                                         if (!is_address_protected (ji, jit_tls->handler_block, ei->handler_start)) {
1987                                                                 is_outside = TRUE;
1988                                                         }
1989                                                 }
1990                                                 if (is_outside) {
1991                                                         jit_tls->handler_block_return_address = NULL;
1992                                                         jit_tls->handler_block = NULL;
1993                                                         mono_thread_resume_interruption (); /*We ignore the exception here, it will be raised later*/
1994                                                 }
1995                                         }
1996
1997                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1998                                                 g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1999                                         jit_tls->orig_ex_ctx_set = TRUE;
2000                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
2001                                         jit_tls->orig_ex_ctx_set = FALSE;
2002                                         mini_set_abort_threshold (ctx);
2003                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
2004                                         mono_set_lmf (lmf);
2005 #ifndef DISABLE_PERFCOUNTERS
2006                                         mono_perfcounters->exceptions_depth += frame_count;
2007 #endif
2008                                         if (obj == (MonoObject *)domain->stack_overflow_ex)
2009                                                 jit_tls->handling_stack_ovf = FALSE;
2010
2011                                         return 0;
2012                                 }
2013                                 mono_error_cleanup (&error);
2014                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
2015                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
2016                                                 g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
2017                                         jit_tls->orig_ex_ctx_set = TRUE;
2018                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
2019                                         jit_tls->orig_ex_ctx_set = FALSE;
2020                                         mini_set_abort_threshold (ctx);
2021                                         call_filter (ctx, ei->handler_start);
2022                                 }
2023                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
2024                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
2025                                                 g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
2026                                         jit_tls->orig_ex_ctx_set = TRUE;
2027                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
2028                                         jit_tls->orig_ex_ctx_set = FALSE;
2029 #ifndef DISABLE_PERFCOUNTERS
2030                                         mono_perfcounters->exceptions_finallys++;
2031 #endif
2032                                         mono_set_lmf (lmf);
2033                                         if (ji->from_llvm) {
2034                                                 /* 
2035                                                  * LLVM compiled finally handlers follow the design
2036                                                  * of the c++ ehabi, i.e. they call a resume function
2037                                                  * at the end instead of returning to the caller.
2038                                                  * So save the exception handling state,
2039                                                  * mono_resume_unwind () will call us again to continue
2040                                                  * the unwinding.
2041                                                  */
2042                                                 jit_tls->resume_state.ex_obj = obj;
2043                                                 jit_tls->resume_state.ji = ji;
2044                                                 jit_tls->resume_state.clause_index = i + 1;
2045                                                 jit_tls->resume_state.ctx = *ctx;
2046                                                 jit_tls->resume_state.new_ctx = new_ctx;
2047                                                 jit_tls->resume_state.lmf = lmf;
2048                                                 jit_tls->resume_state.first_filter_idx = first_filter_idx;
2049                                                 jit_tls->resume_state.filter_idx = filter_idx;
2050                                                 mini_set_abort_threshold (ctx);
2051                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
2052                                                 return 0;
2053                                         } else {
2054                                                 mini_set_abort_threshold (ctx);
2055                                                 call_filter (ctx, ei->handler_start);
2056                                         }
2057                                 }
2058                         }
2059                 }
2060
2061                 jit_tls->orig_ex_ctx_set = TRUE;
2062                 mono_profiler_exception_method_leave (method);
2063                 jit_tls->orig_ex_ctx_set = FALSE;
2064
2065                 *ctx = new_ctx;
2066         }
2067
2068         g_assert_not_reached ();
2069 }
2070
2071 /**
2072  * mono_debugger_run_finally:
2073  * @start_ctx: saved processor state
2074  *
2075  * This method is called by the Mono Debugger to call all `finally' clauses of the
2076  * current stack frame.  It's used when the user issues a `return' command to make
2077  * the current stack frame return.  After returning from this method, the debugger
2078  * unwinds the stack one frame and gives control back to the user.
2079  *
2080  * NOTE: This method is only used when running inside the Mono Debugger.
2081  */
2082 void
2083 mono_debugger_run_finally (MonoContext *start_ctx)
2084 {
2085         static int (*call_filter) (MonoContext *, gpointer) = NULL;
2086         MonoDomain *domain = mono_domain_get ();
2087         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2088         MonoLMF *lmf = mono_get_lmf ();
2089         MonoContext ctx, new_ctx;
2090         MonoJitInfo *ji, rji;
2091         int i;
2092
2093         ctx = *start_ctx;
2094
2095         ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
2096         if (!ji || ji == (gpointer)-1)
2097                 return;
2098
2099         if (!call_filter)
2100                 call_filter = (int (*)(MonoContext *, void *))mono_get_call_filter ();
2101
2102         for (i = 0; i < ji->num_clauses; i++) {
2103                 MonoJitExceptionInfo *ei = &ji->clauses [i];
2104
2105                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
2106                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
2107                         call_filter (&ctx, ei->handler_start);
2108                 }
2109         }
2110 }
2111
2112 /**
2113  * mono_handle_exception:
2114  * @ctx: saved processor state
2115  * @obj: the exception object
2116  */
2117 gboolean
2118 mono_handle_exception (MonoContext *ctx, MonoObject *obj)
2119 {
2120         MONO_REQ_GC_UNSAFE_MODE;
2121
2122 #ifndef DISABLE_PERFCOUNTERS
2123         mono_perfcounters->exceptions_thrown++;
2124 #endif
2125
2126         return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
2127 }
2128
2129 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2130
2131 #ifndef MONO_ARCH_USE_SIGACTION
2132 #error "Can't use sigaltstack without sigaction"
2133 #endif
2134
2135 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
2136
2137 void
2138 mono_setup_altstack (MonoJitTlsData *tls)
2139 {
2140         size_t stsize = 0;
2141         stack_t sa;
2142         guint8 *staddr = NULL;
2143
2144         if (mono_running_on_valgrind ())
2145                 return;
2146
2147         mono_thread_info_get_stack_bounds (&staddr, &stsize);
2148
2149         g_assert (staddr);
2150
2151         tls->end_of_stack = staddr + stsize;
2152         tls->stack_size = stsize;
2153
2154         /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
2155
2156         tls->stack_ovf_guard_base = staddr + mono_pagesize ();
2157         tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
2158
2159         g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
2160
2161         if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
2162                 /* mprotect can fail for the main thread stack */
2163                 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);
2164                 g_assert (gaddr == tls->stack_ovf_guard_base);
2165                 tls->stack_ovf_valloced = TRUE;
2166         }
2167
2168         /* Setup an alternate signal stack */
2169         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);
2170         tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2171
2172         g_assert (tls->signal_stack);
2173
2174         sa.ss_sp = tls->signal_stack;
2175         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2176         sa.ss_flags = 0;
2177         g_assert (sigaltstack (&sa, NULL) == 0);
2178
2179         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);
2180 }
2181
2182 void
2183 mono_free_altstack (MonoJitTlsData *tls)
2184 {
2185         stack_t sa;
2186         int err;
2187
2188         sa.ss_sp = tls->signal_stack;
2189         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2190         sa.ss_flags = SS_DISABLE;
2191         err = sigaltstack  (&sa, NULL);
2192         g_assert (err == 0);
2193
2194         if (tls->signal_stack)
2195                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MEM_ACCOUNT_EXCEPTIONS);
2196         if (tls->stack_ovf_valloced)
2197                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MEM_ACCOUNT_EXCEPTIONS);
2198         else
2199                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
2200 }
2201
2202 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2203
2204 void
2205 mono_setup_altstack (MonoJitTlsData *tls)
2206 {
2207 }
2208
2209 void
2210 mono_free_altstack (MonoJitTlsData *tls)
2211 {
2212 }
2213
2214 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2215
2216 static gboolean
2217 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
2218 {
2219         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
2220         /* we need to leave some room for throwing the exception */
2221         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
2222                 unprotect_size -= mono_pagesize ();
2223         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
2224          * is sufficient stack
2225          */
2226         //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);
2227         if (unprotect_size)
2228                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
2229         return unprotect_size == jit_tls->stack_ovf_guard_size;
2230 }
2231
2232 static G_GNUC_UNUSED void
2233 try_more_restore (void)
2234 {
2235         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2236         if (try_restore_stack_protection (jit_tls, 500))
2237                 jit_tls->restore_stack_prot = NULL;
2238 }
2239
2240 static G_GNUC_UNUSED void
2241 restore_stack_protection (void)
2242 {
2243         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2244         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
2245         /* if we can't restore the stack protection, keep a callback installed so
2246          * we'll try to restore as much stack as we can at each return from unmanaged
2247          * code.
2248          */
2249         if (try_restore_stack_protection (jit_tls, 4096))
2250                 jit_tls->restore_stack_prot = NULL;
2251         else
2252                 jit_tls->restore_stack_prot = try_more_restore_tramp;
2253         /* here we also throw a stack overflow exception */
2254         ex->trace_ips = NULL;
2255         ex->stack_trace = NULL;
2256         mono_raise_exception (ex);
2257 }
2258
2259 gpointer
2260 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
2261 {
2262         MONO_REQ_GC_UNSAFE_MODE;
2263
2264         void (*func)(void) = (void (*)(void))tramp_data;
2265         func ();
2266         return NULL;
2267 }
2268
2269 gboolean
2270 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr)
2271 {
2272         if (mono_llvm_only)
2273                 return FALSE;
2274
2275         /* we got a stack overflow in the soft-guard pages
2276          * There are two cases:
2277          * 1) managed code caused the overflow: we unprotect the soft-guard page
2278          * and let the arch-specific code trigger the exception handling mechanism
2279          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
2280          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
2281          * and hope we can continue with those enabled, at least until the hard-guard page
2282          * is hit. The alternative to continuing here is to just print a message and abort.
2283          * We may add in the future the code to protect the pages again in the codepath
2284          * when we return from unmanaged to managed code.
2285          */
2286         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2287                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2288                 /* we unprotect the minimum amount we can */
2289                 guint32 guard_size;
2290                 gboolean handled = FALSE;
2291
2292                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2293                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2294                         guard_size -= mono_pagesize ();
2295                 }
2296                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2297                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2298                 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);
2299 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2300                 if (ji) {
2301                         mono_arch_handle_altstack_exception (ctx, siginfo, fault_addr, TRUE);
2302                         handled = TRUE;
2303                 }
2304 #endif
2305                 if (!handled) {
2306                         /* We print a message: after this even managed stack overflows
2307                          * may crash the runtime
2308                          */
2309                         mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2310                         if (!jit_tls->handling_stack_ovf) {
2311                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2312                                 jit_tls->handling_stack_ovf = 1;
2313                         } else {
2314                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2315                         }
2316                 }
2317                 return TRUE;
2318         }
2319         return FALSE;
2320 }
2321
2322 typedef struct {
2323         MonoMethod *omethod;
2324         int count;
2325 } PrintOverflowUserData;
2326
2327 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2328 static gboolean
2329 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2330 {
2331         MonoMethod *method = NULL;
2332         PrintOverflowUserData *user_data = (PrintOverflowUserData *)data;
2333         gchar *location;
2334
2335         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2336                 method = jinfo_get_method (frame->ji);
2337
2338         if (method) {
2339                 if (user_data->count == 0) {
2340                         /* The first frame is in its prolog, so a line number cannot be computed */
2341                         user_data->count ++;
2342                         return FALSE;
2343                 }
2344
2345                 /* If this is a one method overflow, skip the other instances */
2346                 if (method == user_data->omethod)
2347                         return FALSE;
2348
2349                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2350                 mono_runtime_printf_err ("  %s", location);
2351                 g_free (location);
2352
2353                 if (user_data->count == 1) {
2354                         mono_runtime_printf_err ("  <...>");
2355                         user_data->omethod = method;
2356                 } else {
2357                         user_data->omethod = NULL;
2358                 }
2359
2360                 user_data->count ++;
2361         } else
2362                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2363
2364         return FALSE;
2365 }
2366 #endif
2367
2368 void
2369 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2370 {
2371 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2372         PrintOverflowUserData ud;
2373         MonoContext mctx;
2374 #endif
2375
2376         /* we don't do much now, but we can warn the user with a useful message */
2377         mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2378
2379 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2380         mono_sigctx_to_monoctx (ctx, &mctx);
2381                         
2382         mono_runtime_printf_err ("Stacktrace:");
2383
2384         memset (&ud, 0, sizeof (ud));
2385
2386         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2387 #else
2388         if (ji && !ji->is_trampoline && jinfo_get_method (ji))
2389                 mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
2390         else
2391                 mono_runtime_printf_err ("At <unmanaged>.");
2392 #endif
2393
2394         _exit (1);
2395 }
2396
2397 static gboolean
2398 print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2399 {
2400         MonoMethod *method = NULL;
2401
2402         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2403                 method = jinfo_get_method (frame->ji);
2404
2405         if (method) {
2406                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2407                 mono_runtime_printf_err ("  %s", location);
2408                 g_free (location);
2409         } else
2410                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2411
2412         return FALSE;
2413 }
2414
2415 static G_GNUC_UNUSED gboolean
2416 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2417 {
2418         GString *p = (GString*)data;
2419         MonoMethod *method = NULL;
2420
2421         if (frame->ji && frame->type != FRAME_TYPE_TRAMPOLINE)
2422                 method = jinfo_get_method (frame->ji);
2423
2424         if (method && frame->domain) {
2425                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
2426                 g_string_append_printf (p, "  %s\n", location);
2427                 g_free (location);
2428         } else
2429                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2430
2431         return FALSE;
2432 }
2433
2434 #ifndef MONO_CROSS_COMPILE
2435
2436 static void print_process_map (void)
2437 {
2438 #ifdef __linux__
2439         FILE *fp = fopen ("/proc/self/maps", "r");
2440         char line [256];
2441
2442         if (fp == NULL) {
2443                 mono_runtime_printf_err ("no /proc/self/maps, not on linux?\n");
2444                 return;
2445         }
2446
2447         mono_runtime_printf_err ("/proc/self/maps:");
2448
2449         while (fgets (line, sizeof (line), fp)) {
2450                 // strip newline
2451                 size_t len = strlen (line) - 1;
2452                 if (len >= 0 && line [len] == '\n')
2453                         line [len] = '\0';
2454
2455                 mono_runtime_printf_err ("%s", line);
2456         }
2457
2458         fclose (fp);
2459 #else
2460         /* do nothing */
2461 #endif
2462 }
2463
2464 static gboolean handling_sigsegv = FALSE;
2465
2466 /*
2467  * mono_handle_native_crash:
2468  *
2469  *   Handle a native crash (e.g. SIGSEGV) while in native code by
2470  *   printing diagnostic information and aborting.
2471  */
2472 void
2473 mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2474 {
2475 #ifdef MONO_ARCH_USE_SIGACTION
2476         struct sigaction sa;
2477 #endif
2478         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2479
2480         gboolean is_sigsegv = !strcmp ("SIGSEGV", signal);
2481
2482         if (handling_sigsegv && is_sigsegv)
2483                 return;
2484
2485         if (mini_get_debug_options ()->suspend_on_sigsegv && is_sigsegv) {
2486                 mono_runtime_printf_err ("Received %s, suspending...", signal);
2487 #ifdef HOST_WIN32
2488                 while (1)
2489                         ;
2490 #else
2491                 while (1) {
2492                         sleep (1);
2493                 }
2494 #endif
2495         }
2496
2497         /* To prevent infinite loops when the stack walk causes a crash */
2498         if (is_sigsegv)
2499                 handling_sigsegv = TRUE;
2500
2501         /* !jit_tls means the thread was not registered with the runtime */
2502         if (jit_tls && mono_thread_internal_current ()) {
2503                 mono_runtime_printf_err ("Stacktrace:\n");
2504
2505                 /* FIXME: Is MONO_UNWIND_LOOKUP_IL_OFFSET correct here? */
2506                 mono_walk_stack (print_stack_frame_to_stderr, MONO_UNWIND_LOOKUP_IL_OFFSET, NULL);
2507         }
2508
2509         print_process_map ();
2510
2511 #ifdef HAVE_BACKTRACE_SYMBOLS
2512  {
2513         void *array [256];
2514         char **names;
2515         int i, size;
2516
2517         mono_runtime_printf_err ("\nNative stacktrace:\n");
2518
2519         size = backtrace (array, 256);
2520         names = backtrace_symbols (array, size);
2521         for (i =0; i < size; ++i) {
2522                 mono_runtime_printf_err ("\t%s", names [i]);
2523         }
2524         g_free (names);
2525
2526         /* Try to get more meaningful information using gdb */
2527
2528 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2529         if (!mini_get_debug_options ()->no_gdb_backtrace) {
2530                 /* From g_spawn_command_line_sync () in eglib */
2531                 pid_t pid;
2532                 int status;
2533                 pid_t crashed_pid = getpid ();
2534
2535                 /*
2536                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2537                  * it will deadlock. Call the syscall directly instead.
2538                  */
2539 #if defined(PLATFORM_ANDROID)
2540                 /* SYS_fork is defined to be __NR_fork which is not defined in some ndk versions */
2541                 g_assert_not_reached ();
2542 #elif !defined(PLATFORM_MACOSX) && defined(SYS_fork)
2543                 pid = (pid_t) syscall (SYS_fork);
2544 #elif defined(PLATFORM_MACOSX) && HAVE_FORK
2545                 pid = (pid_t) fork ();
2546 #else
2547                 g_assert_not_reached ();
2548 #endif
2549
2550 #if defined (HAVE_PRCTL) && defined(PR_SET_PTRACER)
2551                 if (pid > 0) {
2552                         // Allow gdb to attach to the process even if ptrace_scope sysctl variable is set to
2553                         // a value other than 0 (the most permissive ptrace scope). Most modern Linux
2554                         // distributions set the scope to 1 which allows attaching only to direct children of
2555                         // the current process
2556                         prctl (PR_SET_PTRACER, pid, 0, 0, 0);
2557                 }
2558 #endif
2559                 if (pid == 0) {
2560                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2561
2562                         mono_gdb_render_native_backtraces (crashed_pid);
2563                         exit (1);
2564                 }
2565
2566                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2567                 waitpid (pid, &status, 0);
2568         }
2569 #endif
2570  }
2571 #else
2572 #ifdef PLATFORM_ANDROID
2573         /* set DUMPABLE for this process so debuggerd can attach with ptrace(2), see:
2574          * https://android.googlesource.com/platform/bionic/+/151da681000c07da3c24cd30a3279b1ca017f452/linker/debugger.cpp#206
2575          * this has changed on later versions of Android.  Also, we don't want to
2576          * set this on start-up as DUMPABLE has security implications. */
2577         prctl (PR_SET_DUMPABLE, 1);
2578
2579         mono_runtime_printf_err ("\nNo native Android stacktrace (see debuggerd output).\n");
2580 #endif
2581 #endif
2582
2583         /*
2584          * A SIGSEGV indicates something went very wrong so we can no longer depend
2585          * on anything working. So try to print out lots of diagnostics, starting 
2586          * with ones which have a greater chance of working.
2587          */
2588         mono_runtime_printf_err (
2589                          "\n"
2590                          "=================================================================\n"
2591                          "Got a %s while executing native code. This usually indicates\n"
2592                          "a fatal error in the mono runtime or one of the native libraries \n"
2593                          "used by your application.\n"
2594                          "=================================================================\n",
2595                         signal);
2596
2597 #ifdef MONO_ARCH_USE_SIGACTION
2598         sa.sa_handler = SIG_DFL;
2599         sigemptyset (&sa.sa_mask);
2600         sa.sa_flags = 0;
2601
2602         /* Remove our SIGABRT handler */
2603         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2604
2605         /* On some systems we get a SIGILL when calling abort (), because it might
2606          * fail to raise SIGABRT */
2607         g_assert (sigaction (SIGILL, &sa, NULL) != -1);
2608 #endif
2609
2610         if (!mono_do_crash_chaining) {
2611                 /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2612 #if defined (PLATFORM_ANDROID)
2613                 exit (-1);
2614 #else
2615                 abort ();
2616 #endif
2617         }
2618 }
2619
2620 #else
2621
2622 void
2623 mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2624 {
2625         g_assert_not_reached ();
2626 }
2627
2628 #endif /* !MONO_CROSS_COMPILE */
2629
2630 static void
2631 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2632 {
2633         MonoInternalThread *thread = mono_thread_internal_current ();
2634 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2635         MonoContext ctx;
2636 #endif
2637         GString* text;
2638         char *name;
2639         GError *error = NULL;
2640
2641         if (!thread)
2642                 return;
2643
2644         text = g_string_new (0);
2645         if (thread->name) {
2646                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2647                 g_assert (!error);
2648                 g_string_append_printf (text, "\n\"%s\"", name);
2649                 g_free (name);
2650         }
2651         else if (thread->threadpool_thread)
2652                 g_string_append (text, "\n\"<threadpool thread>\"");
2653         else
2654                 g_string_append (text, "\n\"<unnamed thread>\"");
2655
2656         g_string_append_printf (text, " tid=0x%p this=0x%p ", (gpointer)(gsize)thread->tid, thread);
2657         mono_thread_internal_describe (thread, text);
2658         g_string_append (text, "\n");
2659
2660 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2661         if (start_ctx) {
2662                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2663         } else if (!sigctx)
2664                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2665         else
2666                 mono_sigctx_to_monoctx (sigctx, &ctx);
2667
2668         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2669 #else
2670         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2671 #endif
2672
2673         mono_runtime_printf ("%s", text->str);
2674
2675 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2676         OutputDebugStringA(text->str);
2677 #endif
2678
2679         g_string_free (text, TRUE);
2680         mono_runtime_stdout_fflush ();
2681 }
2682
2683 /*
2684  * mono_print_thread_dump:
2685  *
2686  *   Print information about the current thread to stdout.
2687  * SIGCTX can be NULL, allowing this to be called from gdb.
2688  */
2689 void
2690 mono_print_thread_dump (void *sigctx)
2691 {
2692         mono_print_thread_dump_internal (sigctx, NULL);
2693 }
2694
2695 void
2696 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2697 {
2698         mono_print_thread_dump_internal (NULL, ctx);
2699 }
2700
2701 /*
2702  * mono_resume_unwind:
2703  *
2704  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2705  * unwinding.
2706  */
2707 void
2708 mono_resume_unwind (MonoContext *ctx)
2709 {
2710         MONO_REQ_GC_UNSAFE_MODE;
2711
2712         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2713         MonoContext new_ctx;
2714
2715         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2716         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2717         new_ctx = *ctx;
2718
2719         mono_handle_exception_internal (&new_ctx, (MonoObject *)jit_tls->resume_state.ex_obj, TRUE, NULL);
2720
2721         mono_restore_context (&new_ctx);
2722 }
2723
2724 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2725
2726 typedef struct {
2727         MonoJitInfo *ji;
2728         MonoContext ctx;
2729         MonoJitExceptionInfo *ei;
2730 } FindHandlerBlockData;
2731
2732 static gboolean
2733 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2734 {
2735         int i;
2736         gpointer ip;
2737         FindHandlerBlockData *pdata = (FindHandlerBlockData *)data;
2738         MonoJitInfo *ji = frame->ji;
2739
2740         if (!ji)
2741                 return FALSE;
2742
2743         ip = MONO_CONTEXT_GET_IP (ctx);
2744
2745         for (i = 0; i < ji->num_clauses; ++i) {
2746                 MonoJitExceptionInfo *ei = ji->clauses + i;
2747                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2748                         continue;
2749                 /*If ip points to the first instruction it means the handler block didn't start
2750                  so we can leave its execution to the EH machinery*/
2751                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2752                         pdata->ji = ji;
2753                         pdata->ei = ei;
2754                         pdata->ctx = *ctx;
2755                         break;
2756                 }
2757         }
2758         return FALSE;
2759 }
2760
2761
2762 static gpointer
2763 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2764 {
2765         int i;
2766         MonoJitExceptionInfo *clause = NULL;
2767         gpointer ip;
2768
2769         ip = MONO_CONTEXT_GET_IP (ctx);
2770
2771         for (i = 0; i < ji->num_clauses; ++i) {
2772                 clause = &ji->clauses [i];
2773                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2774                         continue;
2775                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2776                         break;
2777         }
2778
2779         /*no matching finally */
2780         if (i == ji->num_clauses)
2781                 return NULL;
2782
2783         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2784         if (ip == clause->handler_start)
2785                 return NULL;
2786
2787         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2788 }
2789
2790 /*
2791  * Finds the bottom handler block running and install a block guard if needed.
2792  */
2793 gboolean
2794 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2795 {
2796         FindHandlerBlockData data = { 0 };
2797         MonoJitTlsData *jit_tls = (MonoJitTlsData *)ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2798         gpointer resume_ip;
2799
2800 #ifndef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT
2801         if (mono_aot_only)
2802                 return FALSE;
2803 #endif
2804
2805         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2806          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2807          */
2808         if (!jit_tls || jit_tls->handler_block_return_address)
2809                 return FALSE;
2810
2811         /* Do an async safe stack walk */
2812         mono_thread_info_set_is_async_context (TRUE);
2813         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data);
2814         mono_thread_info_set_is_async_context (FALSE);
2815
2816         if (!data.ji)
2817                 return FALSE;
2818
2819         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2820
2821         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2822         if (resume_ip == NULL)
2823                 return FALSE;
2824
2825         jit_tls->handler_block_return_address = resume_ip;
2826         jit_tls->handler_block = data.ei;
2827
2828         return TRUE;
2829 }
2830
2831 static gboolean
2832 mono_current_thread_has_handle_block_guard (void)
2833 {
2834         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2835         return jit_tls && jit_tls->handler_block_return_address != NULL;
2836 }
2837
2838 #else
2839 gboolean
2840 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2841 {
2842         return FALSE;
2843 }
2844
2845 static gboolean
2846 mono_current_thread_has_handle_block_guard (void)
2847 {
2848         return FALSE;
2849 }
2850
2851 #endif
2852
2853 void
2854 mono_set_cast_details (MonoClass *from, MonoClass *to)
2855 {
2856         MonoJitTlsData *jit_tls = NULL;
2857
2858         if (mini_get_debug_options ()->better_cast_details) {
2859                 jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2860                 jit_tls->class_cast_from = from;
2861                 jit_tls->class_cast_to = to;
2862         }
2863 }
2864
2865
2866 /*returns false if the thread is not attached*/
2867 gboolean
2868 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
2869 {
2870 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2871         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2872         if (!thread) {
2873                 ctx->valid = FALSE;
2874                 return FALSE;
2875         }
2876
2877         if (sigctx) {
2878                 mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
2879
2880                 ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2881                 ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2882                 ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2883         }
2884         else {
2885                 mono_thread_state_init (ctx);
2886         }
2887
2888         if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF])
2889                 return FALSE;
2890
2891         ctx->valid = TRUE;
2892         return TRUE;
2893 #else
2894         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
2895         return FALSE;
2896 #endif
2897 }
2898
2899 void
2900 mono_thread_state_init (MonoThreadUnwindState *ctx)
2901 {
2902         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2903
2904 #if defined(MONO_CROSS_COMPILE)
2905         ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
2906 #elif MONO_ARCH_HAS_MONO_CONTEXT
2907         MONO_CONTEXT_GET_CURRENT (ctx->ctx);
2908 #else
2909         g_error ("Use a null sigctx requires a working mono-context");
2910 #endif
2911
2912         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2913         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2914         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
2915         ctx->valid = TRUE;
2916 }
2917
2918
2919 gboolean
2920 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
2921 {
2922         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2923         if (!thread) {
2924                 ctx->valid = FALSE;
2925                 return FALSE;
2926         }
2927
2928         ctx->ctx = *mctx;
2929         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2930         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2931         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2932         ctx->valid = TRUE;
2933         return TRUE;
2934 }
2935
2936 /*returns false if the thread is not attached*/
2937 gboolean
2938 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
2939 {
2940         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2941         MONO_ARCH_CONTEXT_DEF
2942
2943         mono_arch_flush_register_windows ();
2944
2945         if (!thread || !thread->jit_data) {
2946                 ctx->valid = FALSE;
2947                 return FALSE;
2948         }
2949 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
2950         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
2951 #else
2952         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
2953 #endif
2954                 
2955         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2956         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2957         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2958         ctx->valid = TRUE;
2959         return TRUE;
2960 }
2961
2962 static void
2963 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
2964 {
2965         mono_handle_exception (ctx, (MonoObject *)exc);
2966         mono_restore_context (ctx);
2967 }
2968
2969 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
2970 void
2971 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
2972 {
2973 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
2974         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2975         jit_tls->ex_ctx = *ctx;
2976
2977         mono_arch_setup_async_callback (ctx, async_cb, user_data);
2978 #else
2979         g_error ("This target doesn't support mono_arch_setup_async_callback");
2980 #endif
2981 }
2982
2983 /*
2984  * mono_restore_context:
2985  *
2986  *   Call the architecture specific restore context function.
2987  */
2988 void
2989 mono_restore_context (MonoContext *ctx)
2990 {
2991         static void (*restore_context) (MonoContext *);
2992
2993         if (!restore_context)
2994                 restore_context = (void (*)(MonoContext *))mono_get_restore_context ();
2995         restore_context (ctx);
2996         g_assert_not_reached ();
2997 }
2998
2999 /*
3000  * mono_jinfo_get_unwind_info:
3001  *
3002  *   Return the unwind info for JI.
3003  */
3004 guint8*
3005 mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
3006 {
3007         if (ji->from_aot)
3008                 return mono_aot_get_unwind_info (ji, unwind_info_len);
3009         else
3010                 return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len);
3011 }
3012
3013 int
3014 mono_jinfo_get_epilog_size (MonoJitInfo *ji)
3015 {
3016         MonoArchEHJitInfo *info;
3017
3018         info = mono_jit_info_get_arch_eh_info (ji);
3019         g_assert (info);
3020
3021         return info->epilog_size;
3022 }
3023
3024 /*
3025  * LLVM/Bitcode exception handling.
3026  */
3027
3028 static void
3029 throw_exception (MonoObject *ex, gboolean rethrow)
3030 {
3031         MONO_REQ_GC_UNSAFE_MODE;
3032
3033         MonoError error;
3034         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3035         MonoException *mono_ex;
3036
3037         if (!mono_object_isinst_checked (ex, mono_defaults.exception_class, &error)) {
3038                 mono_error_assert_ok (&error);
3039                 mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error);
3040                 mono_error_assert_ok (&error);
3041                 jit_tls->thrown_non_exc = mono_gchandle_new (ex, FALSE);
3042         }
3043         else
3044                 mono_ex = (MonoException*)ex;
3045
3046         // Note: Not pinned
3047         jit_tls->thrown_exc = mono_gchandle_new ((MonoObject*)mono_ex, FALSE);
3048
3049         if (!rethrow) {
3050 #ifdef MONO_ARCH_HAVE_UNWIND_BACKTRACE
3051                 GList *l, *ips = NULL;
3052                 GList *trace;
3053
3054                 _Unwind_Backtrace (build_stack_trace, &ips);
3055                 /* The list contains ip-gshared info pairs */
3056                 trace = NULL;
3057                 ips = g_list_reverse (ips);
3058                 for (l = ips; l; l = l->next) {
3059                         trace = g_list_append (trace, l->data);
3060                         trace = g_list_append (trace, NULL);
3061                 }
3062                 MonoArray *ips_arr = mono_glist_to_array (trace, mono_defaults.int_class, &error);
3063                 mono_error_assert_ok (&error);
3064                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
3065                 g_list_free (l);
3066                 g_list_free (trace);
3067 #endif
3068         }
3069
3070         mono_llvm_cpp_throw_exception ();
3071 }
3072
3073 void
3074 mono_llvm_throw_exception (MonoObject *ex)
3075 {
3076         throw_exception (ex, FALSE);
3077 }
3078
3079 void
3080 mono_llvm_rethrow_exception (MonoObject *ex)
3081 {
3082         throw_exception (ex, TRUE);
3083 }
3084
3085 void
3086 mono_llvm_raise_exception (MonoException *e)
3087 {
3088         mono_llvm_throw_exception ((MonoObject*)e);
3089 }
3090
3091 void
3092 mono_llvm_throw_corlib_exception (guint32 ex_token_index)
3093 {
3094         guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
3095         MonoException *ex;
3096
3097         ex = mono_exception_from_token (mono_defaults.exception_class->image, ex_token);
3098
3099         mono_llvm_throw_exception ((MonoObject*)ex);
3100 }
3101
3102 /*
3103  * mono_llvm_resume_exception:
3104  *
3105  *   Resume exception propagation.
3106  */
3107 void
3108 mono_llvm_resume_exception (void)
3109 {
3110         mono_llvm_cpp_throw_exception ();
3111 }
3112
3113 /*
3114  * mono_llvm_load_exception:
3115  *
3116  *   Return the currently thrown exception.
3117  */
3118 MonoObject *
3119 mono_llvm_load_exception (void)
3120 {
3121         MonoError error;
3122         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3123
3124         MonoException *mono_ex = (MonoException*)mono_gchandle_get_target (jit_tls->thrown_exc);
3125
3126         if (mono_ex->trace_ips) {
3127                 GList *trace_ips = NULL;
3128                 gpointer ip = __builtin_return_address (0);
3129
3130                 size_t upper = mono_array_length (mono_ex->trace_ips);
3131
3132                 for (int i = 0; i < upper; i+= 2) {
3133                         gpointer curr_ip = mono_array_get (mono_ex->trace_ips, gpointer, i);
3134                         gpointer curr_info = mono_array_get (mono_ex->trace_ips, gpointer, i + 1);
3135                         trace_ips = g_list_append (trace_ips, curr_ip);
3136                         trace_ips = g_list_append (trace_ips, curr_info);
3137
3138                         if (ip == curr_ip)
3139                                 break;
3140                 }
3141
3142                 // FIXME: Does this work correctly for rethrows?
3143                 // We may be discarding useful information
3144                 // when this gets GC'ed
3145                 MonoArray *ips_arr = mono_glist_to_array (trace_ips, mono_defaults.int_class, &error);
3146                 mono_error_assert_ok (&error);
3147                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
3148                 g_list_free (trace_ips);
3149
3150                 // FIXME:
3151                 //MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex));
3152         } else {
3153                 MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_array_new_checked (mono_domain_get (), mono_defaults.int_class, 0, &error));
3154                 mono_error_assert_ok (&error);
3155                 MONO_OBJECT_SETREF (mono_ex, stack_trace, mono_array_new_checked (mono_domain_get (), mono_defaults.stack_frame_class, 0, &error));
3156                 mono_error_assert_ok (&error);
3157         }
3158
3159         return &mono_ex->object;
3160 }
3161
3162 /*
3163  * mono_llvm_clear_exception:
3164  *
3165  *   Mark the currently thrown exception as handled.
3166  */
3167 void
3168 mono_llvm_clear_exception (void)
3169 {
3170         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3171         mono_gchandle_free (jit_tls->thrown_exc);
3172         jit_tls->thrown_exc = 0;
3173         if (jit_tls->thrown_non_exc)
3174                 mono_gchandle_free (jit_tls->thrown_non_exc);
3175         jit_tls->thrown_non_exc = 0;
3176
3177         mono_memory_barrier ();
3178 }
3179
3180 /*
3181  * mono_llvm_match_exception:
3182  *
3183  *   Return the innermost clause containing REGION_START-REGION_END which can handle
3184  * the current exception.
3185  */
3186 gint32
3187 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj)
3188 {
3189         MonoError error;
3190         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3191         MonoObject *exc;
3192         gint32 index = -1;
3193
3194         g_assert (jit_tls->thrown_exc);
3195         exc = mono_gchandle_get_target (jit_tls->thrown_exc);
3196         if (jit_tls->thrown_non_exc) {
3197                 /*
3198                  * Have to unwrap RuntimeWrappedExceptions if the
3199                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
3200                  */
3201                 if (!wrap_non_exception_throws (jinfo_get_method (jinfo)))
3202                         exc = mono_gchandle_get_target (jit_tls->thrown_non_exc);
3203         }
3204
3205         for (int i = 0; i < jinfo->num_clauses; i++) {
3206                 MonoJitExceptionInfo *ei = &jinfo->clauses [i];
3207                 MonoClass *catch_class;
3208
3209                 if (! (ei->try_offset == region_start && ei->try_offset + ei->try_len == region_end) )
3210                         continue;
3211
3212                 catch_class = ei->data.catch_class;
3213                 if (mono_class_is_open_constructed_type (&catch_class->byval_arg)) {
3214                         MonoGenericContext context;
3215                         MonoType *inflated_type;
3216
3217                         g_assert (rgctx || this_obj);
3218                         context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
3219                         inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
3220                         mono_error_assert_ok (&error); /* FIXME don't swallow the error */
3221
3222                         catch_class = mono_class_from_mono_type (inflated_type);
3223                         mono_metadata_free_type (inflated_type);
3224                 }
3225
3226                 // FIXME: Handle edge cases handled in get_exception_catch_class
3227                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (exc, catch_class, &error)) {
3228                         index = ei->clause_index;
3229                         break;
3230                 } else
3231                         mono_error_assert_ok (&error);
3232                 
3233                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3234                         g_assert_not_reached ();
3235                 }
3236         }
3237
3238         return index;
3239 }
3240
3241 #ifdef ENABLE_LLVM
3242 _Unwind_Reason_Code 
3243 mono_debug_personality (int a, _Unwind_Action b,
3244 uint64_t c, struct _Unwind_Exception *d, struct _Unwind_Context *e)
3245 {
3246         g_assert_not_reached ();
3247 }
3248 #else
3249 void
3250 mono_debug_personality (void);
3251
3252 void
3253 mono_debug_personality (void)
3254 {
3255         g_assert_not_reached ();
3256 }
3257 #endif