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