Merge pull request #303 from ermshiperete/5278
[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 #define MAX_UNMANAGED_BACKTRACE 128
1200 static MonoArray*
1201 build_native_trace (void)
1202 {
1203 #ifdef HAVE_BACKTRACE_SYMBOLS
1204         MonoArray *res;
1205         void *native_trace [MAX_UNMANAGED_BACKTRACE];
1206         int size = backtrace (native_trace, MAX_UNMANAGED_BACKTRACE);
1207         int i;
1208
1209         if (!size)
1210                 return NULL;
1211         res = mono_array_new (mono_domain_get (), mono_defaults.int_class, size);
1212
1213         for (i = 0; i < size; i++)
1214                 mono_array_set (res, gpointer, i, native_trace [i]);
1215         return res;
1216 #else
1217         return NULL;
1218 #endif
1219 }
1220
1221 #define setup_managed_stacktrace_information() do {     \
1222         if (mono_ex && !initial_trace_ips) {    \
1223                 trace_ips = g_list_reverse (trace_ips); \
1224                 MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (trace_ips, mono_defaults.int_class));   \
1225                 MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ());  \
1226                 if (has_dynamic_methods)        \
1227                         /* These methods could go away anytime, so compute the stack trace now */       \
1228                         MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex));      \
1229         }       \
1230         g_list_free (trace_ips);        \
1231         trace_ips = NULL;       \
1232 } while (0)
1233 /*
1234  * mono_handle_exception_internal_first_pass:
1235  *
1236  *   The first pass of exception handling. Unwind the stack until a catch clause which can catch
1237  * OBJ is found. Run the index of the filter clause which caught the exception into
1238  * OUT_FILTER_IDX. Return TRUE if the exception is caught, FALSE otherwise.
1239  */
1240 static gboolean
1241 mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoObject *non_exception)
1242 {
1243         MonoDomain *domain = mono_domain_get ();
1244         MonoJitInfo *ji;
1245         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1246         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1247         MonoLMF *lmf = mono_get_lmf ();
1248         MonoArray *initial_trace_ips = NULL;
1249         GList *trace_ips = NULL;
1250         MonoException *mono_ex;
1251         gboolean stack_overflow = FALSE;
1252         MonoContext initial_ctx;
1253         int frame_count = 0;
1254         gboolean has_dynamic_methods = FALSE;
1255         gint32 filter_idx;
1256         int i;
1257         MonoObject *ex_obj;
1258
1259         g_assert (ctx != NULL);
1260
1261         if (obj == domain->stack_overflow_ex)
1262                 stack_overflow = TRUE;
1263
1264         mono_ex = (MonoException*)obj;
1265         initial_trace_ips = mono_ex->trace_ips;
1266
1267         if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1268                 mono_ex = (MonoException*)obj;
1269                 initial_trace_ips = mono_ex->trace_ips;
1270         } else {
1271                 mono_ex = NULL;
1272         }
1273
1274         if (!call_filter)
1275                 call_filter = mono_get_call_filter ();
1276
1277         g_assert (jit_tls->end_of_stack);
1278         g_assert (jit_tls->abort_func);
1279
1280         if (out_filter_idx)
1281                 *out_filter_idx = -1;
1282         if (out_ji)
1283                 *out_ji = NULL;
1284         filter_idx = 0;
1285         initial_ctx = *ctx;
1286
1287         while (1) {
1288                 MonoContext new_ctx;
1289                 guint32 free_stack;
1290                 int clause_index_start = 0;
1291                 gboolean unwind_res = TRUE;
1292                 
1293                 StackFrameInfo frame;
1294
1295                 unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1296                 if (unwind_res) {
1297                         if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
1298                                 *ctx = new_ctx;
1299                                 continue;
1300                         }
1301                         g_assert (frame.type == FRAME_TYPE_MANAGED);
1302                         ji = frame.ji;
1303                 }
1304
1305                 if (!unwind_res) {
1306                         setup_managed_stacktrace_information ();
1307                         return FALSE;
1308                 }
1309
1310                 frame_count ++;
1311                 //printf ("M: %s %d.\n", mono_method_full_name (ji->method, TRUE), frame_count);
1312
1313                 if (mini_get_debug_options ()->reverse_pinvoke_exceptions && ji->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
1314                         g_error ("A native frame was found while unwinding the stack after an exception.\n"
1315                                          "The native frame called the managed method:\n%s\n",
1316                                          mono_method_full_name (ji->method, TRUE));
1317                 }
1318
1319                 if (ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
1320                         /* 
1321                          * Avoid overwriting the stack trace if the exception is
1322                          * rethrown. Also avoid giant stack traces during a stack
1323                          * overflow.
1324                          */
1325                         if (!initial_trace_ips && (frame_count < 1000)) {
1326                                 trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
1327                                 trace_ips = g_list_prepend (trace_ips,
1328                                                                                         get_generic_info_from_stack_frame (ji, ctx));
1329                         }
1330                 }
1331
1332                 if (ji->method->dynamic)
1333                         has_dynamic_methods = TRUE;
1334
1335                 if (stack_overflow) {
1336                         if (DOES_STACK_GROWS_UP)
1337                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1338                         else
1339                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1340                 } else {
1341                         free_stack = 0xffffff;
1342                 }
1343                                 
1344                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1345                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1346                         gboolean filtered = FALSE;
1347
1348                         /* 
1349                          * During stack overflow, wait till the unwinding frees some stack
1350                          * space before running handlers/finalizers.
1351                          */
1352                         if (free_stack <= (64 * 1024))
1353                                 continue;
1354
1355                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1356                                 /* catch block */
1357                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1358
1359                                 /*
1360                                  * Have to unwrap RuntimeWrappedExceptions if the
1361                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1362                                  */
1363                                 if (non_exception && !wrap_non_exception_throws (ji->method))
1364                                         ex_obj = non_exception;
1365                                 else
1366                                         ex_obj = obj;
1367
1368                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1369                                         gboolean is_user_frame = ji->method->wrapper_type == MONO_WRAPPER_NONE || ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD;
1370                                         mono_perfcounters->exceptions_filters++;
1371                                         mono_debugger_call_exception_handler (ei->data.filter, MONO_CONTEXT_GET_SP (ctx), ex_obj);
1372
1373                                         /*
1374                                         Here's the thing, if this is a filter clause done by a wrapper like runtime invoke, we don't want to
1375                                         trim the stackframe since if it returns FALSE we lose information.
1376
1377                                         FIXME Not 100% sure if it's a good idea even with user clauses.
1378                                         */
1379                                         if (is_user_frame)
1380                                                 setup_managed_stacktrace_information ();
1381
1382                                         if (ji->from_llvm) {
1383 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1384                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1385 #else
1386                                                 g_assert_not_reached ();
1387 #endif
1388                                         } else {
1389                                                 /* store the exception object in bp + ei->exvar_offset */
1390                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1391                                         }
1392
1393                                         mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
1394                                         filtered = call_filter (ctx, ei->data.filter);
1395                                         mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
1396                                         if (filtered && out_filter_idx)
1397                                                 *out_filter_idx = filter_idx;
1398                                         if (out_ji)
1399                                                 *out_ji = ji;
1400                                         filter_idx ++;
1401
1402                                         if (filtered) {
1403                                                 if (!is_user_frame)
1404                                                         setup_managed_stacktrace_information ();
1405                                                 /* mono_debugger_agent_handle_exception () needs this */
1406                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1407                                                 return TRUE;
1408                                         }
1409                                 }
1410
1411                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) {
1412                                         setup_managed_stacktrace_information ();
1413
1414                                         if (out_ji)
1415                                                 *out_ji = ji;
1416
1417                                         /* mono_debugger_agent_handle_exception () needs this */
1418                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1419                                         return TRUE;
1420                                 }
1421                         }
1422                 }
1423
1424                 *ctx = new_ctx;
1425         }
1426
1427         g_assert_not_reached ();
1428 }
1429
1430 /**
1431  * mono_handle_exception_internal:
1432  * @ctx: saved processor state
1433  * @obj: the exception object
1434  * @resume: whenever to resume unwinding based on the state in MonoJitTlsData.
1435  */
1436 static gboolean
1437 mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume, MonoJitInfo **out_ji)
1438 {
1439         MonoDomain *domain = mono_domain_get ();
1440         MonoJitInfo *ji;
1441         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1442         static void (*restore_context) (void *);
1443         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1444         MonoLMF *lmf = mono_get_lmf ();
1445         MonoException *mono_ex;
1446         gboolean stack_overflow = FALSE;
1447         MonoContext initial_ctx;
1448         int frame_count = 0;
1449         gint32 filter_idx, first_filter_idx;
1450         int i;
1451         MonoObject *ex_obj;
1452         MonoObject *non_exception = NULL;
1453
1454         g_assert (ctx != NULL);
1455         if (!obj) {
1456                 MonoException *ex = mono_get_exception_null_reference ();
1457                 MONO_OBJECT_SETREF (ex, message, mono_string_new (domain, "Object reference not set to an instance of an object"));
1458                 obj = (MonoObject *)ex;
1459         } 
1460
1461         /*
1462          * Allocate a new exception object instead of the preconstructed ones.
1463          */
1464         if (obj == domain->stack_overflow_ex) {
1465                 /*
1466                  * It is not a good idea to try and put even more pressure on the little stack available.
1467                  * obj = mono_get_exception_stack_overflow ();
1468                  */
1469                 stack_overflow = TRUE;
1470         }
1471         else if (obj == domain->null_reference_ex) {
1472                 obj = mono_get_exception_null_reference ();
1473         }
1474
1475         if (!mono_object_isinst (obj, mono_defaults.exception_class)) {
1476                 non_exception = obj;
1477                 obj = mono_get_exception_runtime_wrapped (obj);
1478         }
1479
1480         mono_ex = (MonoException*)obj;
1481
1482         if (mono_object_isinst (obj, mono_defaults.exception_class)) {
1483                 mono_ex = (MonoException*)obj;
1484         } else {
1485                 mono_ex = NULL;
1486         }
1487
1488         if (mono_ex && jit_tls->class_cast_from) {
1489                 if (!strcmp (mono_ex->object.vtable->klass->name, "InvalidCastException")) {
1490                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1491                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1492                         char *msg = g_strdup_printf ("Unable to cast object of type '%s' to type '%s'.", from_name, to_name);
1493                         mono_ex->message = mono_string_new (domain, msg);
1494                         g_free (from_name);
1495                         g_free (to_name);
1496                         g_free (msg);
1497                 }
1498                 if (!strcmp (mono_ex->object.vtable->klass->name, "ArrayTypeMismatchException")) {
1499                         char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
1500                         char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
1501                         char *msg = g_strdup_printf ("Source array of type '%s' cannot be cast to destination array type '%s'.", from_name, to_name);
1502                         mono_ex->message = mono_string_new (domain, msg);
1503                         g_free (from_name);
1504                         g_free (to_name);
1505                         g_free (msg);
1506                 }
1507         }
1508
1509         if (!call_filter)
1510                 call_filter = mono_get_call_filter ();
1511
1512         if (!restore_context)
1513                 restore_context = mono_get_restore_context ();
1514
1515         g_assert (jit_tls->end_of_stack);
1516         g_assert (jit_tls->abort_func);
1517
1518         /*
1519          * We set orig_ex_ctx_set to TRUE/FALSE around profiler calls to make sure it doesn't
1520          * end up being TRUE on any code path.
1521          */
1522         memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
1523
1524         if (!resume) {
1525                 gboolean res;
1526
1527                 MonoContext ctx_cp = *ctx;
1528                 if (mono_trace_is_enabled ()) {
1529                         MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
1530                         MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
1531                         MonoObject *message;
1532                         const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
1533                         char *msg = NULL;
1534                         MonoObject *exc = NULL;
1535                         if (get_message == NULL) {
1536                                 message = NULL;
1537                         } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
1538                                 message = NULL;
1539                                 msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
1540                         } else {
1541                                 message = mono_runtime_invoke (get_message, obj, NULL, &exc);
1542                                 
1543                         }
1544                         if (msg == NULL) {
1545                                 msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
1546                         }
1547                         g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)GetCurrentThreadId (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg);
1548                         g_free (msg);
1549                         if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
1550                                 mono_print_thread_dump_from_ctx (ctx);
1551                 }
1552                 jit_tls->orig_ex_ctx_set = TRUE;
1553                 mono_profiler_exception_thrown (obj);
1554                 jit_tls->orig_ex_ctx_set = FALSE;
1555
1556                 res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, non_exception);
1557
1558                 if (!res) {
1559                         if (mini_get_debug_options ()->break_on_exc)
1560                                 G_BREAKPOINT ();
1561                         mono_debugger_agent_handle_exception (obj, ctx, NULL);
1562
1563                         if (mini_get_debug_options ()->suspend_on_unhandled) {
1564                                 fprintf (stderr, "Unhandled exception, suspending...");
1565                                 while (1)
1566                                         ;
1567                         }
1568
1569                         // FIXME: This runs managed code so it might cause another stack overflow when
1570                         // we are handling a stack overflow
1571                         mono_unhandled_exception (obj);
1572                 } else {
1573                         //
1574                         // Treat exceptions that are "handled" by mono_runtime_invoke() as unhandled.
1575                         // See bug #669836.
1576                         //
1577                         if (ji && ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)
1578                                 mono_debugger_agent_handle_exception (obj, ctx, NULL);
1579                         else
1580                                 mono_debugger_agent_handle_exception (obj, ctx, &ctx_cp);
1581                 }
1582         }
1583
1584         if (out_ji)
1585                 *out_ji = NULL;
1586         filter_idx = 0;
1587         initial_ctx = *ctx;
1588
1589         while (1) {
1590                 MonoContext new_ctx;
1591                 guint32 free_stack;
1592                 int clause_index_start = 0;
1593                 gboolean unwind_res = TRUE;
1594                 
1595                 if (resume) {
1596                         resume = FALSE;
1597                         ji = jit_tls->resume_state.ji;
1598                         new_ctx = jit_tls->resume_state.new_ctx;
1599                         clause_index_start = jit_tls->resume_state.clause_index;
1600                         lmf = jit_tls->resume_state.lmf;
1601                         first_filter_idx = jit_tls->resume_state.first_filter_idx;
1602                         filter_idx = jit_tls->resume_state.filter_idx;
1603                 } else {
1604                         StackFrameInfo frame;
1605
1606                         unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
1607                         if (unwind_res) {
1608                                 if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
1609                                         *ctx = new_ctx;
1610                                         continue;
1611                                 }
1612                                 g_assert (frame.type == FRAME_TYPE_MANAGED);
1613                                 ji = frame.ji;
1614                         }
1615                 }
1616
1617                 if (!unwind_res) {
1618                         *(mono_get_lmf_addr ()) = lmf;
1619
1620                         jit_tls->abort_func (obj);
1621                         g_assert_not_reached ();
1622                 }
1623
1624                 frame_count ++;
1625                 //printf ("M: %s %d.\n", mono_method_full_name (ji->method, TRUE), frame_count);
1626
1627                 if (stack_overflow) {
1628                         if (DOES_STACK_GROWS_UP)
1629                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
1630                         else
1631                                 free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
1632                 } else {
1633                         free_stack = 0xffffff;
1634                 }
1635                                 
1636                 for (i = clause_index_start; i < ji->num_clauses; i++) {
1637                         MonoJitExceptionInfo *ei = &ji->clauses [i];
1638                         gboolean filtered = FALSE;
1639
1640                         /* 
1641                          * During stack overflow, wait till the unwinding frees some stack
1642                          * space before running handlers/finalizers.
1643                          */
1644                         if (free_stack <= (64 * 1024))
1645                                 continue;
1646
1647                         if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
1648                                 /* catch block */
1649                                 MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
1650
1651                                 /*
1652                                  * Have to unwrap RuntimeWrappedExceptions if the
1653                                  * method's assembly doesn't have a RuntimeCompatibilityAttribute.
1654                                  */
1655                                 if (non_exception && !wrap_non_exception_throws (ji->method))
1656                                         ex_obj = non_exception;
1657                                 else
1658                                         ex_obj = obj;
1659
1660                                 if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
1661                                         if (ji->from_llvm) {
1662 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
1663                                                 MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
1664 #else
1665                                                 g_assert_not_reached ();
1666 #endif
1667                                         } else {
1668                                                 /* store the exception object in bp + ei->exvar_offset */
1669                                                 *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
1670                                         }
1671                                 }
1672
1673                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1674                                         /* 
1675                                          * Filter clauses should only be run in the 
1676                                          * first pass of exception handling.
1677                                          */
1678                                         filtered = (filter_idx == first_filter_idx);
1679                                         filter_idx ++;
1680                                 }
1681
1682                                 if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
1683                                          mono_object_isinst (ex_obj, catch_class)) || filtered) {
1684                                         /*
1685                                          * This guards against the situation that we abort a thread that is executing a finally clause
1686                                          * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
1687                                          * check for this situation here and resume interruption if we are below the guarded block.
1688                                          */
1689                                         if (G_UNLIKELY (jit_tls->handler_block_return_address)) {
1690                                                 gboolean is_outside = FALSE;
1691                                                 gpointer prot_bp = MONO_CONTEXT_GET_BP (&jit_tls->handler_block_context);
1692                                                 gpointer catch_bp = MONO_CONTEXT_GET_BP (ctx);
1693                                                 //FIXME make this stack direction aware
1694                                                 if (catch_bp > prot_bp) {
1695                                                         is_outside = TRUE;
1696                                                 } else if (catch_bp == prot_bp) {
1697                                                         /* Can be either try { try { } catch {} } finally {} or try { try { } finally {} } catch {}
1698                                                          * So we check if the catch handler_start is protected by the guarded handler protected region
1699                                                          *
1700                                                          * Assumptions:
1701                                                          *      If there is an outstanding guarded_block return address, it means the current thread must be aborted.
1702                                                          *      This is the only way to reach out the guarded block as other cases are handled by the trampoline.
1703                                                          *      There aren't any further finally/fault handler blocks down the stack over this exception.
1704                                                          *   This must be ensured by the code that installs the guard trampoline.
1705                                                          */
1706                                                         g_assert (ji == mini_jit_info_table_find (domain, MONO_CONTEXT_GET_IP (&jit_tls->handler_block_context), NULL));
1707
1708                                                         if (!is_address_protected (ji, jit_tls->handler_block, ei->handler_start)) {
1709                                                                 is_outside = TRUE;
1710                                                         }
1711                                                 }
1712                                                 if (is_outside) {
1713                                                         jit_tls->handler_block_return_address = NULL;
1714                                                         jit_tls->handler_block = NULL;
1715                                                         mono_thread_resume_interruption (); /*We ignore the exception here, it will be raised later*/
1716                                                 }
1717                                         }
1718
1719                                         if (mono_trace_is_enabled () && mono_trace_eval (ji->method))
1720                                                 g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
1721                                         jit_tls->orig_ex_ctx_set = TRUE;
1722                                         mono_profiler_exception_clause_handler (ji->method, ei->flags, i);
1723                                         jit_tls->orig_ex_ctx_set = FALSE;
1724                                         mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
1725                                         MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1726                                         *(mono_get_lmf_addr ()) = lmf;
1727                                         mono_perfcounters->exceptions_depth += frame_count;
1728                                         if (obj == domain->stack_overflow_ex)
1729                                                 jit_tls->handling_stack_ovf = FALSE;
1730
1731                                         return 0;
1732                                 }
1733                                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
1734                                         (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT)) {
1735                                         if (mono_trace_is_enabled () && mono_trace_eval (ji->method))
1736                                                 g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
1737                                         jit_tls->orig_ex_ctx_set = TRUE;
1738                                         mono_profiler_exception_clause_handler (ji->method, ei->flags, i);
1739                                         jit_tls->orig_ex_ctx_set = FALSE;
1740                                         mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
1741                                         call_filter (ctx, ei->handler_start);
1742                                 }
1743                                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
1744                                         (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
1745                                         if (mono_trace_is_enabled () && mono_trace_eval (ji->method))
1746                                                 g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
1747                                         jit_tls->orig_ex_ctx_set = TRUE;
1748                                         mono_profiler_exception_clause_handler (ji->method, ei->flags, i);
1749                                         jit_tls->orig_ex_ctx_set = FALSE;
1750                                         mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
1751                                         mono_perfcounters->exceptions_finallys++;
1752                                         *(mono_get_lmf_addr ()) = lmf;
1753                                         if (ji->from_llvm) {
1754                                                 /* 
1755                                                  * LLVM compiled finally handlers follow the design
1756                                                  * of the c++ ehabi, i.e. they call a resume function
1757                                                  * at the end instead of returning to the caller.
1758                                                  * So save the exception handling state,
1759                                                  * mono_resume_unwind () will call us again to continue
1760                                                  * the unwinding.
1761                                                  */
1762                                                 jit_tls->resume_state.ex_obj = obj;
1763                                                 jit_tls->resume_state.ji = ji;
1764                                                 jit_tls->resume_state.clause_index = i + 1;
1765                                                 jit_tls->resume_state.ctx = *ctx;
1766                                                 jit_tls->resume_state.new_ctx = new_ctx;
1767                                                 jit_tls->resume_state.lmf = lmf;
1768                                                 jit_tls->resume_state.first_filter_idx = first_filter_idx;
1769                                                 jit_tls->resume_state.filter_idx = filter_idx;
1770                                                 MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
1771                                                 return 0;
1772                                         } else {
1773                                                 call_filter (ctx, ei->handler_start);
1774                                         }
1775                                 }
1776                         }
1777                 }
1778
1779                 jit_tls->orig_ex_ctx_set = TRUE;
1780                 mono_profiler_exception_method_leave (ji->method);
1781                 jit_tls->orig_ex_ctx_set = FALSE;
1782
1783                 *ctx = new_ctx;
1784         }
1785
1786         g_assert_not_reached ();
1787 }
1788
1789 /*
1790  * mono_debugger_handle_exception:
1791  *
1792  *  Notify the debugger about exceptions.  Returns TRUE if the debugger wants us to stop
1793  *  at the exception and FALSE to resume with the normal exception handling.
1794  *
1795  *  The arch code is responsible to setup @ctx in a way that MONO_CONTEXT_GET_IP () and
1796  *  MONO_CONTEXT_GET_SP () point to the throw instruction; ie. before executing the
1797  *  `callq throw' instruction.
1798  */
1799 gboolean
1800 mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj)
1801 {
1802         MonoDebuggerExceptionAction action;
1803
1804         if (!mono_debug_using_mono_debugger ())
1805                 return FALSE;
1806
1807         if (!obj) {
1808                 MonoException *ex = mono_get_exception_null_reference ();
1809                 MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_domain_get (), "Object reference not set to an instance of an object"));
1810                 obj = (MonoObject *)ex;
1811         }
1812
1813         action = _mono_debugger_throw_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
1814
1815         if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP) {
1816                 /*
1817                  * The debugger wants us to stop on the `throw' instruction.
1818                  * By the time we get here, it already inserted a breakpoint there.
1819                  */
1820                 return TRUE;
1821         } else if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED) {
1822                 MonoContext ctx_cp = *ctx;
1823                 MonoJitInfo *ji = NULL;
1824                 gboolean ret;
1825
1826                 /*
1827                  * The debugger wants us to stop only if this exception is user-unhandled.
1828                  */
1829
1830                 ret = mono_handle_exception_internal_first_pass (&ctx_cp, obj, NULL, &ji, NULL);
1831                 if (ret && (ji != NULL) && (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)) {
1832                         /*
1833                          * The exception is handled in a runtime-invoke wrapper, that means that it's unhandled
1834                          * inside the method being invoked, so we handle it like a user-unhandled exception.
1835                          */
1836                         ret = FALSE;
1837                 }
1838
1839                 if (!ret) {
1840                         /*
1841                          * The exception is user-unhandled - tell the debugger to stop.
1842                          */
1843                         return _mono_debugger_unhandled_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
1844                 }
1845
1846                 /*
1847                  * The exception is catched somewhere - resume with the normal exception handling and don't
1848                  * stop in the debugger.
1849                  */
1850         }
1851
1852         return FALSE;
1853 }
1854
1855 /**
1856  * mono_debugger_run_finally:
1857  * @start_ctx: saved processor state
1858  *
1859  * This method is called by the Mono Debugger to call all `finally' clauses of the
1860  * current stack frame.  It's used when the user issues a `return' command to make
1861  * the current stack frame return.  After returning from this method, the debugger
1862  * unwinds the stack one frame and gives control back to the user.
1863  *
1864  * NOTE: This method is only used when running inside the Mono Debugger.
1865  */
1866 void
1867 mono_debugger_run_finally (MonoContext *start_ctx)
1868 {
1869         static int (*call_filter) (MonoContext *, gpointer) = NULL;
1870         MonoDomain *domain = mono_domain_get ();
1871         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1872         MonoLMF *lmf = mono_get_lmf ();
1873         MonoContext ctx, new_ctx;
1874         MonoJitInfo *ji, rji;
1875         int i;
1876
1877         ctx = *start_ctx;
1878
1879         ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
1880         if (!ji || ji == (gpointer)-1)
1881                 return;
1882
1883         if (!call_filter)
1884                 call_filter = mono_get_call_filter ();
1885
1886         for (i = 0; i < ji->num_clauses; i++) {
1887                 MonoJitExceptionInfo *ei = &ji->clauses [i];
1888
1889                 if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
1890                     (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
1891                         call_filter (&ctx, ei->handler_start);
1892                 }
1893         }
1894 }
1895
1896 /**
1897  * mono_handle_exception:
1898  * @ctx: saved processor state
1899  * @obj: the exception object
1900  */
1901 gboolean
1902 mono_handle_exception (MonoContext *ctx, gpointer obj)
1903 {
1904         mono_perfcounters->exceptions_thrown++;
1905
1906         return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
1907 }
1908
1909 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
1910
1911 #ifndef MONO_ARCH_USE_SIGACTION
1912 #error "Can't use sigaltstack without sigaction"
1913 #endif
1914
1915 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
1916
1917 void
1918 mono_setup_altstack (MonoJitTlsData *tls)
1919 {
1920         size_t stsize = 0;
1921         stack_t sa;
1922         guint8 *staddr = NULL;
1923
1924         if (mono_running_on_valgrind ())
1925                 return;
1926
1927         mono_thread_get_stack_bounds (&staddr, &stsize);
1928
1929         g_assert (staddr);
1930
1931         tls->end_of_stack = staddr + stsize;
1932         tls->stack_size = stsize;
1933
1934         /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
1935
1936         tls->stack_ovf_guard_base = staddr + mono_pagesize ();
1937         tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
1938
1939         g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
1940
1941         if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
1942                 /* mprotect can fail for the main thread stack */
1943                 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);
1944                 g_assert (gaddr == tls->stack_ovf_guard_base);
1945                 tls->stack_ovf_valloced = TRUE;
1946         }
1947
1948         /* Setup an alternate signal stack */
1949         tls->signal_stack = mono_valloc (0, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON);
1950         tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1951
1952         g_assert (tls->signal_stack);
1953
1954         sa.ss_sp = tls->signal_stack;
1955         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1956 #if __APPLE__
1957         sa.ss_flags = 0;
1958 #else
1959         sa.ss_flags = SS_ONSTACK;
1960 #endif
1961         g_assert (sigaltstack (&sa, NULL) == 0);
1962
1963         mono_gc_register_altstack ((char*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size, (char*)staddr + stsize - ((char*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size), tls->signal_stack, tls->signal_stack_size);
1964 }
1965
1966 void
1967 mono_free_altstack (MonoJitTlsData *tls)
1968 {
1969         stack_t sa;
1970         int err;
1971
1972         sa.ss_sp = tls->signal_stack;
1973         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
1974         sa.ss_flags = SS_DISABLE;
1975         err = sigaltstack  (&sa, NULL);
1976         g_assert (err == 0);
1977
1978         if (tls->signal_stack)
1979                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE);
1980         if (tls->stack_ovf_valloced)
1981                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size);
1982         else
1983                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
1984 }
1985
1986 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
1987
1988 void
1989 mono_setup_altstack (MonoJitTlsData *tls)
1990 {
1991 }
1992
1993 void
1994 mono_free_altstack (MonoJitTlsData *tls)
1995 {
1996 }
1997
1998 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
1999
2000 static gboolean
2001 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
2002 {
2003         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
2004         /* we need to leave some room for throwing the exception */
2005         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
2006                 unprotect_size -= mono_pagesize ();
2007         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
2008          * is sufficient stack
2009          */
2010         //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);
2011         if (unprotect_size)
2012                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
2013         return unprotect_size == jit_tls->stack_ovf_guard_size;
2014 }
2015
2016 static G_GNUC_UNUSED void
2017 try_more_restore (void)
2018 {
2019         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2020         if (try_restore_stack_protection (jit_tls, 500))
2021                 jit_tls->restore_stack_prot = NULL;
2022 }
2023
2024 static G_GNUC_UNUSED void
2025 restore_stack_protection (void)
2026 {
2027         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2028         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
2029         /* if we can't restore the stack protection, keep a callback installed so
2030          * we'll try to restore as much stack as we can at each return from unmanaged
2031          * code.
2032          */
2033         if (try_restore_stack_protection (jit_tls, 4096))
2034                 jit_tls->restore_stack_prot = NULL;
2035         else
2036                 jit_tls->restore_stack_prot = try_more_restore_tramp;
2037         /* here we also throw a stack overflow exception */
2038         ex->trace_ips = NULL;
2039         ex->stack_trace = NULL;
2040         mono_raise_exception (ex);
2041 }
2042
2043 gpointer
2044 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
2045 {
2046         void (*func)(void) = (gpointer)tramp_data;
2047         func ();
2048         return NULL;
2049 }
2050
2051 gboolean
2052 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2053 {
2054         /* we got a stack overflow in the soft-guard pages
2055          * There are two cases:
2056          * 1) managed code caused the overflow: we unprotect the soft-guard page
2057          * and let the arch-specific code trigger the exception handling mechanism
2058          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
2059          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
2060          * and hope we can continue with those enabled, at least until the hard-guard page
2061          * is hit. The alternative to continuing here is to just print a message and abort.
2062          * We may add in the future the code to protect the pages again in the codepath
2063          * when we return from unmanaged to managed code.
2064          */
2065         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2066                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2067                 /* we unprotect the minimum amount we can */
2068                 guint32 guard_size;
2069                 gboolean handled = FALSE;
2070
2071                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2072                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2073                         guard_size -= mono_pagesize ();
2074                 }
2075                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2076                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2077                 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);
2078 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2079                 if (ji) {
2080                         mono_arch_handle_altstack_exception (ctx, fault_addr, TRUE);
2081                         handled = TRUE;
2082                 }
2083 #endif
2084                 if (!handled) {
2085                         /* We print a message: after this even managed stack overflows
2086                          * may crash the runtime
2087                          */
2088                         fprintf (stderr, "Stack overflow in unmanaged: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), fault_addr);
2089                         if (!jit_tls->handling_stack_ovf) {
2090                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2091                                 jit_tls->handling_stack_ovf = 1;
2092                         } else {
2093                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2094                         }
2095                 }
2096                 return TRUE;
2097         }
2098         return FALSE;
2099 }
2100
2101 typedef struct {
2102         FILE *stream;
2103         MonoMethod *omethod;
2104         int count;
2105 } PrintOverflowUserData;
2106
2107 static gboolean
2108 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2109 {
2110         MonoMethod *method = NULL;
2111         PrintOverflowUserData *user_data = data;
2112         FILE *stream = user_data->stream;
2113         gchar *location;
2114
2115         if (frame->ji)
2116                 method = frame->ji->method;
2117
2118         if (method) {
2119                 if (user_data->count == 0) {
2120                         /* The first frame is in its prolog, so a line number cannot be computed */
2121                         user_data->count ++;
2122                         return FALSE;
2123                 }
2124
2125                 /* If this is a one method overflow, skip the other instances */
2126                 if (method == user_data->omethod)
2127                         return FALSE;
2128
2129                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2130                 fprintf (stream, "  %s\n", location);
2131                 g_free (location);
2132
2133                 if (user_data->count == 1) {
2134                         fprintf (stream, "  <...>\n");
2135                         user_data->omethod = method;
2136                 } else {
2137                         user_data->omethod = NULL;
2138                 }
2139
2140                 user_data->count ++;
2141         } else
2142                 fprintf (stream, "  at <unknown> <0x%05x>\n", frame->native_offset);
2143
2144         return FALSE;
2145 }
2146
2147 void
2148 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2149 {
2150         PrintOverflowUserData ud;
2151         MonoContext mctx;
2152
2153         /* we don't do much now, but we can warn the user with a useful message */
2154         fprintf (stderr, "Stack overflow: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), fault_addr);
2155
2156 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2157         mono_arch_sigctx_to_monoctx (ctx, &mctx);
2158                         
2159         fprintf (stderr, "Stacktrace:\n");
2160
2161         memset (&ud, 0, sizeof (ud));
2162         ud.stream = stderr;
2163
2164         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2165 #else
2166         if (ji && ji->method)
2167                 fprintf (stderr, "At %s\n", mono_method_full_name (ji->method, TRUE));
2168         else
2169                 fprintf (stderr, "At <unmanaged>.\n");
2170 #endif
2171
2172         _exit (1);
2173 }
2174
2175 static gboolean
2176 print_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2177 {
2178         FILE *stream = (FILE*)data;
2179         MonoMethod *method = NULL;
2180         if (frame->ji)
2181                 method = frame->ji->method;
2182
2183         if (method) {
2184                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2185                 fprintf (stream, "  %s\n", location);
2186                 g_free (location);
2187         } else
2188                 fprintf (stream, "  at <unknown> <0x%05x>\n", frame->native_offset);
2189
2190         return FALSE;
2191 }
2192
2193 static G_GNUC_UNUSED gboolean
2194 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2195 {
2196         GString *p = (GString*)data;
2197         MonoMethod *method = NULL;
2198         if (frame->ji)
2199                 method = frame->ji->method;
2200
2201         if (method) {
2202                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2203                 g_string_append_printf (p, "  %s\n", location);
2204                 g_free (location);
2205         } else
2206                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2207
2208         return FALSE;
2209 }
2210
2211 static gboolean handling_sigsegv = FALSE;
2212
2213 /*
2214  * mono_handle_native_sigsegv:
2215  *
2216  *   Handle a SIGSEGV received while in native code by printing diagnostic 
2217  * information and aborting.
2218  */
2219 void
2220 mono_handle_native_sigsegv (int signal, void *ctx)
2221 {
2222 #ifdef MONO_ARCH_USE_SIGACTION
2223         struct sigaction sa;
2224 #endif
2225         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2226
2227         if (handling_sigsegv)
2228                 return;
2229
2230         if (mini_get_debug_options ()->suspend_on_sigsegv) {
2231                 fprintf (stderr, "Received SIGSEGV, suspending...");
2232                 while (1)
2233                         ;
2234         }
2235
2236         /* To prevent infinite loops when the stack walk causes a crash */
2237         handling_sigsegv = TRUE;
2238
2239         /* !jit_tls means the thread was not registered with the runtime */
2240         if (jit_tls && mono_thread_internal_current ()) {
2241                 fprintf (stderr, "Stacktrace:\n\n");
2242
2243                 mono_walk_stack (print_stack_frame, TRUE, stderr);
2244
2245                 fflush (stderr);
2246         }
2247
2248 #ifdef HAVE_BACKTRACE_SYMBOLS
2249  {
2250         void *array [256];
2251         char **names;
2252         int i, size;
2253         const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
2254
2255         fprintf (stderr, "\nNative stacktrace:\n\n");
2256
2257         size = backtrace (array, 256);
2258         names = backtrace_symbols (array, size);
2259         for (i =0; i < size; ++i) {
2260                 fprintf (stderr, "\t%s\n", names [i]);
2261         }
2262         free (names);
2263
2264         fflush (stderr);
2265
2266         /* Try to get more meaningful information using gdb */
2267
2268 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2269         if (!mini_get_debug_options ()->no_gdb_backtrace && !mono_debug_using_mono_debugger ()) {
2270                 /* From g_spawn_command_line_sync () in eglib */
2271                 pid_t pid;
2272                 int status;
2273                 pid_t crashed_pid = getpid ();
2274
2275                 //pid = fork ();
2276                 /*
2277                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2278                  * it will deadlock. Call the syscall directly instead.
2279                  */
2280                 pid = mono_runtime_syscall_fork ();
2281
2282                 if (pid == 0) {
2283                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2284
2285                         mono_gdb_render_native_backtraces (crashed_pid);
2286                         exit (1);
2287                 }
2288
2289                 fprintf (stderr, "\nDebug info from gdb:\n\n");
2290                 waitpid (pid, &status, 0);
2291         }
2292 #endif
2293         /*
2294          * A SIGSEGV indicates something went very wrong so we can no longer depend
2295          * on anything working. So try to print out lots of diagnostics, starting 
2296          * with ones which have a greater chance of working.
2297          */
2298         fprintf (stderr,
2299                          "\n"
2300                          "=================================================================\n"
2301                          "Got a %s while executing native code. This usually indicates\n"
2302                          "a fatal error in the mono runtime or one of the native libraries \n"
2303                          "used by your application.\n"
2304                          "=================================================================\n"
2305                          "\n", signal_str);
2306
2307  }
2308 #endif
2309
2310 #ifdef MONO_ARCH_USE_SIGACTION
2311
2312         /* Remove our SIGABRT handler */
2313         sa.sa_handler = SIG_DFL;
2314         sigemptyset (&sa.sa_mask);
2315         sa.sa_flags = 0;
2316
2317         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2318
2319 #endif
2320
2321         abort ();
2322 }
2323
2324 static void
2325 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2326 {
2327         MonoInternalThread *thread = mono_thread_internal_current ();
2328 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2329         MonoContext ctx;
2330 #endif
2331         GString* text = g_string_new (0);
2332         char *name, *wapi_desc;
2333         GError *error = NULL;
2334
2335         if (thread->name) {
2336                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2337                 g_assert (!error);
2338                 g_string_append_printf (text, "\n\"%s\"", name);
2339                 g_free (name);
2340         }
2341         else if (thread->threadpool_thread)
2342                 g_string_append (text, "\n\"<threadpool thread>\"");
2343         else
2344                 g_string_append (text, "\n\"<unnamed thread>\"");
2345
2346 #ifndef HOST_WIN32
2347         wapi_desc = wapi_current_thread_desc ();
2348         g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
2349         free (wapi_desc);
2350 #endif
2351
2352 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2353         if (start_ctx) {
2354                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2355         } else if (!sigctx)
2356                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2357         else
2358                 mono_arch_sigctx_to_monoctx (sigctx, &ctx);
2359
2360         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2361 #else
2362         printf ("\t<Stack traces in thread dumps not supported on this platform>\n");
2363 #endif
2364
2365         fprintf (stdout, "%s", text->str);
2366
2367 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2368         OutputDebugStringA(text->str);
2369 #endif
2370
2371         g_string_free (text, TRUE);
2372         fflush (stdout);
2373 }
2374
2375 /*
2376  * mono_print_thread_dump:
2377  *
2378  *   Print information about the current thread to stdout.
2379  * SIGCTX can be NULL, allowing this to be called from gdb.
2380  */
2381 void
2382 mono_print_thread_dump (void *sigctx)
2383 {
2384         mono_print_thread_dump_internal (sigctx, NULL);
2385 }
2386
2387 void
2388 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2389 {
2390         mono_print_thread_dump_internal (NULL, ctx);
2391 }
2392
2393 /*
2394  * mono_resume_unwind:
2395  *
2396  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2397  * unwinding.
2398  */
2399 void
2400 mono_resume_unwind (MonoContext *ctx)
2401 {
2402         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2403         static void (*restore_context) (MonoContext *);
2404         MonoContext new_ctx;
2405
2406         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2407         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2408         new_ctx = *ctx;
2409
2410         mono_handle_exception_internal (&new_ctx, jit_tls->resume_state.ex_obj, TRUE, NULL);
2411
2412         if (!restore_context)
2413                 restore_context = mono_get_restore_context ();
2414
2415         restore_context (&new_ctx);
2416 }
2417
2418 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2419
2420 typedef struct {
2421         MonoJitInfo *ji;
2422         MonoContext ctx;
2423         MonoJitExceptionInfo *ei;
2424 } FindHandlerBlockData;
2425
2426 static gboolean
2427 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2428 {
2429         int i;
2430         gpointer ip;
2431         FindHandlerBlockData *pdata = data;
2432         MonoJitInfo *ji = frame->ji;
2433
2434         if (!ji)
2435                 return FALSE;
2436
2437         if (ji->method->wrapper_type)
2438                 return FALSE;
2439
2440         ip = MONO_CONTEXT_GET_IP (ctx);
2441
2442         for (i = 0; i < ji->num_clauses; ++i) {
2443                 MonoJitExceptionInfo *ei = ji->clauses + i;
2444                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2445                         continue;
2446                 /*If ip points to the first instruction it means the handler block didn't start
2447                  so we can leave its execution to the EH machinery*/
2448                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2449                         pdata->ji = ji;
2450                         pdata->ei = ei;
2451                         pdata->ctx = *ctx;
2452                         break;
2453                 }
2454         }
2455         return FALSE;
2456 }
2457
2458
2459 static gpointer
2460 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2461 {
2462         int i;
2463         MonoJitExceptionInfo *clause = NULL;
2464         gpointer ip;
2465
2466         ip = MONO_CONTEXT_GET_IP (ctx);
2467
2468         for (i = 0; i < ji->num_clauses; ++i) {
2469                 clause = &ji->clauses [i];
2470                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2471                         continue;
2472                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2473                         break;
2474         }
2475
2476         /*no matching finally */
2477         if (i == ji->num_clauses)
2478                 return NULL;
2479
2480         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2481         if (ip == clause->handler_start)
2482                 return NULL;
2483
2484         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2485 }
2486
2487 /*
2488  * Finds the bottom handler block running and install a block guard if needed.
2489  * FIXME add full-aot support.
2490  */
2491 gboolean
2492 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2493 {
2494         FindHandlerBlockData data = { 0 };
2495         MonoJitTlsData *jit_tls = ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2496         gpointer resume_ip;
2497
2498         /* FIXME */
2499         if (mono_aot_only)
2500                 return FALSE;
2501
2502         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2503          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2504          */
2505         if (!jit_tls || jit_tls->handler_block_return_address)
2506                 return FALSE;
2507
2508         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_SIGNAL_SAFE, &data);
2509
2510         if (!data.ji)
2511                 return FALSE;
2512
2513         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2514
2515         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2516         if (resume_ip == NULL)
2517                 return FALSE;
2518
2519         jit_tls->handler_block_return_address = resume_ip;
2520         jit_tls->handler_block = data.ei;
2521
2522         return TRUE;
2523 }
2524
2525 #else
2526 gboolean
2527 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2528 {
2529         return FALSE;
2530 }
2531
2532 #endif
2533
2534 void
2535 mono_set_cast_details (MonoClass *from, MonoClass *to)
2536 {
2537         MonoJitTlsData *jit_tls = NULL;
2538
2539         if (mini_get_debug_options ()->better_cast_details) {
2540                 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2541                 jit_tls->class_cast_from = from;
2542                 jit_tls->class_cast_to = to;
2543         }
2544 }
2545
2546
2547 /*returns false if the thread is not attached*/
2548 gboolean
2549 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
2550 {
2551 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2552         MonoInternalThread *thread = mono_thread_internal_current ();
2553         if (!thread || !thread->jit_data) {
2554                 ctx->valid = FALSE;
2555                 return FALSE;
2556         }
2557
2558         if (sigctx)
2559                 mono_arch_sigctx_to_monoctx (sigctx, &ctx->ctx);
2560         else
2561 #if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE)
2562                 MONO_CONTEXT_GET_CURRENT (ctx->ctx);
2563 #else
2564                 g_error ("Use a null sigctx requires a working mono-context");
2565 #endif
2566
2567         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2568         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2569         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2570         ctx->valid = TRUE;
2571         return TRUE;
2572 #else
2573         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
2574         return FALSE;
2575 #endif
2576 }
2577
2578 gboolean
2579 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
2580 {
2581         MonoInternalThread *thread = mono_thread_internal_current ();
2582         if (!thread || !thread->jit_data) {
2583                 ctx->valid = FALSE;
2584                 return FALSE;
2585         }
2586
2587         ctx->ctx = *mctx;
2588         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2589         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2590         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2591         ctx->valid = TRUE;
2592         return TRUE;
2593 }
2594
2595 /*returns false if the thread is not attached*/
2596 gboolean
2597 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
2598 {
2599         MonoInternalThread *thread = mono_thread_internal_current ();
2600         MONO_ARCH_CONTEXT_DEF
2601
2602         mono_arch_flush_register_windows ();
2603
2604         if (!thread || !thread->jit_data) {
2605                 ctx->valid = FALSE;
2606                 return FALSE;
2607         }
2608 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
2609         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
2610 #else
2611         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
2612 #endif
2613                 
2614         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2615         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2616         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2617         ctx->valid = TRUE;
2618         return TRUE;
2619 }
2620
2621 static void
2622 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
2623 {
2624         void (*restore_context) (MonoContext *);
2625         restore_context = mono_get_restore_context ();
2626
2627         mono_handle_exception (ctx, exc);
2628         restore_context (ctx);
2629 }
2630
2631 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
2632 void
2633 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
2634 {
2635 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
2636         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2637         jit_tls->ex_ctx = *ctx;
2638
2639         mono_arch_setup_async_callback (ctx, async_cb, user_data);
2640 #else
2641         g_error ("This target doesn't support mono_arch_setup_async_callback");
2642 #endif
2643 }