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