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