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