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