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