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