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