Merge pull request #1084 from tritao/msvc-warnings
[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 = 0;
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 (mini_get_debug_options ()->suspend_on_exception) {
1546                 mono_runtime_printf_err ("Exception thrown, suspending...");
1547                 while (1)
1548                         ;
1549         }
1550
1551         if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1552                 mono_ex = (MonoException*)obj;
1553         } else {
1554                 mono_ex = NULL;
1555         }
1556
1557         if (mono_ex && jit_tls->class_cast_from) {
1558                 if (!strcmp (mono_ex->object.vtable->klass->name, "InvalidCastException")) {
1559                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1560                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1561                         char *msg = g_strdup_printf ("Unable to cast object of type '%s' to type '%s'.", from_name, to_name);
1562                         mono_ex->message = mono_string_new (domain, msg);
1563                         g_free (from_name);
1564                         g_free (to_name);
1565                         g_free (msg);
1566                 }
1567                 if (!strcmp (mono_ex->object.vtable->klass->name, "ArrayTypeMismatchException")) {
1568                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1569                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1570                         char *msg = g_strdup_printf ("Source array of type '%s' cannot be cast to destination array type '%s'.", from_name, to_name);
1571                         mono_ex->message = mono_string_new (domain, msg);
1572                         g_free (from_name);
1573                         g_free (to_name);
1574                         g_free (msg);
1575                 }
1576         }
1577
1578         if (!call_filter)
1579                 call_filter = mono_get_call_filter ();
1580
1581         g_assert (jit_tls->end_of_stack);
1582         g_assert (jit_tls->abort_func);
1583
1584         /*
1585          * We set orig_ex_ctx_set to TRUE/FALSE around profiler calls to make sure it doesn't
1586          * end up being TRUE on any code path.
1587          */
1588         memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
1589
1590         if (!resume) {
1591                 gboolean res;
1592
1593                 MonoContext ctx_cp = *ctx;
1594                 if (mono_trace_is_enabled ()) {
1595                         MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
1596                         MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
1597                         MonoObject *message;
1598                         const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
1599                         char *msg = NULL;
1600                         MonoObject *exc = NULL;
1601                         if (get_message == NULL) {
1602                                 message = NULL;
1603                         } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
1604                                 message = NULL;
1605                                 msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
1606                         } else {
1607                                 message = mono_runtime_invoke (get_message, obj, NULL, &exc);
1608                                 
1609                         }
1610                         if (msg == NULL) {
1611                                 msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
1612                         }
1613                         g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)GetCurrentThreadId (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg);
1614                         g_free (msg);
1615                         if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
1616                                 mono_print_thread_dump_from_ctx (ctx);
1617                 }
1618                 jit_tls->orig_ex_ctx_set = TRUE;
1619                 mono_profiler_exception_thrown (obj);
1620                 jit_tls->orig_ex_ctx_set = FALSE;
1621
1622                 res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception);
1623
1624                 if (!res) {
1625                         if (mini_get_debug_options ()->break_on_exc)
1626                                 G_BREAKPOINT ();
1627                         mono_debugger_agent_handle_exception (obj, ctx, NULL);
1628
1629                         if (mini_get_debug_options ()->suspend_on_unhandled) {
1630                                 mono_runtime_printf_err ("Unhandled exception, suspending...");
1631                                 while (1)
1632                                         ;
1633                         }
1634
1635                         // FIXME: This runs managed code so it might cause another stack overflow when
1636                         // we are handling a stack overflow
1637                         mono_unhandled_exception (obj);
1638                 } else {
1639                         gboolean unhandled = FALSE;
1640
1641                         /*
1642                          * The exceptions caught by the mono_runtime_invoke () calls in mono_async_invoke () needs to be treated as
1643                          * unhandled (#669836).
1644                          * FIXME: The check below is hackish, but its hard to distinguish these runtime invoke calls from others
1645                          * in the runtime.
1646                          */
1647                         if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
1648                                 if (prev_ji) {
1649                                         MonoInternalThread *thread = mono_thread_internal_current ();
1650                                         if (jinfo_get_method (prev_ji) == thread->async_invoke_method)
1651                                                 unhandled = TRUE;
1652                                 }
1653                         }
1654                         if (unhandled)
1655                                 mono_debugger_agent_handle_exception (obj, ctx, NULL);
1656                         else
1657                                 mono_debugger_agent_handle_exception (obj, ctx, &ctx_cp);
1658                 }
1659         }
1660
1661         if (out_ji)
1662                 *out_ji = NULL;
1663         filter_idx = 0;
1664         initial_ctx = *ctx;
1665
1666         while (1) {
1667                 MonoContext new_ctx;
1668                 guint32 free_stack;
1669                 int clause_index_start = 0;
1670                 gboolean unwind_res = TRUE;
1671                 
1672                 if (resume) {
1673                         resume = FALSE;
1674                         ji = jit_tls->resume_state.ji;
1675                         new_ctx = jit_tls->resume_state.new_ctx;
1676                         clause_index_start = jit_tls->resume_state.clause_index;
1677                         lmf = jit_tls->resume_state.lmf;
1678                         first_filter_idx = jit_tls->resume_state.first_filter_idx;
1679                         filter_idx = jit_tls->resume_state.filter_idx;
1680                 } else {
1681                         StackFrameInfo frame;
1682
1683                         unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1684                         if (unwind_res) {
1685                                 if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
1686                                         *ctx = new_ctx;
1687                                         continue;
1688                                 }
1689                                 g_assert (frame.type == FRAME_TYPE_MANAGED);
1690                                 ji = frame.ji;
1691                         }
1692                 }
1693
1694                 if (!unwind_res) {
1695                         *(mono_get_lmf_addr ()) = lmf;
1696
1697                         jit_tls->abort_func (obj);
1698                         g_assert_not_reached ();
1699                 }
1700
1701                 method = jinfo_get_method (ji);
1702                 frame_count ++;
1703                 //printf ("M: %s %d.\n", mono_method_full_name (method, TRUE), frame_count);
1704
1705                 if (stack_overflow) {
1706                         if (DOES_STACK_GROWS_UP)
1707                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1708                         else
1709                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1710                 } else {
1711                         free_stack = 0xffffff;
1712                 }
1713                                 
1714                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1715                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1716                         gboolean filtered = FALSE;
1717
1718                         /* 
1719                          * During stack overflow, wait till the unwinding frees some stack
1720                          * space before running handlers/finalizers.
1721                          */
1722                         if (free_stack <= (64 * 1024))
1723                                 continue;
1724
1725                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1726                                 /* catch block */
1727                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1728
1729                                 /*
1730                                  * Have to unwrap RuntimeWrappedExceptions if the
1731                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1732                                  */
1733                                 if (non_exception && !wrap_non_exception_throws (method))
1734                                         ex_obj = non_exception;
1735                                 else
1736                                         ex_obj = obj;
1737
1738                                 if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
1739                                         if (ji->from_llvm) {
1740 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1741                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1742 #else
1743                                                 g_assert_not_reached ();
1744 #endif
1745                                         } else {
1746                                                 /* store the exception object in bp + ei->exvar_offset */
1747                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1748                                         }
1749                                 }
1750
1751                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1752                                         /* 
1753                                          * Filter clauses should only be run in the 
1754                                          * first pass of exception handling.
1755                                          */
1756                                         filtered = (filter_idx == first_filter_idx);
1757                                         filter_idx ++;
1758                                 }
1759
1760                                 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
1761                                          mono_object_isinst (ex_obj, catch_class)) || filtered) {
1762                                         /*
1763                                          * This guards against the situation that we abort a thread that is executing a finally clause
1764                                          * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
1765                                          * check for this situation here and resume interruption if we are below the guarded block.
1766                                          */
1767                                         if (G_UNLIKELY (jit_tls->handler_block_return_address)) {
1768                                                 gboolean is_outside = FALSE;
1769                                                 gpointer prot_bp = MONO_CONTEXT_GET_BP (&jit_tls->handler_block_context);
1770                                                 gpointer catch_bp = MONO_CONTEXT_GET_BP (ctx);
1771                                                 //FIXME make this stack direction aware
1772                                                 if (catch_bp > prot_bp) {
1773                                                         is_outside = TRUE;
1774                                                 } else if (catch_bp == prot_bp) {
1775                                                         /* Can be either try { try { } catch {} } finally {} or try { try { } finally {} } catch {}
1776                                                          * So we check if the catch handler_start is protected by the guarded handler protected region
1777                                                          *
1778                                                          * Assumptions:
1779                                                          *      If there is an outstanding guarded_block return address, it means the current thread must be aborted.
1780                                                          *      This is the only way to reach out the guarded block as other cases are handled by the trampoline.
1781                                                          *      There aren't any further finally/fault handler blocks down the stack over this exception.
1782                                                          *   This must be ensured by the code that installs the guard trampoline.
1783                                                          */
1784                                                         g_assert (ji == mini_jit_info_table_find (domain, MONO_CONTEXT_GET_IP (&jit_tls->handler_block_context), NULL));
1785
1786                                                         if (!is_address_protected (ji, jit_tls->handler_block, ei->handler_start)) {
1787                                                                 is_outside = TRUE;
1788                                                         }
1789                                                 }
1790                                                 if (is_outside) {
1791                                                         jit_tls->handler_block_return_address = NULL;
1792                                                         jit_tls->handler_block = NULL;
1793                                                         mono_thread_resume_interruption (); /*We ignore the exception here, it will be raised later*/
1794                                                 }
1795                                         }
1796
1797                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1798                                                 g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1799                                         jit_tls->orig_ex_ctx_set = TRUE;
1800                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1801                                         jit_tls->orig_ex_ctx_set = FALSE;
1802                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1803                                         *(mono_get_lmf_addr ()) = lmf;
1804 #ifndef DISABLE_PERFCOUNTERS
1805                                         mono_perfcounters->exceptions_depth += frame_count;
1806 #endif
1807                                         if (obj == domain->stack_overflow_ex)
1808                                                 jit_tls->handling_stack_ovf = FALSE;
1809
1810                                         return 0;
1811                                 }
1812                                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
1813                                         (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT)) {
1814                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1815                                                 g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1816                                         jit_tls->orig_ex_ctx_set = TRUE;
1817                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1818                                         jit_tls->orig_ex_ctx_set = FALSE;
1819                                         call_filter (ctx, ei->handler_start);
1820                                 }
1821                                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
1822                                         (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
1823                                         if (mono_trace_is_enabled () && mono_trace_eval (method))
1824                                                 g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (method, TRUE));
1825                                         jit_tls->orig_ex_ctx_set = TRUE;
1826                                         mono_profiler_exception_clause_handler (method, ei->flags, i);
1827                                         jit_tls->orig_ex_ctx_set = FALSE;
1828 #ifndef DISABLE_PERFCOUNTERS
1829                                         mono_perfcounters->exceptions_finallys++;
1830 #endif
1831                                         *(mono_get_lmf_addr ()) = lmf;
1832                                         if (ji->from_llvm) {
1833                                                 /* 
1834                                                  * LLVM compiled finally handlers follow the design
1835                                                  * of the c++ ehabi, i.e. they call a resume function
1836                                                  * at the end instead of returning to the caller.
1837                                                  * So save the exception handling state,
1838                                                  * mono_resume_unwind () will call us again to continue
1839                                                  * the unwinding.
1840                                                  */
1841                                                 jit_tls->resume_state.ex_obj = obj;
1842                                                 jit_tls->resume_state.ji = ji;
1843                                                 jit_tls->resume_state.clause_index = i + 1;
1844                                                 jit_tls->resume_state.ctx = *ctx;
1845                                                 jit_tls->resume_state.new_ctx = new_ctx;
1846                                                 jit_tls->resume_state.lmf = lmf;
1847                                                 jit_tls->resume_state.first_filter_idx = first_filter_idx;
1848                                                 jit_tls->resume_state.filter_idx = filter_idx;
1849                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1850                                                 return 0;
1851                                         } else {
1852                                                 call_filter (ctx, ei->handler_start);
1853                                         }
1854                                 }
1855                         }
1856                 }
1857
1858                 jit_tls->orig_ex_ctx_set = TRUE;
1859                 mono_profiler_exception_method_leave (method);
1860                 jit_tls->orig_ex_ctx_set = FALSE;
1861
1862                 *ctx = new_ctx;
1863         }
1864
1865         g_assert_not_reached ();
1866 }
1867
1868 /**
1869  * mono_debugger_run_finally:
1870  * @start_ctx: saved processor state
1871  *
1872  * This method is called by the Mono Debugger to call all `finally' clauses of the
1873  * current stack frame.  It's used when the user issues a `return' command to make
1874  * the current stack frame return.  After returning from this method, the debugger
1875  * unwinds the stack one frame and gives control back to the user.
1876  *
1877  * NOTE: This method is only used when running inside the Mono Debugger.
1878  */
1879 void
1880 mono_debugger_run_finally (MonoContext *start_ctx)
1881 {
1882         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1883         MonoDomain *domain = mono_domain_get ();
1884         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1885         MonoLMF *lmf = mono_get_lmf ();
1886         MonoContext ctx, new_ctx;
1887         MonoJitInfo *ji, rji;
1888         int i;
1889
1890         ctx = *start_ctx;
1891
1892         ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
1893         if (!ji || ji == (gpointer)-1)
1894                 return;
1895
1896         if (!call_filter)
1897                 call_filter = mono_get_call_filter ();
1898
1899         for (i = 0; i < ji->num_clauses; i++) {
1900                 MonoJitExceptionInfo *ei = &ji->clauses [i];
1901
1902                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
1903                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
1904                         call_filter (&ctx, ei->handler_start);
1905                 }
1906         }
1907 }
1908
1909 /**
1910  * mono_handle_exception:
1911  * @ctx: saved processor state
1912  * @obj: the exception object
1913  */
1914 gboolean
1915 mono_handle_exception (MonoContext *ctx, gpointer obj)
1916 {
1917 #ifndef DISABLE_PERFCOUNTERS
1918         mono_perfcounters->exceptions_thrown++;
1919 #endif
1920
1921         return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
1922 }
1923
1924 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
1925
1926 #ifndef MONO_ARCH_USE_SIGACTION
1927 #error "Can't use sigaltstack without sigaction"
1928 #endif
1929
1930 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
1931
1932 void
1933 mono_setup_altstack (MonoJitTlsData *tls)
1934 {
1935         size_t stsize = 0;
1936         stack_t sa;
1937         guint8 *staddr = NULL;
1938
1939         if (mono_running_on_valgrind ())
1940                 return;
1941
1942         mono_thread_info_get_stack_bounds (&staddr, &stsize);
1943
1944         g_assert (staddr);
1945
1946         tls->end_of_stack = staddr + stsize;
1947         tls->stack_size = stsize;
1948
1949         /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
1950
1951         tls->stack_ovf_guard_base = staddr + mono_pagesize ();
1952         tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
1953
1954         g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
1955
1956         if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
1957                 /* mprotect can fail for the main thread stack */
1958                 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);
1959                 g_assert (gaddr == tls->stack_ovf_guard_base);
1960                 tls->stack_ovf_valloced = TRUE;
1961         }
1962
1963         /* Setup an alternate signal stack */
1964         tls->signal_stack = mono_valloc (0, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON);
1965         tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1966
1967         g_assert (tls->signal_stack);
1968
1969         sa.ss_sp = tls->signal_stack;
1970         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1971         sa.ss_flags = 0;
1972         g_assert (sigaltstack (&sa, NULL) == 0);
1973
1974         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);
1975 }
1976
1977 void
1978 mono_free_altstack (MonoJitTlsData *tls)
1979 {
1980         stack_t sa;
1981         int err;
1982
1983         sa.ss_sp = tls->signal_stack;
1984         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1985         sa.ss_flags = SS_DISABLE;
1986         err = sigaltstack  (&sa, NULL);
1987         g_assert (err == 0);
1988
1989         if (tls->signal_stack)
1990                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE);
1991         if (tls->stack_ovf_valloced)
1992                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size);
1993         else
1994                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
1995 }
1996
1997 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
1998
1999 void
2000 mono_setup_altstack (MonoJitTlsData *tls)
2001 {
2002 }
2003
2004 void
2005 mono_free_altstack (MonoJitTlsData *tls)
2006 {
2007 }
2008
2009 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2010
2011 static gboolean
2012 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
2013 {
2014         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
2015         /* we need to leave some room for throwing the exception */
2016         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
2017                 unprotect_size -= mono_pagesize ();
2018         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
2019          * is sufficient stack
2020          */
2021         //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);
2022         if (unprotect_size)
2023                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
2024         return unprotect_size == jit_tls->stack_ovf_guard_size;
2025 }
2026
2027 static G_GNUC_UNUSED void
2028 try_more_restore (void)
2029 {
2030         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2031         if (try_restore_stack_protection (jit_tls, 500))
2032                 jit_tls->restore_stack_prot = NULL;
2033 }
2034
2035 static G_GNUC_UNUSED void
2036 restore_stack_protection (void)
2037 {
2038         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2039         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
2040         /* if we can't restore the stack protection, keep a callback installed so
2041          * we'll try to restore as much stack as we can at each return from unmanaged
2042          * code.
2043          */
2044         if (try_restore_stack_protection (jit_tls, 4096))
2045                 jit_tls->restore_stack_prot = NULL;
2046         else
2047                 jit_tls->restore_stack_prot = try_more_restore_tramp;
2048         /* here we also throw a stack overflow exception */
2049         ex->trace_ips = NULL;
2050         ex->stack_trace = NULL;
2051         mono_raise_exception (ex);
2052 }
2053
2054 gpointer
2055 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
2056 {
2057         void (*func)(void) = (gpointer)tramp_data;
2058         func ();
2059         return NULL;
2060 }
2061
2062 gboolean
2063 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2064 {
2065         /* we got a stack overflow in the soft-guard pages
2066          * There are two cases:
2067          * 1) managed code caused the overflow: we unprotect the soft-guard page
2068          * and let the arch-specific code trigger the exception handling mechanism
2069          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
2070          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
2071          * and hope we can continue with those enabled, at least until the hard-guard page
2072          * is hit. The alternative to continuing here is to just print a message and abort.
2073          * We may add in the future the code to protect the pages again in the codepath
2074          * when we return from unmanaged to managed code.
2075          */
2076         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2077                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2078                 /* we unprotect the minimum amount we can */
2079                 guint32 guard_size;
2080                 gboolean handled = FALSE;
2081
2082                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2083                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2084                         guard_size -= mono_pagesize ();
2085                 }
2086                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2087                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2088                 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);
2089 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2090                 if (ji) {
2091                         mono_arch_handle_altstack_exception (ctx, fault_addr, TRUE);
2092                         handled = TRUE;
2093                 }
2094 #endif
2095                 if (!handled) {
2096                         /* We print a message: after this even managed stack overflows
2097                          * may crash the runtime
2098                          */
2099                         mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2100                         if (!jit_tls->handling_stack_ovf) {
2101                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2102                                 jit_tls->handling_stack_ovf = 1;
2103                         } else {
2104                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2105                         }
2106                 }
2107                 return TRUE;
2108         }
2109         return FALSE;
2110 }
2111
2112 typedef struct {
2113         MonoMethod *omethod;
2114         int count;
2115 } PrintOverflowUserData;
2116
2117 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2118 static gboolean
2119 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2120 {
2121         MonoMethod *method = NULL;
2122         PrintOverflowUserData *user_data = data;
2123         gchar *location;
2124
2125         if (frame->ji)
2126                 method = jinfo_get_method (frame->ji);
2127
2128         if (method) {
2129                 if (user_data->count == 0) {
2130                         /* The first frame is in its prolog, so a line number cannot be computed */
2131                         user_data->count ++;
2132                         return FALSE;
2133                 }
2134
2135                 /* If this is a one method overflow, skip the other instances */
2136                 if (method == user_data->omethod)
2137                         return FALSE;
2138
2139                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2140                 mono_runtime_printf_err ("  %s", location);
2141                 g_free (location);
2142
2143                 if (user_data->count == 1) {
2144                         mono_runtime_printf_err ("  <...>");
2145                         user_data->omethod = method;
2146                 } else {
2147                         user_data->omethod = NULL;
2148                 }
2149
2150                 user_data->count ++;
2151         } else
2152                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2153
2154         return FALSE;
2155 }
2156 #endif
2157
2158 void
2159 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2160 {
2161 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2162         PrintOverflowUserData ud;
2163         MonoContext mctx;
2164 #endif
2165
2166         /* we don't do much now, but we can warn the user with a useful message */
2167         mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2168
2169 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2170         mono_arch_sigctx_to_monoctx (ctx, &mctx);
2171                         
2172         mono_runtime_printf_err ("Stacktrace:");
2173
2174         memset (&ud, 0, sizeof (ud));
2175
2176         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2177 #else
2178         if (ji && jinfo_get_method (ji))
2179                 mono_runtime_printf_err ("At %s", mono_method_full_name (jinfo_get_method (ji), TRUE));
2180         else
2181                 mono_runtime_printf_err ("At <unmanaged>.");
2182 #endif
2183
2184         _exit (1);
2185 }
2186
2187 static gboolean
2188 print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2189 {
2190         MonoMethod *method = NULL;
2191
2192         if (frame->ji)
2193                 method = jinfo_get_method (frame->ji);
2194
2195         if (method) {
2196                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2197                 mono_runtime_printf_err ("  %s", location);
2198                 g_free (location);
2199         } else
2200                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2201
2202         return FALSE;
2203 }
2204
2205 static G_GNUC_UNUSED gboolean
2206 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2207 {
2208         GString *p = (GString*)data;
2209         MonoMethod *method = NULL;
2210
2211         if (frame->ji)
2212                 method = jinfo_get_method (frame->ji);
2213
2214         if (method) {
2215                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2216                 g_string_append_printf (p, "  %s\n", location);
2217                 g_free (location);
2218         } else
2219                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2220
2221         return FALSE;
2222 }
2223
2224 static gboolean handling_sigsegv = FALSE;
2225
2226 /*
2227  * mono_handle_native_sigsegv:
2228  *
2229  *   Handle a SIGSEGV received while in native code by printing diagnostic 
2230  * information and aborting.
2231  */
2232 void
2233 mono_handle_native_sigsegv (int signal, void *ctx)
2234 {
2235 #ifdef MONO_ARCH_USE_SIGACTION
2236         struct sigaction sa;
2237 #endif
2238         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2239         const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
2240
2241         if (handling_sigsegv)
2242                 return;
2243
2244         if (mini_get_debug_options ()->suspend_on_sigsegv) {
2245                 mono_runtime_printf_err ("Received SIGSEGV, suspending...");
2246 #ifdef HOST_WIN32
2247                 while (1)
2248                         ;
2249 #else
2250                 while (1) {
2251                         sleep (0);
2252                 }
2253 #endif
2254         }
2255
2256         /* To prevent infinite loops when the stack walk causes a crash */
2257         handling_sigsegv = TRUE;
2258
2259         /* !jit_tls means the thread was not registered with the runtime */
2260         if (jit_tls && mono_thread_internal_current ()) {
2261                 mono_runtime_printf_err ("Stacktrace:\n");
2262
2263                 mono_walk_stack (print_stack_frame_to_stderr, TRUE, NULL);
2264         }
2265
2266 #ifdef HAVE_BACKTRACE_SYMBOLS
2267  {
2268         void *array [256];
2269         char **names;
2270         int i, size;
2271
2272         mono_runtime_printf_err ("\nNative stacktrace:\n");
2273
2274         size = backtrace (array, 256);
2275         names = backtrace_symbols (array, size);
2276         for (i =0; i < size; ++i) {
2277                 mono_runtime_printf_err ("\t%s", names [i]);
2278         }
2279         free (names);
2280
2281         /* Try to get more meaningful information using gdb */
2282
2283 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2284         if (!mini_get_debug_options ()->no_gdb_backtrace) {
2285                 /* From g_spawn_command_line_sync () in eglib */
2286                 pid_t pid;
2287                 int status;
2288                 pid_t crashed_pid = getpid ();
2289
2290                 //pid = fork ();
2291                 /*
2292                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2293                  * it will deadlock. Call the syscall directly instead.
2294                  */
2295                 pid = mono_runtime_syscall_fork ();
2296
2297                 if (pid == 0) {
2298                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2299
2300                         mono_gdb_render_native_backtraces (crashed_pid);
2301                         exit (1);
2302                 }
2303
2304                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2305                 waitpid (pid, &status, 0);
2306         }
2307 #endif
2308  }
2309 #endif
2310
2311         /*
2312          * A SIGSEGV indicates something went very wrong so we can no longer depend
2313          * on anything working. So try to print out lots of diagnostics, starting 
2314          * with ones which have a greater chance of working.
2315          */
2316         mono_runtime_printf_err (
2317                          "\n"
2318                          "=================================================================\n"
2319                          "Got a %s while executing native code. This usually indicates\n"
2320                          "a fatal error in the mono runtime or one of the native libraries \n"
2321                          "used by your application.\n"
2322                          "=================================================================\n",
2323                         signal_str);
2324
2325
2326 #ifdef MONO_ARCH_USE_SIGACTION
2327
2328         /* Remove our SIGABRT handler */
2329         sa.sa_handler = SIG_DFL;
2330         sigemptyset (&sa.sa_mask);
2331         sa.sa_flags = 0;
2332
2333         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2334
2335 #endif
2336
2337         if (!mono_do_crash_chaining) {
2338                 /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2339 #if defined (PLATFORM_ANDROID)
2340                 exit (-1);
2341 #else
2342                 abort ();
2343 #endif
2344         }
2345 }
2346
2347 static void
2348 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2349 {
2350         MonoInternalThread *thread = mono_thread_internal_current ();
2351 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2352         MonoContext ctx;
2353 #endif
2354         GString* text = g_string_new (0);
2355         char *name;
2356 #ifndef HOST_WIN32
2357         char *wapi_desc;
2358 #endif
2359         GError *error = NULL;
2360
2361         if (thread->name) {
2362                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2363                 g_assert (!error);
2364                 g_string_append_printf (text, "\n\"%s\"", name);
2365                 g_free (name);
2366         }
2367         else if (thread->threadpool_thread)
2368                 g_string_append (text, "\n\"<threadpool thread>\"");
2369         else
2370                 g_string_append (text, "\n\"<unnamed thread>\"");
2371
2372 #ifndef HOST_WIN32
2373         wapi_desc = wapi_current_thread_desc ();
2374         g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
2375         free (wapi_desc);
2376 #endif
2377
2378 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2379         if (start_ctx) {
2380                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2381         } else if (!sigctx)
2382                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2383         else
2384                 mono_arch_sigctx_to_monoctx (sigctx, &ctx);
2385
2386         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2387 #else
2388         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2389 #endif
2390
2391         mono_runtime_printf ("%s", text->str);
2392
2393 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2394         OutputDebugStringA(text->str);
2395 #endif
2396
2397         g_string_free (text, TRUE);
2398         mono_runtime_stdout_fflush ();
2399 }
2400
2401 /*
2402  * mono_print_thread_dump:
2403  *
2404  *   Print information about the current thread to stdout.
2405  * SIGCTX can be NULL, allowing this to be called from gdb.
2406  */
2407 void
2408 mono_print_thread_dump (void *sigctx)
2409 {
2410         mono_print_thread_dump_internal (sigctx, NULL);
2411 }
2412
2413 void
2414 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2415 {
2416         mono_print_thread_dump_internal (NULL, ctx);
2417 }
2418
2419 /*
2420  * mono_resume_unwind:
2421  *
2422  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2423  * unwinding.
2424  */
2425 void
2426 mono_resume_unwind (MonoContext *ctx)
2427 {
2428         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2429         MonoContext new_ctx;
2430
2431         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2432         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2433         new_ctx = *ctx;
2434
2435         mono_handle_exception_internal (&new_ctx, jit_tls->resume_state.ex_obj, TRUE, NULL);
2436
2437         mono_restore_context (&new_ctx);
2438 }
2439
2440 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2441
2442 typedef struct {
2443         MonoJitInfo *ji;
2444         MonoContext ctx;
2445         MonoJitExceptionInfo *ei;
2446 } FindHandlerBlockData;
2447
2448 static gboolean
2449 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2450 {
2451         int i;
2452         gpointer ip;
2453         FindHandlerBlockData *pdata = data;
2454         MonoJitInfo *ji = frame->ji;
2455
2456         if (!ji)
2457                 return FALSE;
2458
2459         ip = MONO_CONTEXT_GET_IP (ctx);
2460
2461         for (i = 0; i < ji->num_clauses; ++i) {
2462                 MonoJitExceptionInfo *ei = ji->clauses + i;
2463                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2464                         continue;
2465                 /*If ip points to the first instruction it means the handler block didn't start
2466                  so we can leave its execution to the EH machinery*/
2467                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2468                         pdata->ji = ji;
2469                         pdata->ei = ei;
2470                         pdata->ctx = *ctx;
2471                         break;
2472                 }
2473         }
2474         return FALSE;
2475 }
2476
2477
2478 static gpointer
2479 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2480 {
2481         int i;
2482         MonoJitExceptionInfo *clause = NULL;
2483         gpointer ip;
2484
2485         ip = MONO_CONTEXT_GET_IP (ctx);
2486
2487         for (i = 0; i < ji->num_clauses; ++i) {
2488                 clause = &ji->clauses [i];
2489                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2490                         continue;
2491                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2492                         break;
2493         }
2494
2495         /*no matching finally */
2496         if (i == ji->num_clauses)
2497                 return NULL;
2498
2499         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2500         if (ip == clause->handler_start)
2501                 return NULL;
2502
2503         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2504 }
2505
2506 /*
2507  * Finds the bottom handler block running and install a block guard if needed.
2508  * FIXME add full-aot support.
2509  */
2510 gboolean
2511 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2512 {
2513         FindHandlerBlockData data = { 0 };
2514         MonoJitTlsData *jit_tls = ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2515         gpointer resume_ip;
2516
2517         /* FIXME */
2518         if (mono_aot_only)
2519                 return FALSE;
2520
2521         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2522          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2523          */
2524         if (!jit_tls || jit_tls->handler_block_return_address)
2525                 return FALSE;
2526
2527         /* Do an async safe stack walk */
2528         mono_thread_info_set_is_async_context (TRUE);
2529         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_NONE, &data);
2530         mono_thread_info_set_is_async_context (FALSE);
2531
2532         if (!data.ji)
2533                 return FALSE;
2534
2535         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2536
2537         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2538         if (resume_ip == NULL)
2539                 return FALSE;
2540
2541         jit_tls->handler_block_return_address = resume_ip;
2542         jit_tls->handler_block = data.ei;
2543
2544         return TRUE;
2545 }
2546
2547 #else
2548 gboolean
2549 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2550 {
2551         return FALSE;
2552 }
2553
2554 #endif
2555
2556 void
2557 mono_set_cast_details (MonoClass *from, MonoClass *to)
2558 {
2559         MonoJitTlsData *jit_tls = NULL;
2560
2561         if (mini_get_debug_options ()->better_cast_details) {
2562                 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2563                 jit_tls->class_cast_from = from;
2564                 jit_tls->class_cast_to = to;
2565         }
2566 }
2567
2568
2569 /*returns false if the thread is not attached*/
2570 gboolean
2571 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
2572 {
2573 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2574         MonoInternalThread *thread = mono_thread_internal_current ();
2575         if (!thread || !thread->jit_data) {
2576                 ctx->valid = FALSE;
2577                 return FALSE;
2578         }
2579
2580         if (sigctx)
2581                 mono_arch_sigctx_to_monoctx (sigctx, &ctx->ctx);
2582         else
2583 #if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE)
2584                 MONO_CONTEXT_GET_CURRENT (ctx->ctx);
2585 #else
2586                 g_error ("Use a null sigctx requires a working mono-context");
2587 #endif
2588
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 #else
2595         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
2596         return FALSE;
2597 #endif
2598 }
2599
2600 gboolean
2601 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
2602 {
2603         MonoInternalThread *thread = mono_thread_internal_current ();
2604         if (!thread || !thread->jit_data) {
2605                 ctx->valid = FALSE;
2606                 return FALSE;
2607         }
2608
2609         ctx->ctx = *mctx;
2610         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2611         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2612         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2613         ctx->valid = TRUE;
2614         return TRUE;
2615 }
2616
2617 /*returns false if the thread is not attached*/
2618 gboolean
2619 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
2620 {
2621         MonoInternalThread *thread = mono_thread_internal_current ();
2622         MONO_ARCH_CONTEXT_DEF
2623
2624         mono_arch_flush_register_windows ();
2625
2626         if (!thread || !thread->jit_data) {
2627                 ctx->valid = FALSE;
2628                 return FALSE;
2629         }
2630 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
2631         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
2632 #else
2633         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
2634 #endif
2635                 
2636         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2637         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2638         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2639         ctx->valid = TRUE;
2640         return TRUE;
2641 }
2642
2643 static void
2644 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
2645 {
2646         mono_handle_exception (ctx, exc);
2647         mono_restore_context (ctx);
2648 }
2649
2650 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
2651 void
2652 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
2653 {
2654 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
2655         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2656         jit_tls->ex_ctx = *ctx;
2657
2658         mono_arch_setup_async_callback (ctx, async_cb, user_data);
2659 #else
2660         g_error ("This target doesn't support mono_arch_setup_async_callback");
2661 #endif
2662 }
2663
2664 void
2665 mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
2666 {
2667         unhandled_exception_hook = func;
2668         unhandled_exception_hook_data = user_data;
2669 }
2670
2671 void
2672 mono_invoke_unhandled_exception_hook (MonoObject *exc)
2673 {
2674         if (unhandled_exception_hook) {
2675                 unhandled_exception_hook (exc, unhandled_exception_hook_data);
2676         } else {
2677                 MonoObject *other = NULL;
2678                 MonoString *str = mono_object_to_string (exc, &other);
2679                 char *msg = NULL;
2680                 
2681                 if (str)
2682                         msg = mono_string_to_utf8 (str);
2683                 else if (other) {
2684                         char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
2685                         char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);
2686
2687                         msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
2688                                 original_backtrace, nested_backtrace);
2689
2690                         g_free (original_backtrace);
2691                         g_free (nested_backtrace);
2692                 } else {
2693                         msg = g_strdup ("Nested exception trying to figure out what went wrong");
2694                 }
2695                 mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
2696                 g_free (msg);
2697 #if defined(__APPLE__) && defined(__arm__)
2698                 g_assertion_message ("Terminating runtime due to unhandled exception");
2699 #else
2700                 exit (mono_environment_exitcode_get ());
2701 #endif
2702         }
2703
2704         g_assert_not_reached ();
2705 }
2706
2707 /*
2708  * mono_restore_context:
2709  *
2710  *   Call the architecture specific restore context function.
2711  */
2712 void
2713 mono_restore_context (MonoContext *ctx)
2714 {
2715         static void (*restore_context) (MonoContext *);
2716
2717         if (!restore_context)
2718                 restore_context = mono_get_restore_context ();
2719         restore_context (ctx);
2720         g_assert_not_reached ();
2721 }
2722
2723 /*
2724  * mono_jinfo_get_unwind_info:
2725  *
2726  *   Return the unwind info for JI.
2727  */
2728 guint8*
2729 mono_jinfo_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
2730 {
2731         if (ji->from_aot)
2732                 return mono_aot_get_unwind_info (ji, unwind_info_len);
2733         else
2734                 return mono_get_cached_unwind_info (ji->used_regs, unwind_info_len);
2735 }