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