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