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