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