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