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