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