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