c69678b593d2c848366d33b2b398a1d5a0475bb9
[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                 //pid = fork ();
2492                 /*
2493                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2494                  * it will deadlock. Call the syscall directly instead.
2495                  */
2496                 pid = mono_runtime_syscall_fork ();
2497 #if defined (HAVE_PRCTL) && defined(PR_SET_PTRACER)
2498                 if (pid > 0) {
2499                         // Allow gdb to attach to the process even if ptrace_scope sysctl variable is set to
2500                         // a value other than 0 (the most permissive ptrace scope). Most modern Linux
2501                         // distributions set the scope to 1 which allows attaching only to direct children of
2502                         // the current process
2503                         prctl (PR_SET_PTRACER, pid, 0, 0, 0);
2504                 }
2505 #endif
2506                 if (pid == 0) {
2507                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2508
2509                         mono_gdb_render_native_backtraces (crashed_pid);
2510                         exit (1);
2511                 }
2512
2513                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2514                 waitpid (pid, &status, 0);
2515         }
2516 #endif
2517  }
2518 #else
2519         mono_exception_native_unwind (ctx, info);
2520 #endif
2521
2522         /*
2523          * A SIGSEGV indicates something went very wrong so we can no longer depend
2524          * on anything working. So try to print out lots of diagnostics, starting 
2525          * with ones which have a greater chance of working.
2526          */
2527         mono_runtime_printf_err (
2528                          "\n"
2529                          "=================================================================\n"
2530                          "Got a %s while executing native code. This usually indicates\n"
2531                          "a fatal error in the mono runtime or one of the native libraries \n"
2532                          "used by your application.\n"
2533                          "=================================================================\n",
2534                         signal);
2535
2536
2537 #ifdef MONO_ARCH_USE_SIGACTION
2538
2539         /* Remove our SIGABRT handler */
2540         sa.sa_handler = SIG_DFL;
2541         sigemptyset (&sa.sa_mask);
2542         sa.sa_flags = 0;
2543
2544         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2545
2546 #endif
2547
2548         if (!mono_do_crash_chaining) {
2549                 /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2550 #if defined (PLATFORM_ANDROID)
2551                 exit (-1);
2552 #else
2553                 abort ();
2554 #endif
2555         }
2556 }
2557
2558 #else
2559
2560 void
2561 mono_handle_native_crash (const char *signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2562 {
2563         g_assert_not_reached ();
2564 }
2565
2566 #endif /* !MONO_CROSS_COMPILE */
2567
2568 static void
2569 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2570 {
2571         MonoInternalThread *thread = mono_thread_internal_current ();
2572 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2573         MonoContext ctx;
2574 #endif
2575         GString* text;
2576         char *name;
2577         GError *error = NULL;
2578
2579         if (!thread)
2580                 return;
2581
2582         text = g_string_new (0);
2583         if (thread->name) {
2584                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2585                 g_assert (!error);
2586                 g_string_append_printf (text, "\n\"%s\"", name);
2587                 g_free (name);
2588         }
2589         else if (thread->threadpool_thread)
2590                 g_string_append (text, "\n\"<threadpool thread>\"");
2591         else
2592                 g_string_append (text, "\n\"<unnamed thread>\"");
2593
2594         g_string_append_printf (text, " tid=0x%p this=0x%p ", (gpointer)(gsize)thread->tid, thread);
2595         mono_thread_internal_describe (thread, text);
2596         g_string_append (text, "\n");
2597
2598 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2599         if (start_ctx) {
2600                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2601         } else if (!sigctx)
2602                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2603         else
2604                 mono_sigctx_to_monoctx (sigctx, &ctx);
2605
2606         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2607 #else
2608         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2609 #endif
2610
2611         mono_runtime_printf ("%s", text->str);
2612
2613 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2614         OutputDebugStringA(text->str);
2615 #endif
2616
2617         g_string_free (text, TRUE);
2618         mono_runtime_stdout_fflush ();
2619 }
2620
2621 /*
2622  * mono_print_thread_dump:
2623  *
2624  *   Print information about the current thread to stdout.
2625  * SIGCTX can be NULL, allowing this to be called from gdb.
2626  */
2627 void
2628 mono_print_thread_dump (void *sigctx)
2629 {
2630         mono_print_thread_dump_internal (sigctx, NULL);
2631 }
2632
2633 void
2634 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2635 {
2636         mono_print_thread_dump_internal (NULL, ctx);
2637 }
2638
2639 /*
2640  * mono_resume_unwind:
2641  *
2642  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2643  * unwinding.
2644  */
2645 void
2646 mono_resume_unwind (MonoContext *ctx)
2647 {
2648         MONO_REQ_GC_UNSAFE_MODE;
2649
2650         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2651         MonoContext new_ctx;
2652
2653         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2654         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2655         new_ctx = *ctx;
2656
2657         mono_handle_exception_internal (&new_ctx, (MonoObject *)jit_tls->resume_state.ex_obj, TRUE, NULL);
2658
2659         mono_restore_context (&new_ctx);
2660 }
2661
2662 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2663
2664 typedef struct {
2665         MonoJitInfo *ji;
2666         MonoContext ctx;
2667         MonoJitExceptionInfo *ei;
2668 } FindHandlerBlockData;
2669
2670 static gboolean
2671 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2672 {
2673         int i;
2674         gpointer ip;
2675         FindHandlerBlockData *pdata = (FindHandlerBlockData *)data;
2676         MonoJitInfo *ji = frame->ji;
2677
2678         if (!ji)
2679                 return FALSE;
2680
2681         ip = MONO_CONTEXT_GET_IP (ctx);
2682
2683         for (i = 0; i < ji->num_clauses; ++i) {
2684                 MonoJitExceptionInfo *ei = ji->clauses + i;
2685                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2686                         continue;
2687                 /*If ip points to the first instruction it means the handler block didn't start
2688                  so we can leave its execution to the EH machinery*/
2689                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2690                         pdata->ji = ji;
2691                         pdata->ei = ei;
2692                         pdata->ctx = *ctx;
2693                         break;
2694                 }
2695         }
2696         return FALSE;
2697 }
2698
2699
2700 static gpointer
2701 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2702 {
2703         int i;
2704         MonoJitExceptionInfo *clause = NULL;
2705         gpointer ip;
2706
2707         ip = MONO_CONTEXT_GET_IP (ctx);
2708
2709         for (i = 0; i < ji->num_clauses; ++i) {
2710                 clause = &ji->clauses [i];
2711                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2712                         continue;
2713                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2714                         break;
2715         }
2716
2717         /*no matching finally */
2718         if (i == ji->num_clauses)
2719                 return NULL;
2720
2721         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2722         if (ip == clause->handler_start)
2723                 return NULL;
2724
2725         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2726 }
2727
2728 /*
2729  * Finds the bottom handler block running and install a block guard if needed.
2730  */
2731 gboolean
2732 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2733 {
2734         FindHandlerBlockData data = { 0 };
2735         MonoJitTlsData *jit_tls = (MonoJitTlsData *)ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2736         gpointer resume_ip;
2737
2738 #ifndef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT
2739         if (mono_aot_only)
2740                 return FALSE;
2741 #endif
2742
2743         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2744          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2745          */
2746         if (!jit_tls || jit_tls->handler_block_return_address)
2747                 return FALSE;
2748
2749         /* Do an async safe stack walk */
2750         mono_thread_info_set_is_async_context (TRUE);
2751         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data);
2752         mono_thread_info_set_is_async_context (FALSE);
2753
2754         if (!data.ji)
2755                 return FALSE;
2756
2757         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2758
2759         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2760         if (resume_ip == NULL)
2761                 return FALSE;
2762
2763         jit_tls->handler_block_return_address = resume_ip;
2764         jit_tls->handler_block = data.ei;
2765
2766         return TRUE;
2767 }
2768
2769 static gboolean
2770 mono_current_thread_has_handle_block_guard (void)
2771 {
2772         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2773         return jit_tls && jit_tls->handler_block_return_address != NULL;
2774 }
2775
2776 #else
2777 gboolean
2778 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2779 {
2780         return FALSE;
2781 }
2782
2783 static gboolean
2784 mono_current_thread_has_handle_block_guard (void)
2785 {
2786         return FALSE;
2787 }
2788
2789 #endif
2790
2791 void
2792 mono_set_cast_details (MonoClass *from, MonoClass *to)
2793 {
2794         MonoJitTlsData *jit_tls = NULL;
2795
2796         if (mini_get_debug_options ()->better_cast_details) {
2797                 jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2798                 jit_tls->class_cast_from = from;
2799                 jit_tls->class_cast_to = to;
2800         }
2801 }
2802
2803
2804 /*returns false if the thread is not attached*/
2805 gboolean
2806 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
2807 {
2808 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2809         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2810         if (!thread) {
2811                 ctx->valid = FALSE;
2812                 g_error ("Invoked mono_thread_state_init_from_sigctx from non-Mono thread");
2813                 return FALSE;
2814         }
2815
2816         if (sigctx) {
2817                 mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
2818
2819                 ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2820                 ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2821                 ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2822         }
2823         else {
2824                 mono_thread_state_init (ctx);
2825         }
2826
2827         if (!ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] || !ctx->unwind_data [MONO_UNWIND_DATA_LMF])
2828                 return FALSE;
2829
2830         ctx->valid = TRUE;
2831         return TRUE;
2832 #else
2833         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
2834         return FALSE;
2835 #endif
2836 }
2837
2838 void
2839 mono_thread_state_init (MonoThreadUnwindState *ctx)
2840 {
2841         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2842
2843 #if defined(MONO_CROSS_COMPILE)
2844         ctx->valid = FALSE; //A cross compiler doesn't need to suspend.
2845 #elif MONO_ARCH_HAS_MONO_CONTEXT
2846         MONO_CONTEXT_GET_CURRENT (ctx->ctx);
2847 #else
2848         g_error ("Use a null sigctx requires a working mono-context");
2849 #endif
2850
2851         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2852         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2853         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread ? thread->jit_data : NULL;
2854         ctx->valid = TRUE;
2855 }
2856
2857
2858 gboolean
2859 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
2860 {
2861         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2862         if (!thread) {
2863                 ctx->valid = FALSE;
2864                 return FALSE;
2865         }
2866
2867         ctx->ctx = *mctx;
2868         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2869         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2870         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2871         ctx->valid = TRUE;
2872         return TRUE;
2873 }
2874
2875 /*returns false if the thread is not attached*/
2876 gboolean
2877 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
2878 {
2879         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2880         MONO_ARCH_CONTEXT_DEF
2881
2882         mono_arch_flush_register_windows ();
2883
2884         if (!thread || !thread->jit_data) {
2885                 ctx->valid = FALSE;
2886                 return FALSE;
2887         }
2888 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
2889         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
2890 #else
2891         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
2892 #endif
2893                 
2894         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2895         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2896         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2897         ctx->valid = TRUE;
2898         return TRUE;
2899 }
2900
2901 static void
2902 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
2903 {
2904         mono_handle_exception (ctx, (MonoObject *)exc);
2905         mono_restore_context (ctx);
2906 }
2907
2908 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
2909 void
2910 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
2911 {
2912 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
2913         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2914         jit_tls->ex_ctx = *ctx;
2915
2916         mono_arch_setup_async_callback (ctx, async_cb, user_data);
2917 #else
2918         g_error ("This target doesn't support mono_arch_setup_async_callback");
2919 #endif
2920 }
2921
2922 /*
2923  * mono_restore_context:
2924  *
2925  *   Call the architecture specific restore context function.
2926  */
2927 void
2928 mono_restore_context (MonoContext *ctx)
2929 {
2930         static void (*restore_context) (MonoContext *);
2931
2932         if (!restore_context)
2933                 restore_context = (void (*)(MonoContext *))mono_get_restore_context ();
2934         restore_context (ctx);
2935         g_assert_not_reached ();
2936 }
2937
2938 /*
2939  * mono_jinfo_get_unwind_info:
2940  *
2941  *   Return the unwind info for JI.
2942  */
2943 guint8*
2944 mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
2945 {
2946         if (ji->from_aot)
2947                 return mono_aot_get_unwind_info (ji, unwind_info_len);
2948         else
2949                 return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len);
2950 }
2951
2952 int
2953 mono_jinfo_get_epilog_size (MonoJitInfo *ji)
2954 {
2955         MonoArchEHJitInfo *info;
2956
2957         info = mono_jit_info_get_arch_eh_info (ji);
2958         g_assert (info);
2959
2960         return info->epilog_size;
2961 }
2962
2963 /*
2964  * LLVM/Bitcode exception handling.
2965  */
2966
2967 static void
2968 throw_exception (MonoObject *ex, gboolean rethrow)
2969 {
2970         MONO_REQ_GC_UNSAFE_MODE;
2971
2972         MonoError error;
2973         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
2974         MonoException *mono_ex;
2975
2976         if (!mono_object_isinst_checked (ex, mono_defaults.exception_class, &error)) {
2977                 mono_error_assert_ok (&error);
2978                 mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error);
2979                 mono_error_assert_ok (&error);
2980                 jit_tls->thrown_non_exc = mono_gchandle_new (ex, FALSE);
2981         }
2982         else
2983                 mono_ex = (MonoException*)ex;
2984
2985         // Note: Not pinned
2986         jit_tls->thrown_exc = mono_gchandle_new ((MonoObject*)mono_ex, FALSE);
2987
2988         if (!rethrow) {
2989 #ifdef MONO_ARCH_HAVE_UNWIND_BACKTRACE
2990                 GList *l, *ips = NULL;
2991                 GList *trace;
2992
2993                 _Unwind_Backtrace (build_stack_trace, &ips);
2994                 /* The list contains ip-gshared info pairs */
2995                 trace = NULL;
2996                 ips = g_list_reverse (ips);
2997                 for (l = ips; l; l = l->next) {
2998                         trace = g_list_append (trace, l->data);
2999                         trace = g_list_append (trace, NULL);
3000                 }
3001                 MonoArray *ips_arr = mono_glist_to_array (trace, mono_defaults.int_class, &error);
3002                 mono_error_assert_ok (&error);
3003                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
3004                 g_list_free (l);
3005                 g_list_free (trace);
3006 #endif
3007         }
3008
3009         mono_llvm_cpp_throw_exception ();
3010 }
3011
3012 void
3013 mono_llvm_throw_exception (MonoObject *ex)
3014 {
3015         throw_exception (ex, FALSE);
3016 }
3017
3018 void
3019 mono_llvm_rethrow_exception (MonoObject *ex)
3020 {
3021         throw_exception (ex, TRUE);
3022 }
3023
3024 void
3025 mono_llvm_raise_exception (MonoException *e)
3026 {
3027         mono_llvm_throw_exception ((MonoObject*)e);
3028 }
3029
3030 void
3031 mono_llvm_throw_corlib_exception (guint32 ex_token_index)
3032 {
3033         guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
3034         MonoException *ex;
3035
3036         ex = mono_exception_from_token (mono_defaults.exception_class->image, ex_token);
3037
3038         mono_llvm_throw_exception ((MonoObject*)ex);
3039 }
3040
3041 /*
3042  * mono_llvm_resume_exception:
3043  *
3044  *   Resume exception propagation.
3045  */
3046 void
3047 mono_llvm_resume_exception (void)
3048 {
3049         mono_llvm_cpp_throw_exception ();
3050 }
3051
3052 /*
3053  * mono_llvm_load_exception:
3054  *
3055  *   Return the currently thrown exception.
3056  */
3057 MonoObject *
3058 mono_llvm_load_exception (void)
3059 {
3060         MonoError error;
3061         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3062
3063         MonoException *mono_ex = (MonoException*)mono_gchandle_get_target (jit_tls->thrown_exc);
3064
3065         if (mono_ex->trace_ips) {
3066                 GList *trace_ips = NULL;
3067                 gpointer ip = __builtin_return_address (0);
3068
3069                 size_t upper = mono_array_length (mono_ex->trace_ips);
3070
3071                 for (int i = 0; i < upper; i+= 2) {
3072                         gpointer curr_ip = mono_array_get (mono_ex->trace_ips, gpointer, i);
3073                         gpointer curr_info = mono_array_get (mono_ex->trace_ips, gpointer, i + 1);
3074                         trace_ips = g_list_append (trace_ips, curr_ip);
3075                         trace_ips = g_list_append (trace_ips, curr_info);
3076
3077                         if (ip == curr_ip)
3078                                 break;
3079                 }
3080
3081                 // FIXME: Does this work correctly for rethrows?
3082                 // We may be discarding useful information
3083                 // when this gets GC'ed
3084                 MonoArray *ips_arr = mono_glist_to_array (trace_ips, mono_defaults.int_class, &error);
3085                 mono_error_assert_ok (&error);
3086                 MONO_OBJECT_SETREF (mono_ex, trace_ips, ips_arr);
3087                 g_list_free (trace_ips);
3088
3089                 // FIXME:
3090                 //MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex));
3091         } else {
3092                 MONO_OBJECT_SETREF (mono_ex, trace_ips, mono_array_new_checked (mono_domain_get (), mono_defaults.int_class, 0, &error));
3093                 mono_error_assert_ok (&error);
3094                 MONO_OBJECT_SETREF (mono_ex, stack_trace, mono_array_new_checked (mono_domain_get (), mono_defaults.stack_frame_class, 0, &error));
3095                 mono_error_assert_ok (&error);
3096         }
3097
3098         return &mono_ex->object;
3099 }
3100
3101 /*
3102  * mono_llvm_clear_exception:
3103  *
3104  *   Mark the currently thrown exception as handled.
3105  */
3106 void
3107 mono_llvm_clear_exception (void)
3108 {
3109         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3110         mono_gchandle_free (jit_tls->thrown_exc);
3111         jit_tls->thrown_exc = 0;
3112         if (jit_tls->thrown_non_exc)
3113                 mono_gchandle_free (jit_tls->thrown_non_exc);
3114         jit_tls->thrown_non_exc = 0;
3115
3116         mono_memory_barrier ();
3117 }
3118
3119 /*
3120  * mono_llvm_match_exception:
3121  *
3122  *   Return the innermost clause containing REGION_START-REGION_END which can handle
3123  * the current exception.
3124  */
3125 gint32
3126 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj)
3127 {
3128         MonoError error;
3129         MonoJitTlsData *jit_tls = mono_get_jit_tls ();
3130         MonoObject *exc;
3131         gint32 index = -1;
3132
3133         g_assert (jit_tls->thrown_exc);
3134         exc = mono_gchandle_get_target (jit_tls->thrown_exc);
3135         if (jit_tls->thrown_non_exc) {
3136                 /*
3137                  * Have to unwrap RuntimeWrappedExceptions if the
3138                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
3139                  */
3140                 if (!wrap_non_exception_throws (jinfo_get_method (jinfo)))
3141                         exc = mono_gchandle_get_target (jit_tls->thrown_non_exc);
3142         }
3143
3144         for (int i = 0; i < jinfo->num_clauses; i++) {
3145                 MonoJitExceptionInfo *ei = &jinfo->clauses [i];
3146                 MonoClass *catch_class;
3147
3148                 if (! (ei->try_offset == region_start && ei->try_offset + ei->try_len == region_end) )
3149                         continue;
3150
3151                 catch_class = ei->data.catch_class;
3152                 if (mono_class_is_open_constructed_type (&catch_class->byval_arg)) {
3153                         MonoGenericContext context;
3154                         MonoType *inflated_type;
3155
3156                         g_assert (rgctx || this_obj);
3157                         context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
3158                         inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
3159                         mono_error_assert_ok (&error); /* FIXME don't swallow the error */
3160
3161                         catch_class = mono_class_from_mono_type (inflated_type);
3162                         mono_metadata_free_type (inflated_type);
3163                 }
3164
3165                 // FIXME: Handle edge cases handled in get_exception_catch_class
3166                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (exc, catch_class, &error)) {
3167                         index = ei->clause_index;
3168                         break;
3169                 } else
3170                         mono_error_assert_ok (&error);
3171                 
3172                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3173                         g_assert_not_reached ();
3174                 }
3175         }
3176
3177         return index;
3178 }
3179
3180 #ifdef ENABLE_LLVM
3181 _Unwind_Reason_Code 
3182 mono_debug_personality (int a, _Unwind_Action b,
3183 uint64_t c, struct _Unwind_Exception *d, struct _Unwind_Context *e)
3184 {
3185         g_assert_not_reached ();
3186 }
3187 #else
3188 void
3189 mono_debug_personality (void);
3190
3191 void
3192 mono_debug_personality (void)
3193 {
3194         g_assert_not_reached ();
3195 }
3196 #endif