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