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