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