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