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