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