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