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