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