Merge pull request #1659 from alexanderkyte/stringbuilder-referencesource
[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
704                 sf->method_index = ji->from_aot ? mono_aot_find_method_index (method) : 0xffffff;
705                 sf->method_address = (gsize) ji->code_start;
706                 sf->native_offset = (char *)ip - (char *)ji->code_start;
707
708                 /*
709                  * mono_debug_lookup_source_location() returns both the file / line number information
710                  * and the IL offset.  Note that computing the IL offset is already an expensive
711                  * operation, so we shouldn't call this method twice.
712                  */
713                 location = mono_debug_lookup_source_location (jinfo_get_method (ji), sf->native_offset, domain);
714                 if (location) {
715                         sf->il_offset = location->il_offset;
716                 } else {
717                         SeqPoint sp;
718                         if (find_prev_seq_point_for_native_offset (domain, jinfo_get_method (ji), sf->native_offset, NULL, &sp))
719                                 sf->il_offset = sp.il_offset;
720                         else
721                                 sf->il_offset = -1;
722                 }
723
724                 if (need_file_info) {
725                         if (location && location->source_file) {
726                                 MONO_OBJECT_SETREF (sf, filename, mono_string_new (domain, location->source_file));
727                                 sf->line = location->row;
728                                 sf->column = location->column;
729                         } else {
730                                 sf->line = sf->column = 0;
731                                 sf->filename = NULL;
732                         }
733                 }
734
735                 mono_debug_free_source_location (location);
736                 mono_array_setref (res, i, sf);
737         }
738
739         return res;
740 }
741
742 static void
743 mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
744 {
745         if (!start_ctx) {
746                 MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
747                 if (jit_tls && jit_tls->orig_ex_ctx_set)
748                         start_ctx = &jit_tls->orig_ex_ctx;
749         }
750         mono_walk_stack_with_ctx (func, start_ctx, unwind_options, user_data);
751 }
752 /**
753  * mono_walk_stack_with_ctx:
754  *
755  * Unwind the current thread starting at @start_ctx.
756  * 
757  * If @start_ctx is null, we capture the current context.
758  */
759 void
760 mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
761 {
762         MonoContext extra_ctx;
763         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
764         MONO_ARCH_CONTEXT_DEF
765
766         if (!thread || !thread->jit_data)
767                 return;
768
769         if (!start_ctx) {
770                 mono_arch_flush_register_windows ();
771
772 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
773                 MONO_INIT_CONTEXT_FROM_CURRENT (&extra_ctx);
774 #else
775                 MONO_INIT_CONTEXT_FROM_FUNC (&extra_ctx, mono_walk_stack_with_ctx);
776 #endif
777                 start_ctx = &extra_ctx;
778         }
779
780         mono_walk_stack_full (func, start_ctx, mono_domain_get (), thread->jit_data, mono_get_lmf (), unwind_options, user_data);
781 }
782
783 /**
784  * mono_walk_stack_with_state:
785  *
786  * Unwind a thread described by @state.
787  *
788  * State must be valid (state->valid == TRUE).
789  *
790  * If you are using this function to unwind another thread, make sure it is suspended.
791  * 
792  * If @state is null, we capture the current context.
793  */
794 void
795 mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, MonoUnwindOptions unwind_options, void *user_data)
796 {
797         MonoThreadUnwindState extra_state;
798         if (!state) {
799                 g_assert (!mono_thread_info_is_async_context ());
800                 if (!mono_thread_state_init_from_current (&extra_state))
801                         return;
802                 state = &extra_state;
803         }
804
805         g_assert (state->valid);
806
807         mono_walk_stack_full (func,
808                 &state->ctx, 
809                 state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
810                 state->unwind_data [MONO_UNWIND_DATA_JIT_TLS],
811                 state->unwind_data [MONO_UNWIND_DATA_LMF],
812                 unwind_options, user_data);
813 }
814
815 void
816 mono_walk_stack (MonoJitStackWalk func, MonoUnwindOptions options, void *user_data)
817 {
818         MonoThreadUnwindState state;
819         if (!mono_thread_state_init_from_current (&state))
820                 return;
821         mono_walk_stack_with_state (func, &state, options, user_data);
822 }
823
824 /**
825  * mono_walk_stack_full:
826  * @func: callback to call for each stack frame
827  * @domain: starting appdomain, can be NULL to use the current domain
828  * @unwind_options: what extra information the unwinder should gather
829  * @start_ctx: starting state of the stack walk, can be NULL.
830  * @thread: the thread whose stack to walk, can be NULL to use the current thread
831  * @lmf: the LMF of @thread, can be NULL to use the LMF of the current thread
832  * @user_data: data passed to the callback
833  *
834  * This function walks the stack of a thread, starting from the state
835  * represented by start_ctx. For each frame the callback
836  * function is called with the relevant info. The walk ends when no more
837  * managed stack frames are found or when the callback returns a TRUE value.
838  */
839 static void
840 mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data)
841 {
842         gint il_offset, i;
843         MonoContext ctx, new_ctx;
844         StackFrameInfo frame;
845         gboolean res;
846         mgreg_t *reg_locations [MONO_MAX_IREGS];
847         mgreg_t *new_reg_locations [MONO_MAX_IREGS];
848         gboolean get_reg_locations = unwind_options & MONO_UNWIND_REG_LOCATIONS;
849         gboolean async = mono_thread_info_is_async_context ();
850
851         g_assert (start_ctx);
852         g_assert (domain);
853         g_assert (jit_tls);
854         /*The LMF will be null if the target have no managed frames.*/
855         /* g_assert (lmf); */
856
857         if (async)
858                 g_assert (unwind_options == MONO_UNWIND_NONE);
859
860         memcpy (&ctx, start_ctx, sizeof (MonoContext));
861         memset (reg_locations, 0, sizeof (reg_locations));
862
863         while (MONO_CONTEXT_GET_SP (&ctx) < jit_tls->end_of_stack) {
864                 frame.lmf = lmf;
865                 res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, get_reg_locations ? new_reg_locations : NULL, &frame);
866                 if (!res)
867                         return;
868
869                 if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji) {
870                         MonoDebugSourceLocation *source;
871
872                         source = mono_debug_lookup_source_location (jinfo_get_method (frame.ji), frame.native_offset, domain);
873                         if (source) {
874                                 il_offset = source->il_offset;
875                         } else {
876                                 SeqPoint sp;
877                                 if (find_prev_seq_point_for_native_offset (domain, jinfo_get_method (frame.ji), frame.native_offset, NULL, &sp))
878                                         il_offset = sp.il_offset;
879                                 else
880                                         il_offset = -1;
881                         }
882                         mono_debug_free_source_location (source);
883                 } else
884                         il_offset = -1;
885
886                 frame.il_offset = il_offset;
887
888                 if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji) {
889                         frame.actual_method = get_method_from_stack_frame (frame.ji, get_generic_info_from_stack_frame (frame.ji, &ctx));
890                 } else {
891                         frame.actual_method = frame.method;
892                 }
893
894                 if (get_reg_locations)
895                         frame.reg_locations = reg_locations;
896
897                 if (func (&frame, &ctx, user_data))
898                         return;
899
900                 if (get_reg_locations) {
901                         for (i = 0; i < MONO_MAX_IREGS; ++i)
902                                 if (new_reg_locations [i])
903                                         reg_locations [i] = new_reg_locations [i];
904                 }
905                 
906                 ctx = new_ctx;
907         }
908 }
909
910 MonoBoolean
911 ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, 
912                           MonoReflectionMethod **method, 
913                           gint32 *iloffset, gint32 *native_offset,
914                           MonoString **file, gint32 *line, gint32 *column)
915 {
916         MonoDomain *domain = mono_domain_get ();
917         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
918         MonoLMF *lmf = mono_get_lmf ();
919         MonoJitInfo *ji = NULL;
920         MonoContext ctx, new_ctx;
921         MonoDebugSourceLocation *location;
922         MonoMethod *jmethod = NULL, *actual_method;
923         StackFrameInfo frame;
924         gboolean res;
925
926         MONO_ARCH_CONTEXT_DEF;
927
928         mono_arch_flush_register_windows ();
929
930 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
931         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx);
932 #else
933         MONO_INIT_CONTEXT_FROM_FUNC (&ctx, ves_icall_get_frame_info);
934 #endif
935
936         new_ctx = ctx;
937         do {
938                 ctx = new_ctx;
939                 res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, &frame);
940                 if (!res)
941                         return FALSE;
942
943                 if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE || frame.type == FRAME_TYPE_DEBUGGER_INVOKE)
944                         continue;
945
946                 ji = frame.ji;
947                 *native_offset = frame.native_offset;
948
949                 /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */
950                 jmethod = jinfo_get_method (ji);
951                 if (jmethod->wrapper_type != MONO_WRAPPER_NONE && jmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && jmethod->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE)
952                         continue;
953                 skip--;
954         } while (skip >= 0);
955
956         actual_method = get_method_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, &ctx));
957
958         mono_gc_wbarrier_generic_store (method, (MonoObject*) mono_method_get_object (domain, actual_method, NULL));
959
960         location = mono_debug_lookup_source_location (jmethod, *native_offset, domain);
961         if (location)
962                 *iloffset = location->il_offset;
963         else
964                 *iloffset = 0;
965
966         if (need_file_info) {
967                 if (location) {
968                         mono_gc_wbarrier_generic_store (file, (MonoObject*) mono_string_new (domain, location->source_file));
969                         *line = location->row;
970                         *column = location->column;
971                 } else {
972                         *file = NULL;
973                         *line = *column = 0;
974                 }
975         }
976
977         mono_debug_free_source_location (location);
978
979         return TRUE;
980 }
981
982 typedef struct {
983         guint32 skips;
984         MonoSecurityFrame *frame;
985 } MonoFrameSecurityInfo;
986
987 static gboolean
988 callback_get_first_frame_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
989 {
990         MonoFrameSecurityInfo *si = (MonoFrameSecurityInfo*) data;
991         MonoJitInfo *ji = frame->ji;
992         MonoMethod *method;
993
994         if (!ji)
995                 return FALSE;
996
997         /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
998         method = jinfo_get_method (ji);
999         if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
1000             method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
1001             method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
1002             method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
1003             method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
1004                 return FALSE;
1005         }
1006
1007         if (si->skips > 0) {
1008                 si->skips--;
1009                 return FALSE;
1010         }
1011
1012         si->frame = mono_declsec_create_frame (frame->domain, ji);
1013
1014         /* Stop - we only want the first frame (e.g. LinkDemand and InheritanceDemand) */
1015         return TRUE;
1016 }
1017
1018 /**
1019  * ves_icall_System_Security_SecurityFrame_GetSecurityFrame:
1020  * @skip: the number of stack frames to skip
1021  *
1022  * This function returns a the security informations of a single stack frame 
1023  * (after the skipped ones). This is required for [NonCas]LinkDemand[Choice]
1024  * and [NonCas]InheritanceDemand[Choice] as only the caller security is 
1025  * evaluated.
1026  */
1027 MonoSecurityFrame*
1028 ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip)
1029 {
1030         MonoFrameSecurityInfo si;
1031
1032         si.skips = skip;
1033         si.frame = NULL;
1034
1035         mono_walk_stack (callback_get_first_frame_security_info, MONO_UNWIND_DEFAULT, &si);
1036
1037         return (si.skips == 0) ? si.frame : NULL;
1038 }
1039
1040
1041 typedef struct {
1042         guint32 skips;
1043         MonoArray *stack;
1044         guint32 count;
1045         guint32 maximum;
1046 } MonoSecurityStack;
1047
1048 static void
1049 grow_array (MonoSecurityStack *stack)
1050 {
1051         MonoDomain *domain = mono_domain_get ();
1052         guint32 newsize = (stack->maximum << 1);
1053         MonoArray *newstack = mono_array_new (domain, mono_defaults.runtimesecurityframe_class, newsize);
1054         int i;
1055         for (i=0; i < stack->maximum; i++) {
1056                 gpointer frame = mono_array_get (stack->stack, gpointer, i);
1057                 mono_array_setref (newstack, i, frame);
1058         }
1059         stack->maximum = newsize;
1060         stack->stack = newstack;
1061 }
1062
1063 static gboolean
1064 callback_get_stack_frames_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
1065 {
1066         MonoSecurityStack *ss = (MonoSecurityStack*) data;
1067         MonoJitInfo *ji = frame->ji;
1068         MonoMethod *method;
1069
1070         if (!ji)
1071                 return FALSE;
1072
1073         /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
1074         method = jinfo_get_method (ji);
1075         if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
1076             method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
1077             method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
1078             method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
1079             method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
1080                 return FALSE;
1081         }
1082
1083         if (ss->skips > 0) {
1084                 ss->skips--;
1085                 return FALSE;
1086         }
1087
1088         if (ss->count == ss->maximum)
1089                 grow_array (ss);
1090
1091         mono_array_setref (ss->stack, ss->count++, mono_declsec_create_frame (frame->domain, ji));
1092
1093         /* continue down the stack */
1094         return FALSE;
1095 }
1096
1097 static MonoArray *
1098 glist_to_array (GList *list, MonoClass *eclass) 
1099 {
1100         MonoDomain *domain = mono_domain_get ();
1101         MonoArray *res;
1102         int len, i;
1103
1104         if (!list)
1105                 return NULL;
1106
1107         len = g_list_length (list);
1108         res = mono_array_new (domain, eclass, len);
1109
1110         for (i = 0; list; list = list->next, i++)
1111                 mono_array_set (res, gpointer, i, list->data);
1112
1113         return res;
1114 }
1115
1116 /**
1117  * ves_icall_System_Security_SecurityFrame_GetSecurityStack:
1118  * @skip: the number of stack frames to skip
1119  *
1120  * This function returns an managed array of containing the security
1121  * informations for each frame (after the skipped ones). This is used for
1122  * [NonCas]Demand[Choice] where the complete evaluation of the stack is 
1123  * required.
1124  */
1125 MonoArray*
1126 ves_icall_System_Security_SecurityFrame_GetSecurityStack (gint32 skip)
1127 {
1128         MonoSecurityStack ss;
1129
1130 #if     defined(__ia64__) || defined(__s390__) || defined(__s390x__)
1131         skip--;
1132 #endif
1133
1134         ss.skips = skip;
1135         ss.count = 0;
1136         ss.maximum = MONO_CAS_INITIAL_STACK_SIZE;
1137         ss.stack = mono_array_new (mono_domain_get (), mono_defaults.runtimesecurityframe_class, ss.maximum);
1138         mono_walk_stack (callback_get_stack_frames_security_info, MONO_UNWIND_DEFAULT, &ss);
1139         /* g_warning ("STACK RESULT: %d out of %d", ss.count, ss.maximum); */
1140         return ss.stack;
1141 }
1142
1143 static MonoClass*
1144 get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
1145 {
1146         MonoClass *catch_class = ei->data.catch_class;
1147         MonoType *inflated_type;
1148         MonoGenericContext context;
1149
1150         /*MonoJitExceptionInfo::data is an union used by filter and finally clauses too.*/
1151         if (!catch_class || ei->flags != MONO_EXCEPTION_CLAUSE_NONE)
1152                 return NULL;
1153
1154         if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
1155                 return catch_class;
1156         context = get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx));
1157
1158         /* FIXME: we shouldn't inflate but instead put the
1159            type in the rgctx and fetch it from there.  It
1160            might be a good idea to do this lazily, i.e. only
1161            when the exception is actually thrown, so as not to
1162            waste space for exception clauses which might never
1163            be encountered. */
1164         inflated_type = mono_class_inflate_generic_type (&catch_class->byval_arg, &context);
1165         catch_class = mono_class_from_mono_type (inflated_type);
1166         mono_metadata_free_type (inflated_type);
1167
1168         return catch_class;
1169 }
1170
1171 /*
1172  * mini_jit_info_table_find:
1173  *
1174  *   Same as mono_jit_info_table_find, but search all the domains of the current thread
1175  * if ADDR is not found in DOMAIN. The domain where the method was found is stored into
1176  * OUT_DOMAIN if it is not NULL.
1177  */
1178 MonoJitInfo*
1179 mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
1180 {
1181         MonoJitInfo *ji;
1182         MonoInternalThread *t = mono_thread_internal_current ();
1183         gpointer *refs;
1184
1185         if (out_domain)
1186                 *out_domain = NULL;
1187
1188         ji = mono_jit_info_table_find (domain, addr);
1189         if (ji) {
1190                 if (out_domain)
1191                         *out_domain = domain;
1192                 return ji;
1193         }
1194
1195         /* maybe it is shared code, so we also search in the root domain */
1196         if (domain != mono_get_root_domain ()) {
1197                 ji = mono_jit_info_table_find (mono_get_root_domain (), addr);
1198                 if (ji) {
1199                         if (out_domain)
1200                                 *out_domain = mono_get_root_domain ();
1201                         return ji;
1202                 }
1203         }
1204
1205         if (!t)
1206                 return NULL;
1207
1208         refs = (t->appdomain_refs) ? *(gpointer *) t->appdomain_refs : NULL;
1209         for (; refs && *refs; refs++) {
1210                 if (*refs != domain && *refs != mono_get_root_domain ()) {
1211                         ji = mono_jit_info_table_find ((MonoDomain*) *refs, addr);
1212                         if (ji) {
1213                                 if (out_domain)
1214                                         *out_domain = (MonoDomain*) *refs;
1215                                 return ji;
1216                         }
1217                 }
1218         }
1219
1220         return NULL;
1221 }
1222
1223 /*
1224  * wrap_non_exception_throws:
1225  *
1226  *   Determine whenever M's assembly has a RuntimeCompatibilityAttribute with the
1227  * WrapNonExceptionThrows flag set.
1228  */
1229 static gboolean
1230 wrap_non_exception_throws (MonoMethod *m)
1231 {
1232         MonoAssembly *ass = m->klass->image->assembly;
1233         MonoCustomAttrInfo* attrs;
1234         static MonoClass *klass;
1235         int i;
1236         gboolean val = FALSE;
1237
1238         g_assert (ass);
1239         if (ass->wrap_non_exception_throws_inited)
1240                 return ass->wrap_non_exception_throws;
1241
1242         klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1243
1244         attrs = mono_custom_attrs_from_assembly (ass);
1245         if (attrs) {
1246                 for (i = 0; i < attrs->num_attrs; ++i) {
1247                         MonoCustomAttrEntry *attr = &attrs->attrs [i];
1248                         const gchar *p;
1249                         int num_named, named_type, name_len;
1250                         char *name;
1251
1252                         if (!attr->ctor || attr->ctor->klass != klass)
1253                                 continue;
1254                         /* Decode the RuntimeCompatibilityAttribute. See reflection.c */
1255                         p = (const char*)attr->data;
1256                         g_assert (read16 (p) == 0x0001);
1257                         p += 2;
1258                         num_named = read16 (p);
1259                         if (num_named != 1)
1260                                 continue;
1261                         p += 2;
1262                         named_type = *p;
1263                         p ++;
1264                         /* data_type = *p; */
1265                         p ++;
1266                         /* Property */
1267                         if (named_type != 0x54)
1268                                 continue;
1269                         name_len = mono_metadata_decode_blob_size (p, &p);
1270                         name = g_malloc (name_len + 1);
1271                         memcpy (name, p, name_len);
1272                         name [name_len] = 0;
1273                         p += name_len;
1274                         g_assert (!strcmp (name, "WrapNonExceptionThrows"));
1275                         g_free (name);
1276                         /* The value is a BOOLEAN */
1277                         val = *p;
1278                 }
1279                 mono_custom_attrs_free (attrs);
1280         }
1281
1282         ass->wrap_non_exception_throws = val;
1283         mono_memory_barrier ();
1284         ass->wrap_non_exception_throws_inited = TRUE;
1285
1286         return val;
1287 }
1288
1289 #ifndef MONO_ARCH_STACK_GROWS_UP
1290 #define DOES_STACK_GROWS_UP 1
1291 #else
1292 #define DOES_STACK_GROWS_UP 0
1293 #endif
1294
1295 #define MAX_UNMANAGED_BACKTRACE 128
1296 static MonoArray*
1297 build_native_trace (void)
1298 {
1299 /* This puppy only makes sense on mobile, IOW, ARM. */
1300 #if defined (HAVE_BACKTRACE_SYMBOLS) && defined (TARGET_ARM)
1301         MonoArray *res;
1302         void *native_trace [MAX_UNMANAGED_BACKTRACE];
1303         int size = backtrace (native_trace, MAX_UNMANAGED_BACKTRACE);
1304         int i;
1305
1306         if (!size)
1307                 return NULL;
1308         res = mono_array_new (mono_domain_get (), mono_defaults.int_class, size);
1309
1310         for (i = 0; i < size; i++)
1311                 mono_array_set (res, gpointer, i, native_trace [i]);
1312         return res;
1313 #else
1314         return NULL;
1315 #endif
1316 }
1317
1318 #define setup_managed_stacktrace_information() do {     \
1319         if (mono_ex && !initial_trace_ips) {    \
1320                 trace_ips = g_list_reverse (trace_ips); \
1321                 MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (trace_ips, mono_defaults.int_class));   \
1322                 MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ());  \
1323                 if (has_dynamic_methods)        \
1324                         /* These methods could go away anytime, so compute the stack trace now */       \
1325                         MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex));      \
1326         }       \
1327         g_list_free (trace_ips);        \
1328         trace_ips = NULL;       \
1329 } while (0)
1330 /*
1331  * mono_handle_exception_internal_first_pass:
1332  *
1333  *   The first pass of exception handling. Unwind the stack until a catch clause which can catch
1334  * OBJ is found. Run the index of the filter clause which caught the exception into
1335  * OUT_FILTER_IDX. Return TRUE if the exception is caught, FALSE otherwise.
1336  */
1337 static gboolean
1338 mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception)
1339 {
1340         MonoDomain *domain = mono_domain_get ();
1341         MonoJitInfo *ji = NULL;
1342         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1343         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1344         MonoLMF *lmf = mono_get_lmf ();
1345         MonoArray *initial_trace_ips = NULL;
1346         GList *trace_ips = NULL;
1347         MonoException *mono_ex;
1348         gboolean stack_overflow = FALSE;
1349         MonoContext initial_ctx;
1350         MonoMethod *method;
1351         int frame_count = 0;
1352         gboolean has_dynamic_methods = FALSE;
1353         gint32 filter_idx;
1354         int i;
1355         MonoObject *ex_obj;
1356
1357         g_assert (ctx != NULL);
1358
1359         if (obj == domain->stack_overflow_ex)
1360                 stack_overflow = TRUE;
1361
1362         mono_ex = (MonoException*)obj;
1363         initial_trace_ips = mono_ex->trace_ips;
1364
1365         if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1366                 mono_ex = (MonoException*)obj;
1367                 initial_trace_ips = mono_ex->trace_ips;
1368         } else {
1369                 mono_ex = NULL;
1370         }
1371
1372         if (!call_filter)
1373                 call_filter = mono_get_call_filter ();
1374
1375         g_assert (jit_tls->end_of_stack);
1376         g_assert (jit_tls->abort_func);
1377
1378         if (out_filter_idx)
1379                 *out_filter_idx = -1;
1380         if (out_ji)
1381                 *out_ji = NULL;
1382         if (out_prev_ji)
1383                 *out_prev_ji = NULL;
1384         filter_idx = 0;
1385         initial_ctx = *ctx;
1386
1387         while (1) {
1388                 MonoContext new_ctx;
1389                 guint32 free_stack;
1390                 int clause_index_start = 0;
1391                 gboolean unwind_res = TRUE;
1392                 
1393                 StackFrameInfo frame;
1394
1395                 if (out_prev_ji)
1396                         *out_prev_ji = ji;
1397
1398                 unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1399                 if (unwind_res) {
1400                         if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
1401                                 *ctx = new_ctx;
1402                                 continue;
1403                         }
1404                         g_assert (frame.type == FRAME_TYPE_MANAGED);
1405                         ji = frame.ji;
1406                 }
1407
1408                 if (!unwind_res) {
1409                         setup_managed_stacktrace_information ();
1410                         return FALSE;
1411                 }
1412
1413                 frame_count ++;
1414                 method = jinfo_get_method (ji);
1415                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1416
1417                 if (mini_get_debug_options ()->reverse_pinvoke_exceptions && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
1418                         g_error ("A native frame was found while unwinding the stack after an exception.\n"
1419                                          "The native frame called the managed method:\n%s\n",
1420                                          mono_method_full_name (method, TRUE));
1421                 }
1422
1423                 if (method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
1424                         /* 
1425                          * Avoid overwriting the stack trace if the exception is
1426                          * rethrown. Also avoid giant stack traces during a stack
1427                          * overflow.
1428                          */
1429                         if (!initial_trace_ips && (frame_count < 1000)) {
1430                                 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
1431                                 trace_ips = g_list_prepend (trace_ips,
1432                                                                                         get_generic_info_from_stack_frame (ji, ctx));
1433                         }
1434                 }
1435
1436                 if (method->dynamic)
1437                         has_dynamic_methods = TRUE;
1438
1439                 if (stack_overflow) {
1440                         if (DOES_STACK_GROWS_UP)
1441                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1442                         else
1443                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1444                 } else {
1445                         free_stack = 0xffffff;
1446                 }
1447                                 
1448                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1449                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1450                         gboolean filtered = FALSE;
1451
1452                         /* 
1453                          * During stack overflow, wait till the unwinding frees some stack
1454                          * space before running handlers/finalizers.
1455                          */
1456                         if (free_stack <= (64 * 1024))
1457                                 continue;
1458
1459                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1460                                 /* catch block */
1461                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1462
1463                                 /*
1464                                  * Have to unwrap RuntimeWrappedExceptions if the
1465                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1466                                  */
1467                                 if (non_exception && !wrap_non_exception_throws (method))
1468                                         ex_obj = non_exception;
1469                                 else
1470                                         ex_obj = obj;
1471
1472                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1473                                         gboolean is_user_frame = method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD;
1474 #ifndef DISABLE_PERFCOUNTERS
1475                                         mono_perfcounters->exceptions_filters++;
1476 #endif
1477                                         /*
1478                                         Here's the thing, if this is a filter clause done by a wrapper like runtime invoke, we don't want to
1479                                         trim the stackframe since if it returns FALSE we lose information.
1480
1481                                         FIXME Not 100% sure if it's a good idea even with user clauses.
1482                                         */
1483                                         if (is_user_frame)
1484                                                 setup_managed_stacktrace_information ();
1485
1486                                         if (ji->from_llvm) {
1487 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1488                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1489 #else
1490                                                 g_assert_not_reached ();
1491 #endif
1492                                         } else {
1493                                                 /* store the exception object in bp + ei->exvar_offset */
1494                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1495                                         }
1496
1497                                         mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
1498                                         filtered = call_filter (ctx, ei->data.filter);
1499                                         mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
1500                                         if (filtered && out_filter_idx)
1501                                                 *out_filter_idx = filter_idx;
1502                                         if (out_ji)
1503                                                 *out_ji = ji;
1504                                         filter_idx ++;
1505
1506                                         if (filtered) {
1507                                                 if (!is_user_frame)
1508                                                         setup_managed_stacktrace_information ();
1509                                                 /* mono_debugger_agent_handle_exception () needs this */
1510                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1511                                                 return TRUE;
1512                                         }
1513                                 }
1514
1515                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) {
1516                                         setup_managed_stacktrace_information ();
1517
1518                                         if (out_ji)
1519                                                 *out_ji = ji;
1520
1521                                         /* mono_debugger_agent_handle_exception () needs this */
1522                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1523                                         return TRUE;
1524                                 }
1525                         }
1526                 }
1527
1528                 *ctx = new_ctx;
1529         }
1530
1531         g_assert_not_reached ();
1532 }
1533
1534 /**
1535  * mono_handle_exception_internal:
1536  * @ctx: saved processor state
1537  * @obj: the exception object
1538  * @resume: whenever to resume unwinding based on the state in MonoJitTlsData.
1539  */
1540 static gboolean
1541 mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume, MonoJitInfo **out_ji)
1542 {
1543         MonoDomain *domain = mono_domain_get ();
1544         MonoJitInfo *ji, *prev_ji;
1545         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1546         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1547         MonoLMF *lmf = mono_get_lmf ();
1548         MonoException *mono_ex;
1549         gboolean stack_overflow = FALSE;
1550         MonoContext initial_ctx;
1551         MonoMethod *method;
1552         int frame_count = 0;
1553         gint32 filter_idx, first_filter_idx = 0;
1554         int i;
1555         MonoObject *ex_obj;
1556         MonoObject *non_exception = NULL;
1557
1558         g_assert (ctx != NULL);
1559         if (!obj) {
1560                 MonoException *ex = mono_get_exception_null_reference ();
1561                 MONO_OBJECT_SETREF (ex, message, mono_string_new (domain, "Object reference not set to an instance of an object"));
1562                 obj = (MonoObject *)ex;
1563         } 
1564
1565         /*
1566          * Allocate a new exception object instead of the preconstructed ones.
1567          */
1568         if (obj == domain->stack_overflow_ex) {
1569                 /*
1570                  * It is not a good idea to try and put even more pressure on the little stack available.
1571                  * obj = mono_get_exception_stack_overflow ();
1572                  */
1573                 stack_overflow = TRUE;
1574         }
1575         else if (obj == domain->null_reference_ex) {
1576                 obj = mono_get_exception_null_reference ();
1577         }
1578
1579         if (!mono_object_isinst (obj, mono_defaults.exception_class)) {
1580                 non_exception = obj;
1581                 obj = mono_get_exception_runtime_wrapped (obj);
1582         }
1583
1584         mono_ex = (MonoException*)obj;
1585
1586         if (mini_get_debug_options ()->suspend_on_exception) {
1587                 mono_runtime_printf_err ("Exception thrown, suspending...");
1588                 while (1)
1589                         ;
1590         }
1591
1592         if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1593                 mono_ex = (MonoException*)obj;
1594         } else {
1595                 mono_ex = NULL;
1596         }
1597
1598         if (mono_ex && jit_tls->class_cast_from) {
1599                 if (!strcmp (mono_ex->object.vtable->klass->name, "InvalidCastException")) {
1600                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1601                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1602                         char *msg = g_strdup_printf ("Unable to cast object of type '%s' to type '%s'.", from_name, to_name);
1603                         mono_ex->message = mono_string_new (domain, msg);
1604                         g_free (from_name);
1605                         g_free (to_name);
1606                         g_free (msg);
1607                 }
1608                 if (!strcmp (mono_ex->object.vtable->klass->name, "ArrayTypeMismatchException")) {
1609                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1610                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1611                         char *msg = g_strdup_printf ("Source array of type '%s' cannot be cast to destination array type '%s'.", from_name, to_name);
1612                         mono_ex->message = mono_string_new (domain, msg);
1613                         g_free (from_name);
1614                         g_free (to_name);
1615                         g_free (msg);
1616                 }
1617         }
1618
1619         if (!call_filter)
1620                 call_filter = mono_get_call_filter ();
1621
1622         g_assert (jit_tls->end_of_stack);
1623         g_assert (jit_tls->abort_func);
1624
1625         /*
1626          * We set orig_ex_ctx_set to TRUE/FALSE around profiler calls to make sure it doesn't
1627          * end up being TRUE on any code path.
1628          */
1629         memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
1630
1631         if (!resume) {
1632                 gboolean res;
1633
1634                 MonoContext ctx_cp = *ctx;
1635                 if (mono_trace_is_enabled ()) {
1636                         MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
1637                         MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
1638                         MonoObject *message;
1639                         const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
1640                         char *msg = NULL;
1641                         MonoObject *exc = NULL;
1642                         if (get_message == NULL) {
1643                                 message = NULL;
1644                         } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
1645                                 message = NULL;
1646                                 msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
1647                         } else {
1648                                 message = mono_runtime_invoke (get_message, obj, NULL, &exc);
1649                                 
1650                         }
1651                         if (msg == NULL) {
1652                                 msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
1653                         }
1654                         g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)GetCurrentThreadId (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg);
1655                         g_free (msg);
1656                         if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
1657                                 mono_print_thread_dump_from_ctx (ctx);
1658                 }
1659                 jit_tls->orig_ex_ctx_set = TRUE;
1660                 mono_profiler_exception_thrown (obj);
1661                 jit_tls->orig_ex_ctx_set = FALSE;
1662
1663                 res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
1664
1665                 if (!res) {
1666                         if (mini_get_debug_options ()->break_on_exc)
1667                                 G_BREAKPOINT ();
1668                         mono_debugger_agent_handle_exception (obj, ctx, NULL);
1669
1670                         if (mini_get_debug_options ()->suspend_on_unhandled) {
1671                                 mono_runtime_printf_err ("Unhandled exception, suspending...");
1672                                 while (1)
1673                                         ;
1674                         }
1675
1676                         // FIXME: This runs managed code so it might cause another stack overflow when
1677                         // we are handling a stack overflow
1678                         mono_unhandled_exception (obj);
1679                 } else {
1680                         gboolean unhandled = FALSE;
1681
1682                         /*
1683                          * The exceptions caught by the mono_runtime_invoke () calls in mono_async_invoke () needs to be treated as
1684                          * unhandled (#669836).
1685                          * FIXME: The check below is hackish, but its hard to distinguish these runtime invoke calls from others
1686                          * in the runtime.
1687                          */
1688                         if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
1689                                 if (prev_ji) {
1690                                         MonoInternalThread *thread = mono_thread_internal_current ();
1691                                         if (jinfo_get_method (prev_ji) == thread->async_invoke_method)
1692                                                 unhandled = TRUE;
1693                                 }
1694                         }
1695                         if (unhandled)
1696                                 mono_debugger_agent_handle_exception (obj, ctx, NULL);
1697                         else
1698                                 mono_debugger_agent_handle_exception (obj, ctx, &ctx_cp);
1699                 }
1700         }
1701
1702         if (out_ji)
1703                 *out_ji = NULL;
1704         filter_idx = 0;
1705         initial_ctx = *ctx;
1706
1707         while (1) {
1708                 MonoContext new_ctx;
1709                 guint32 free_stack;
1710                 int clause_index_start = 0;
1711                 gboolean unwind_res = TRUE;
1712                 
1713                 if (resume) {
1714                         resume = FALSE;
1715                         ji = jit_tls->resume_state.ji;
1716                         new_ctx = jit_tls->resume_state.new_ctx;
1717                         clause_index_start = jit_tls->resume_state.clause_index;
1718                         lmf = jit_tls->resume_state.lmf;
1719                         first_filter_idx = jit_tls->resume_state.first_filter_idx;
1720                         filter_idx = jit_tls->resume_state.filter_idx;
1721                 } else {
1722                         StackFrameInfo frame;
1723
1724                         unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1725                         if (unwind_res) {
1726                                 if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
1727                                         *ctx = new_ctx;
1728                                         continue;
1729                                 }
1730                                 g_assert (frame.type == FRAME_TYPE_MANAGED);
1731                                 ji = frame.ji;
1732                         }
1733                 }
1734
1735                 if (!unwind_res) {
1736                         *(mono_get_lmf_addr ()) = lmf;
1737
1738                         jit_tls->abort_func (obj);
1739                         g_assert_not_reached ();
1740                 }
1741
1742                 method = jinfo_get_method (ji);
1743                 frame_count ++;
1744                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1745
1746                 if (stack_overflow) {
1747                         if (DOES_STACK_GROWS_UP)
1748                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1749                         else
1750                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1751                 } else {
1752                         free_stack = 0xffffff;
1753                 }
1754                                 
1755                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1756                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1757                         gboolean filtered = FALSE;
1758
1759                         /* 
1760                          * During stack overflow, wait till the unwinding frees some stack
1761                          * space before running handlers/finalizers.
1762                          */
1763                         if (free_stack <= (64 * 1024))
1764                                 continue;
1765
1766                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1767                                 /* catch block */
1768                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1769
1770                                 /*
1771                                  * Have to unwrap RuntimeWrappedExceptions if the
1772                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1773                                  */
1774                                 if (non_exception && !wrap_non_exception_throws (method))
1775                                         ex_obj = non_exception;
1776                                 else
1777                                         ex_obj = obj;
1778
1779                                 if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
1780                                         if (ji->from_llvm) {
1781 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1782                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1783 #else
1784                                                 g_assert_not_reached ();
1785 #endif
1786                                         } else {
1787                                                 /* store the exception object in bp + ei->exvar_offset */
1788                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1789                                         }
1790                                 }
1791
1792                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1793                                         /* 
1794                                          * Filter clauses should only be run in the 
1795                                          * first pass of exception handling.
1796                                          */
1797                                         filtered = (filter_idx == first_filter_idx);
1798                                         filter_idx ++;
1799                                 }
1800
1801                                 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
1802                                          mono_object_isinst (ex_obj, catch_class)) || filtered) {
1803                                         /*
1804                                          * This guards against the situation that we abort a thread that is executing a finally clause
1805                                          * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
1806                                          * check for this situation here and resume interruption if we are below the guarded block.
1807                                          */
1808                                         if (G_UNLIKELY (jit_tls->handler_block_return_address)) {
1809                                                 gboolean is_outside = FALSE;
1810                                                 gpointer prot_bp = MONO_CONTEXT_GET_BP (&jit_tls->handler_block_context);
1811                                                 gpointer catch_bp = MONO_CONTEXT_GET_BP (ctx);
1812                                                 //FIXME make this stack direction aware
1813                                                 if (catch_bp > prot_bp) {
1814                                                         is_outside = TRUE;
1815                                                 } else if (catch_bp == prot_bp) {
1816                                                         /* Can be either try { try { } catch {} } finally {} or try { try { } finally {} } catch {}
1817                                                          * So we check if the catch handler_start is protected by the guarded handler protected region
1818                                                          *
1819                                                          * Assumptions:
1820                                                          *      If there is an outstanding guarded_block return address, it means the current thread must be aborted.
1821                                                          *      This is the only way to reach out the guarded block as other cases are handled by the trampoline.
1822                                                          *      There aren't any further finally/fault handler blocks down the stack over this exception.
1823                                                          *   This must be ensured by the code that installs the guard trampoline.
1824                                                          */
1825                                                         g_assert (ji == mini_jit_info_table_find (domain, MONO_CONTEXT_GET_IP (&jit_tls->handler_block_context), NULL));
1826
1827                                                         if (!is_address_protected (ji, jit_tls->handler_block, ei->handler_start)) {
1828                                                                 is_outside = TRUE;
1829                                                         }
1830                                                 }
1831                                                 if (is_outside) {
1832                                                         jit_tls->handler_block_return_address = NULL;
1833                                                         jit_tls->handler_block = NULL;
1834                                                         mono_thread_resume_interruption (); /*We ignore the exception here, it will be raised later*/
1835                                                 }
1836                                         }
1837
1838                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1839                                                 g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1840                                         jit_tls->orig_ex_ctx_set = TRUE;
1841                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1842                                         jit_tls->orig_ex_ctx_set = FALSE;
1843                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1844                                         mono_set_lmf (lmf);
1845 #ifndef DISABLE_PERFCOUNTERS
1846                                         mono_perfcounters->exceptions_depth += frame_count;
1847 #endif
1848                                         if (obj == domain->stack_overflow_ex)
1849                                                 jit_tls->handling_stack_ovf = FALSE;
1850
1851                                         return 0;
1852                                 }
1853                                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
1854                                         (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT)) {
1855                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1856                                                 g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1857                                         jit_tls->orig_ex_ctx_set = TRUE;
1858                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1859                                         jit_tls->orig_ex_ctx_set = FALSE;
1860                                         call_filter (ctx, ei->handler_start);
1861                                 }
1862                                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
1863                                         (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
1864                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1865                                                 g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1866                                         jit_tls->orig_ex_ctx_set = TRUE;
1867                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1868                                         jit_tls->orig_ex_ctx_set = FALSE;
1869 #ifndef DISABLE_PERFCOUNTERS
1870                                         mono_perfcounters->exceptions_finallys++;
1871 #endif
1872                                         mono_set_lmf (lmf);
1873                                         if (ji->from_llvm) {
1874                                                 /* 
1875                                                  * LLVM compiled finally handlers follow the design
1876                                                  * of the c++ ehabi, i.e. they call a resume function
1877                                                  * at the end instead of returning to the caller.
1878                                                  * So save the exception handling state,
1879                                                  * mono_resume_unwind () will call us again to continue
1880                                                  * the unwinding.
1881                                                  */
1882                                                 jit_tls->resume_state.ex_obj = obj;
1883                                                 jit_tls->resume_state.ji = ji;
1884                                                 jit_tls->resume_state.clause_index = i + 1;
1885                                                 jit_tls->resume_state.ctx = *ctx;
1886                                                 jit_tls->resume_state.new_ctx = new_ctx;
1887                                                 jit_tls->resume_state.lmf = lmf;
1888                                                 jit_tls->resume_state.first_filter_idx = first_filter_idx;
1889                                                 jit_tls->resume_state.filter_idx = filter_idx;
1890                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1891                                                 return 0;
1892                                         } else {
1893                                                 call_filter (ctx, ei->handler_start);
1894                                         }
1895                                 }
1896                         }
1897                 }
1898
1899                 jit_tls->orig_ex_ctx_set = TRUE;
1900                 mono_profiler_exception_method_leave (method);
1901                 jit_tls->orig_ex_ctx_set = FALSE;
1902
1903                 *ctx = new_ctx;
1904         }
1905
1906         g_assert_not_reached ();
1907 }
1908
1909 /**
1910  * mono_debugger_run_finally:
1911  * @start_ctx: saved processor state
1912  *
1913  * This method is called by the Mono Debugger to call all `finally' clauses of the
1914  * current stack frame.  It's used when the user issues a `return' command to make
1915  * the current stack frame return.  After returning from this method, the debugger
1916  * unwinds the stack one frame and gives control back to the user.
1917  *
1918  * NOTE: This method is only used when running inside the Mono Debugger.
1919  */
1920 void
1921 mono_debugger_run_finally (MonoContext *start_ctx)
1922 {
1923         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1924         MonoDomain *domain = mono_domain_get ();
1925         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1926         MonoLMF *lmf = mono_get_lmf ();
1927         MonoContext ctx, new_ctx;
1928         MonoJitInfo *ji, rji;
1929         int i;
1930
1931         ctx = *start_ctx;
1932
1933         ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
1934         if (!ji || ji == (gpointer)-1)
1935                 return;
1936
1937         if (!call_filter)
1938                 call_filter = mono_get_call_filter ();
1939
1940         for (i = 0; i < ji->num_clauses; i++) {
1941                 MonoJitExceptionInfo *ei = &ji->clauses [i];
1942
1943                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
1944                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
1945                         call_filter (&ctx, ei->handler_start);
1946                 }
1947         }
1948 }
1949
1950 /**
1951  * mono_handle_exception:
1952  * @ctx: saved processor state
1953  * @obj: the exception object
1954  */
1955 gboolean
1956 mono_handle_exception (MonoContext *ctx, gpointer obj)
1957 {
1958 #ifndef DISABLE_PERFCOUNTERS
1959         mono_perfcounters->exceptions_thrown++;
1960 #endif
1961
1962         return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
1963 }
1964
1965 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
1966
1967 #ifndef MONO_ARCH_USE_SIGACTION
1968 #error "Can't use sigaltstack without sigaction"
1969 #endif
1970
1971 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
1972
1973 void
1974 mono_setup_altstack (MonoJitTlsData *tls)
1975 {
1976         size_t stsize = 0;
1977         stack_t sa;
1978         guint8 *staddr = NULL;
1979
1980         if (mono_running_on_valgrind ())
1981                 return;
1982
1983         mono_thread_info_get_stack_bounds (&staddr, &stsize);
1984
1985         g_assert (staddr);
1986
1987         tls->end_of_stack = staddr + stsize;
1988         tls->stack_size = stsize;
1989
1990         /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
1991
1992         tls->stack_ovf_guard_base = staddr + mono_pagesize ();
1993         tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
1994
1995         g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
1996
1997         if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
1998                 /* mprotect can fail for the main thread stack */
1999                 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);
2000                 g_assert (gaddr == tls->stack_ovf_guard_base);
2001                 tls->stack_ovf_valloced = TRUE;
2002         }
2003
2004         /* Setup an alternate signal stack */
2005         tls->signal_stack = mono_valloc (0, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON);
2006         tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2007
2008         g_assert (tls->signal_stack);
2009
2010         sa.ss_sp = tls->signal_stack;
2011         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2012         sa.ss_flags = 0;
2013         g_assert (sigaltstack (&sa, NULL) == 0);
2014
2015         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);
2016 }
2017
2018 void
2019 mono_free_altstack (MonoJitTlsData *tls)
2020 {
2021         stack_t sa;
2022         int err;
2023
2024         sa.ss_sp = tls->signal_stack;
2025         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2026         sa.ss_flags = SS_DISABLE;
2027         err = sigaltstack  (&sa, NULL);
2028         g_assert (err == 0);
2029
2030         if (tls->signal_stack)
2031                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE);
2032         if (tls->stack_ovf_valloced)
2033                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size);
2034         else
2035                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
2036 }
2037
2038 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2039
2040 void
2041 mono_setup_altstack (MonoJitTlsData *tls)
2042 {
2043 }
2044
2045 void
2046 mono_free_altstack (MonoJitTlsData *tls)
2047 {
2048 }
2049
2050 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2051
2052 static gboolean
2053 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
2054 {
2055         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
2056         /* we need to leave some room for throwing the exception */
2057         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
2058                 unprotect_size -= mono_pagesize ();
2059         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
2060          * is sufficient stack
2061          */
2062         //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);
2063         if (unprotect_size)
2064                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
2065         return unprotect_size == jit_tls->stack_ovf_guard_size;
2066 }
2067
2068 static G_GNUC_UNUSED void
2069 try_more_restore (void)
2070 {
2071         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2072         if (try_restore_stack_protection (jit_tls, 500))
2073                 jit_tls->restore_stack_prot = NULL;
2074 }
2075
2076 static G_GNUC_UNUSED void
2077 restore_stack_protection (void)
2078 {
2079         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2080         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
2081         /* if we can't restore the stack protection, keep a callback installed so
2082          * we'll try to restore as much stack as we can at each return from unmanaged
2083          * code.
2084          */
2085         if (try_restore_stack_protection (jit_tls, 4096))
2086                 jit_tls->restore_stack_prot = NULL;
2087         else
2088                 jit_tls->restore_stack_prot = try_more_restore_tramp;
2089         /* here we also throw a stack overflow exception */
2090         ex->trace_ips = NULL;
2091         ex->stack_trace = NULL;
2092         mono_raise_exception (ex);
2093 }
2094
2095 gpointer
2096 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
2097 {
2098         void (*func)(void) = (gpointer)tramp_data;
2099         func ();
2100         return NULL;
2101 }
2102
2103 gboolean
2104 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, guint8* fault_addr)
2105 {
2106         /* we got a stack overflow in the soft-guard pages
2107          * There are two cases:
2108          * 1) managed code caused the overflow: we unprotect the soft-guard page
2109          * and let the arch-specific code trigger the exception handling mechanism
2110          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
2111          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
2112          * and hope we can continue with those enabled, at least until the hard-guard page
2113          * is hit. The alternative to continuing here is to just print a message and abort.
2114          * We may add in the future the code to protect the pages again in the codepath
2115          * when we return from unmanaged to managed code.
2116          */
2117         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2118                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2119                 /* we unprotect the minimum amount we can */
2120                 guint32 guard_size;
2121                 gboolean handled = FALSE;
2122
2123                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2124                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2125                         guard_size -= mono_pagesize ();
2126                 }
2127                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2128                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2129                 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);
2130 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2131                 if (ji) {
2132                         mono_arch_handle_altstack_exception (ctx, siginfo, fault_addr, TRUE);
2133                         handled = TRUE;
2134                 }
2135 #endif
2136                 if (!handled) {
2137                         /* We print a message: after this even managed stack overflows
2138                          * may crash the runtime
2139                          */
2140                         mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2141                         if (!jit_tls->handling_stack_ovf) {
2142                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2143                                 jit_tls->handling_stack_ovf = 1;
2144                         } else {
2145                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2146                         }
2147                 }
2148                 return TRUE;
2149         }
2150         return FALSE;
2151 }
2152
2153 typedef struct {
2154         MonoMethod *omethod;
2155         int count;
2156 } PrintOverflowUserData;
2157
2158 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2159 static gboolean
2160 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2161 {
2162         MonoMethod *method = NULL;
2163         PrintOverflowUserData *user_data = data;
2164         gchar *location;
2165
2166         if (frame->ji)
2167                 method = jinfo_get_method (frame->ji);
2168
2169         if (method) {
2170                 if (user_data->count == 0) {
2171                         /* The first frame is in its prolog, so a line number cannot be computed */
2172                         user_data->count ++;
2173                         return FALSE;
2174                 }
2175
2176                 /* If this is a one method overflow, skip the other instances */
2177                 if (method == user_data->omethod)
2178                         return FALSE;
2179
2180                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2181                 mono_runtime_printf_err ("  %s", location);
2182                 g_free (location);
2183
2184                 if (user_data->count == 1) {
2185                         mono_runtime_printf_err ("  <...>");
2186                         user_data->omethod = method;
2187                 } else {
2188                         user_data->omethod = NULL;
2189                 }
2190
2191                 user_data->count ++;
2192         } else
2193                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2194
2195         return FALSE;
2196 }
2197 #endif
2198
2199 void
2200 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2201 {
2202 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2203         PrintOverflowUserData ud;
2204         MonoContext mctx;
2205 #endif
2206
2207         /* we don't do much now, but we can warn the user with a useful message */
2208         mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2209
2210 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2211         mono_sigctx_to_monoctx (ctx, &mctx);
2212                         
2213         mono_runtime_printf_err ("Stacktrace:");
2214
2215         memset (&ud, 0, sizeof (ud));
2216
2217         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2218 #else
2219         if (ji && jinfo_get_method (ji))
2220                 mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
2221         else
2222                 mono_runtime_printf_err ("At <unmanaged>.");
2223 #endif
2224
2225         _exit (1);
2226 }
2227
2228 static gboolean
2229 print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2230 {
2231         MonoMethod *method = NULL;
2232
2233         if (frame->ji)
2234                 method = jinfo_get_method (frame->ji);
2235
2236         if (method) {
2237                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2238                 mono_runtime_printf_err ("  %s", location);
2239                 g_free (location);
2240         } else
2241                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2242
2243         return FALSE;
2244 }
2245
2246 static G_GNUC_UNUSED gboolean
2247 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2248 {
2249         GString *p = (GString*)data;
2250         MonoMethod *method = NULL;
2251
2252         if (frame->ji)
2253                 method = jinfo_get_method (frame->ji);
2254
2255         if (method && frame->domain) {
2256                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
2257                 g_string_append_printf (p, "  %s\n", location);
2258                 g_free (location);
2259         } else
2260                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2261
2262         return FALSE;
2263 }
2264
2265 #ifndef MONO_CROSS_COMPILE
2266
2267 static gboolean handling_sigsegv = FALSE;
2268
2269 /*
2270  * mono_handle_native_sigsegv:
2271  *
2272  *   Handle a SIGSEGV received while in native code by printing diagnostic 
2273  * information and aborting.
2274  */
2275 void
2276 mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2277 {
2278 #ifdef MONO_ARCH_USE_SIGACTION
2279         struct sigaction sa;
2280 #endif
2281         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2282         const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
2283
2284         if (handling_sigsegv)
2285                 return;
2286
2287         if (mini_get_debug_options ()->suspend_on_sigsegv) {
2288                 mono_runtime_printf_err ("Received SIGSEGV, suspending...");
2289 #ifdef HOST_WIN32
2290                 while (1)
2291                         ;
2292 #else
2293                 while (1) {
2294                         sleep (1);
2295                 }
2296 #endif
2297         }
2298
2299         /* To prevent infinite loops when the stack walk causes a crash */
2300         handling_sigsegv = TRUE;
2301
2302         /* !jit_tls means the thread was not registered with the runtime */
2303         if (jit_tls && mono_thread_internal_current ()) {
2304                 mono_runtime_printf_err ("Stacktrace:\n");
2305
2306                 mono_walk_stack (print_stack_frame_to_stderr, TRUE, NULL);
2307         }
2308
2309 #ifdef HAVE_BACKTRACE_SYMBOLS
2310  {
2311         void *array [256];
2312         char **names;
2313         int i, size;
2314
2315         mono_runtime_printf_err ("\nNative stacktrace:\n");
2316
2317         size = backtrace (array, 256);
2318         names = backtrace_symbols (array, size);
2319         for (i =0; i < size; ++i) {
2320                 mono_runtime_printf_err ("\t%s", names [i]);
2321         }
2322         free (names);
2323
2324         /* Try to get more meaningful information using gdb */
2325
2326 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2327         if (!mini_get_debug_options ()->no_gdb_backtrace) {
2328                 /* From g_spawn_command_line_sync () in eglib */
2329                 pid_t pid;
2330                 int status;
2331                 pid_t crashed_pid = getpid ();
2332
2333                 //pid = fork ();
2334                 /*
2335                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2336                  * it will deadlock. Call the syscall directly instead.
2337                  */
2338                 pid = mono_runtime_syscall_fork ();
2339
2340                 if (pid == 0) {
2341                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2342
2343                         mono_gdb_render_native_backtraces (crashed_pid);
2344                         exit (1);
2345                 }
2346
2347                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2348                 waitpid (pid, &status, 0);
2349         }
2350 #endif
2351  }
2352 #elif defined (ENABLE_EXTENSION_MODULE)
2353         mono_extension_handle_native_sigsegv (ctx, info);
2354 #endif
2355
2356         /*
2357          * A SIGSEGV indicates something went very wrong so we can no longer depend
2358          * on anything working. So try to print out lots of diagnostics, starting 
2359          * with ones which have a greater chance of working.
2360          */
2361         mono_runtime_printf_err (
2362                          "\n"
2363                          "=================================================================\n"
2364                          "Got a %s while executing native code. This usually indicates\n"
2365                          "a fatal error in the mono runtime or one of the native libraries \n"
2366                          "used by your application.\n"
2367                          "=================================================================\n",
2368                         signal_str);
2369
2370
2371 #ifdef MONO_ARCH_USE_SIGACTION
2372
2373         /* Remove our SIGABRT handler */
2374         sa.sa_handler = SIG_DFL;
2375         sigemptyset (&sa.sa_mask);
2376         sa.sa_flags = 0;
2377
2378         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2379
2380 #endif
2381
2382         if (!mono_do_crash_chaining) {
2383                 /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2384 #if defined (PLATFORM_ANDROID)
2385                 exit (-1);
2386 #else
2387                 abort ();
2388 #endif
2389         }
2390 }
2391
2392 #else
2393
2394 void
2395 mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info)
2396 {
2397         g_assert_not_reached ();
2398 }
2399
2400 #endif /* !MONO_CROSS_COMPILE */
2401
2402 static void
2403 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2404 {
2405         MonoInternalThread *thread = mono_thread_internal_current ();
2406 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2407         MonoContext ctx;
2408 #endif
2409         GString* text;
2410         char *name;
2411 #ifndef HOST_WIN32
2412         char *wapi_desc;
2413 #endif
2414         GError *error = NULL;
2415
2416         if (!thread)
2417                 return;
2418
2419         text = g_string_new (0);
2420         if (thread->name) {
2421                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2422                 g_assert (!error);
2423                 g_string_append_printf (text, "\n\"%s\"", name);
2424                 g_free (name);
2425         }
2426         else if (thread->threadpool_thread)
2427                 g_string_append (text, "\n\"<threadpool thread>\"");
2428         else
2429                 g_string_append (text, "\n\"<unnamed thread>\"");
2430
2431 #ifndef HOST_WIN32
2432         wapi_desc = wapi_current_thread_desc ();
2433         g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
2434         free (wapi_desc);
2435 #endif
2436
2437 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2438         if (start_ctx) {
2439                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2440         } else if (!sigctx)
2441                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2442         else
2443                 mono_sigctx_to_monoctx (sigctx, &ctx);
2444
2445         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2446 #else
2447         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2448 #endif
2449
2450         mono_runtime_printf ("%s", text->str);
2451
2452 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2453         OutputDebugStringA(text->str);
2454 #endif
2455
2456         g_string_free (text, TRUE);
2457         mono_runtime_stdout_fflush ();
2458 }
2459
2460 /*
2461  * mono_print_thread_dump:
2462  *
2463  *   Print information about the current thread to stdout.
2464  * SIGCTX can be NULL, allowing this to be called from gdb.
2465  */
2466 void
2467 mono_print_thread_dump (void *sigctx)
2468 {
2469         mono_print_thread_dump_internal (sigctx, NULL);
2470 }
2471
2472 void
2473 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2474 {
2475         mono_print_thread_dump_internal (NULL, ctx);
2476 }
2477
2478 /*
2479  * mono_resume_unwind:
2480  *
2481  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2482  * unwinding.
2483  */
2484 void
2485 mono_resume_unwind (MonoContext *ctx)
2486 {
2487         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2488         MonoContext new_ctx;
2489
2490         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2491         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2492         new_ctx = *ctx;
2493
2494         mono_handle_exception_internal (&new_ctx, jit_tls->resume_state.ex_obj, TRUE, NULL);
2495
2496         mono_restore_context (&new_ctx);
2497 }
2498
2499 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2500
2501 typedef struct {
2502         MonoJitInfo *ji;
2503         MonoContext ctx;
2504         MonoJitExceptionInfo *ei;
2505 } FindHandlerBlockData;
2506
2507 static gboolean
2508 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2509 {
2510         int i;
2511         gpointer ip;
2512         FindHandlerBlockData *pdata = data;
2513         MonoJitInfo *ji = frame->ji;
2514
2515         if (!ji)
2516                 return FALSE;
2517
2518         ip = MONO_CONTEXT_GET_IP (ctx);
2519
2520         for (i = 0; i < ji->num_clauses; ++i) {
2521                 MonoJitExceptionInfo *ei = ji->clauses + i;
2522                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2523                         continue;
2524                 /*If ip points to the first instruction it means the handler block didn't start
2525                  so we can leave its execution to the EH machinery*/
2526                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2527                         pdata->ji = ji;
2528                         pdata->ei = ei;
2529                         pdata->ctx = *ctx;
2530                         break;
2531                 }
2532         }
2533         return FALSE;
2534 }
2535
2536
2537 static gpointer
2538 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2539 {
2540         int i;
2541         MonoJitExceptionInfo *clause = NULL;
2542         gpointer ip;
2543
2544         ip = MONO_CONTEXT_GET_IP (ctx);
2545
2546         for (i = 0; i < ji->num_clauses; ++i) {
2547                 clause = &ji->clauses [i];
2548                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2549                         continue;
2550                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2551                         break;
2552         }
2553
2554         /*no matching finally */
2555         if (i == ji->num_clauses)
2556                 return NULL;
2557
2558         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2559         if (ip == clause->handler_start)
2560                 return NULL;
2561
2562         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2563 }
2564
2565 /*
2566  * Finds the bottom handler block running and install a block guard if needed.
2567  * FIXME add full-aot support.
2568  */
2569 gboolean
2570 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2571 {
2572         FindHandlerBlockData data = { 0 };
2573         MonoJitTlsData *jit_tls = ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2574         gpointer resume_ip;
2575
2576         /* FIXME */
2577         if (mono_aot_only)
2578                 return FALSE;
2579
2580         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2581          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2582          */
2583         if (!jit_tls || jit_tls->handler_block_return_address)
2584                 return FALSE;
2585
2586         /* Do an async safe stack walk */
2587         mono_thread_info_set_is_async_context (TRUE);
2588         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data);
2589         mono_thread_info_set_is_async_context (FALSE);
2590
2591         if (!data.ji)
2592                 return FALSE;
2593
2594         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2595
2596         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2597         if (resume_ip == NULL)
2598                 return FALSE;
2599
2600         jit_tls->handler_block_return_address = resume_ip;
2601         jit_tls->handler_block = data.ei;
2602
2603         return TRUE;
2604 }
2605
2606 #else
2607 gboolean
2608 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2609 {
2610         return FALSE;
2611 }
2612
2613 #endif
2614
2615 void
2616 mono_set_cast_details (MonoClass *from, MonoClass *to)
2617 {
2618         MonoJitTlsData *jit_tls = NULL;
2619
2620         if (mini_get_debug_options ()->better_cast_details) {
2621                 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2622                 jit_tls->class_cast_from = from;
2623                 jit_tls->class_cast_to = to;
2624         }
2625 }
2626
2627
2628 /*returns false if the thread is not attached*/
2629 gboolean
2630 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
2631 {
2632 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2633         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2634         if (!thread) {
2635                 ctx->valid = FALSE;
2636                 G_BREAKPOINT ();
2637                 return FALSE;
2638         }
2639
2640         if (sigctx)
2641                 mono_sigctx_to_monoctx (sigctx, &ctx->ctx);
2642         else
2643 #if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE)
2644                 MONO_CONTEXT_GET_CURRENT (ctx->ctx);
2645 #else
2646                 g_error ("Use a null sigctx requires a working mono-context");
2647 #endif
2648
2649         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2650         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2651         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2652         ctx->valid = TRUE;
2653         return TRUE;
2654 #else
2655         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
2656         return FALSE;
2657 #endif
2658 }
2659
2660 gboolean
2661 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
2662 {
2663         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2664         if (!thread) {
2665                 ctx->valid = FALSE;
2666                 return FALSE;
2667         }
2668
2669         ctx->ctx = *mctx;
2670         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2671         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2672         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2673         ctx->valid = TRUE;
2674         return TRUE;
2675 }
2676
2677 /*returns false if the thread is not attached*/
2678 gboolean
2679 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
2680 {
2681         MonoThreadInfo *thread = mono_thread_info_current_unchecked ();
2682         MONO_ARCH_CONTEXT_DEF
2683
2684         mono_arch_flush_register_windows ();
2685
2686         if (!thread || !thread->jit_data) {
2687                 ctx->valid = FALSE;
2688                 return FALSE;
2689         }
2690 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
2691         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
2692 #else
2693         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
2694 #endif
2695                 
2696         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2697         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2698         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2699         ctx->valid = TRUE;
2700         return TRUE;
2701 }
2702
2703 static void
2704 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
2705 {
2706         mono_handle_exception (ctx, exc);
2707         mono_restore_context (ctx);
2708 }
2709
2710 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
2711 void
2712 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
2713 {
2714 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
2715         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2716         jit_tls->ex_ctx = *ctx;
2717
2718         mono_arch_setup_async_callback (ctx, async_cb, user_data);
2719 #else
2720         g_error ("This target doesn't support mono_arch_setup_async_callback");
2721 #endif
2722 }
2723
2724 void
2725 mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
2726 {
2727         unhandled_exception_hook = func;
2728         unhandled_exception_hook_data = user_data;
2729 }
2730
2731 void
2732 mono_invoke_unhandled_exception_hook (MonoObject *exc)
2733 {
2734         if (unhandled_exception_hook) {
2735                 unhandled_exception_hook (exc, unhandled_exception_hook_data);
2736         } else {
2737                 MonoObject *other = NULL;
2738                 MonoString *str = mono_object_to_string (exc, &other);
2739                 char *msg = NULL;
2740                 
2741                 if (str)
2742                         msg = mono_string_to_utf8 (str);
2743                 else if (other) {
2744                         char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
2745                         char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);
2746
2747                         msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
2748                                 original_backtrace, nested_backtrace);
2749
2750                         g_free (original_backtrace);
2751                         g_free (nested_backtrace);
2752                 } else {
2753                         msg = g_strdup ("Nested exception trying to figure out what went wrong");
2754                 }
2755                 mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
2756                 g_free (msg);
2757 #if defined(HOST_IOS)
2758                 g_assertion_message ("Terminating runtime due to unhandled exception");
2759 #else
2760                 exit (mono_environment_exitcode_get ());
2761 #endif
2762         }
2763
2764         g_assert_not_reached ();
2765 }
2766
2767 /*
2768  * mono_restore_context:
2769  *
2770  *   Call the architecture specific restore context function.
2771  */
2772 void
2773 mono_restore_context (MonoContext *ctx)
2774 {
2775         static void (*restore_context) (MonoContext *);
2776
2777         if (!restore_context)
2778                 restore_context = mono_get_restore_context ();
2779         restore_context (ctx);
2780         g_assert_not_reached ();
2781 }
2782
2783 /*
2784  * mono_jinfo_get_unwind_info:
2785  *
2786  *   Return the unwind info for JI.
2787  */
2788 guint8*
2789 mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
2790 {
2791         if (ji->from_aot)
2792                 return mono_aot_get_unwind_info (ji, unwind_info_len);
2793         else
2794                 return mono_get_cached_unwind_info (ji->unwind_info, unwind_info_len);
2795 }
2796
2797 int
2798 mono_jinfo_get_epilog_size (MonoJitInfo *ji)
2799 {
2800         MonoArchEHJitInfo *info;
2801
2802         info = mono_jit_info_get_arch_eh_info (ji);
2803         g_assert (info);
2804
2805         return info->epilog_size;
2806 }