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