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