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