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