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