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