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