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