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