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