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