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