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