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