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