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