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