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