Merge pull request #615 from nealef/master
[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         sa.ss_flags = 0;
2006         g_assert (sigaltstack (&sa, NULL) == 0);
2007
2008         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);
2009 }
2010
2011 void
2012 mono_free_altstack (MonoJitTlsData *tls)
2013 {
2014         stack_t sa;
2015         int err;
2016
2017         sa.ss_sp = tls->signal_stack;
2018         sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
2019         sa.ss_flags = SS_DISABLE;
2020         err = sigaltstack  (&sa, NULL);
2021         g_assert (err == 0);
2022
2023         if (tls->signal_stack)
2024                 mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE);
2025         if (tls->stack_ovf_valloced)
2026                 mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size);
2027         else
2028                 mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
2029 }
2030
2031 #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2032
2033 void
2034 mono_setup_altstack (MonoJitTlsData *tls)
2035 {
2036 }
2037
2038 void
2039 mono_free_altstack (MonoJitTlsData *tls)
2040 {
2041 }
2042
2043 #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
2044
2045 static gboolean
2046 try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
2047 {
2048         gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
2049         /* we need to leave some room for throwing the exception */
2050         while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
2051                 unprotect_size -= mono_pagesize ();
2052         /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
2053          * is sufficient stack
2054          */
2055         //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);
2056         if (unprotect_size)
2057                 mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
2058         return unprotect_size == jit_tls->stack_ovf_guard_size;
2059 }
2060
2061 static G_GNUC_UNUSED void
2062 try_more_restore (void)
2063 {
2064         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2065         if (try_restore_stack_protection (jit_tls, 500))
2066                 jit_tls->restore_stack_prot = NULL;
2067 }
2068
2069 static G_GNUC_UNUSED void
2070 restore_stack_protection (void)
2071 {
2072         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2073         MonoException *ex = mono_domain_get ()->stack_overflow_ex;
2074         /* if we can't restore the stack protection, keep a callback installed so
2075          * we'll try to restore as much stack as we can at each return from unmanaged
2076          * code.
2077          */
2078         if (try_restore_stack_protection (jit_tls, 4096))
2079                 jit_tls->restore_stack_prot = NULL;
2080         else
2081                 jit_tls->restore_stack_prot = try_more_restore_tramp;
2082         /* here we also throw a stack overflow exception */
2083         ex->trace_ips = NULL;
2084         ex->stack_trace = NULL;
2085         mono_raise_exception (ex);
2086 }
2087
2088 gpointer
2089 mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
2090 {
2091         void (*func)(void) = (gpointer)tramp_data;
2092         func ();
2093         return NULL;
2094 }
2095
2096 gboolean
2097 mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2098 {
2099         /* we got a stack overflow in the soft-guard pages
2100          * There are two cases:
2101          * 1) managed code caused the overflow: we unprotect the soft-guard page
2102          * and let the arch-specific code trigger the exception handling mechanism
2103          * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
2104          * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
2105          * and hope we can continue with those enabled, at least until the hard-guard page
2106          * is hit. The alternative to continuing here is to just print a message and abort.
2107          * We may add in the future the code to protect the pages again in the codepath
2108          * when we return from unmanaged to managed code.
2109          */
2110         if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
2111                         fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
2112                 /* we unprotect the minimum amount we can */
2113                 guint32 guard_size;
2114                 gboolean handled = FALSE;
2115
2116                 guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
2117                 while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
2118                         guard_size -= mono_pagesize ();
2119                 }
2120                 guard_size = jit_tls->stack_ovf_guard_size - guard_size;
2121                 /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
2122                 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);
2123 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
2124                 if (ji) {
2125                         mono_arch_handle_altstack_exception (ctx, fault_addr, TRUE);
2126                         handled = TRUE;
2127                 }
2128 #endif
2129                 if (!handled) {
2130                         /* We print a message: after this even managed stack overflows
2131                          * may crash the runtime
2132                          */
2133                         mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2134                         if (!jit_tls->handling_stack_ovf) {
2135                                 jit_tls->restore_stack_prot = restore_stack_protection_tramp;
2136                                 jit_tls->handling_stack_ovf = 1;
2137                         } else {
2138                                 /*fprintf (stderr, "Already handling stack overflow\n");*/
2139                         }
2140                 }
2141                 return TRUE;
2142         }
2143         return FALSE;
2144 }
2145
2146 typedef struct {
2147         MonoMethod *omethod;
2148         int count;
2149 } PrintOverflowUserData;
2150
2151 static gboolean
2152 print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2153 {
2154         MonoMethod *method = NULL;
2155         PrintOverflowUserData *user_data = data;
2156         gchar *location;
2157
2158         if (frame->ji)
2159                 method = frame->ji->method;
2160
2161         if (method) {
2162                 if (user_data->count == 0) {
2163                         /* The first frame is in its prolog, so a line number cannot be computed */
2164                         user_data->count ++;
2165                         return FALSE;
2166                 }
2167
2168                 /* If this is a one method overflow, skip the other instances */
2169                 if (method == user_data->omethod)
2170                         return FALSE;
2171
2172                 location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2173                 mono_runtime_printf_err ("  %s", location);
2174                 g_free (location);
2175
2176                 if (user_data->count == 1) {
2177                         mono_runtime_printf_err ("  <...>");
2178                         user_data->omethod = method;
2179                 } else {
2180                         user_data->omethod = NULL;
2181                 }
2182
2183                 user_data->count ++;
2184         } else
2185                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2186
2187         return FALSE;
2188 }
2189
2190 void
2191 mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
2192 {
2193         PrintOverflowUserData ud;
2194         MonoContext mctx;
2195
2196         /* we don't do much now, but we can warn the user with a useful message */
2197         mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
2198
2199 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2200         mono_arch_sigctx_to_monoctx (ctx, &mctx);
2201                         
2202         mono_runtime_printf_err ("Stacktrace:");
2203
2204         memset (&ud, 0, sizeof (ud));
2205
2206         mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
2207 #else
2208         if (ji && ji->method)
2209                 mono_runtime_printf_err ("At %s", mono_method_full_name (ji->method, TRUE));
2210         else
2211                 mono_runtime_printf_err ("At <unmanaged>.");
2212 #endif
2213
2214         _exit (1);
2215 }
2216
2217 static gboolean
2218 print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2219 {
2220         MonoMethod *method = NULL;
2221         if (frame->ji)
2222                 method = frame->ji->method;
2223
2224         if (method) {
2225                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2226                 mono_runtime_printf_err ("  %s", location);
2227                 g_free (location);
2228         } else
2229                 mono_runtime_printf_err ("  at <unknown> <0x%05x>", frame->native_offset);
2230
2231         return FALSE;
2232 }
2233
2234 static G_GNUC_UNUSED gboolean
2235 print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2236 {
2237         GString *p = (GString*)data;
2238         MonoMethod *method = NULL;
2239         if (frame->ji)
2240                 method = frame->ji->method;
2241
2242         if (method) {
2243                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
2244                 g_string_append_printf (p, "  %s\n", location);
2245                 g_free (location);
2246         } else
2247                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
2248
2249         return FALSE;
2250 }
2251
2252 static gboolean handling_sigsegv = FALSE;
2253
2254 /*
2255  * mono_handle_native_sigsegv:
2256  *
2257  *   Handle a SIGSEGV received while in native code by printing diagnostic 
2258  * information and aborting.
2259  */
2260 void
2261 mono_handle_native_sigsegv (int signal, void *ctx)
2262 {
2263 #ifdef MONO_ARCH_USE_SIGACTION
2264         struct sigaction sa;
2265 #endif
2266         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2267         const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
2268
2269         if (handling_sigsegv)
2270                 return;
2271
2272         if (mini_get_debug_options ()->suspend_on_sigsegv) {
2273                 mono_runtime_printf_err ("Received SIGSEGV, suspending...");
2274                 while (1)
2275                         ;
2276         }
2277
2278         /* To prevent infinite loops when the stack walk causes a crash */
2279         handling_sigsegv = TRUE;
2280
2281         /* !jit_tls means the thread was not registered with the runtime */
2282         if (jit_tls && mono_thread_internal_current ()) {
2283                 mono_runtime_printf_err ("Stacktrace:\n");
2284
2285                 mono_walk_stack (print_stack_frame_to_stderr, TRUE, NULL);
2286         }
2287
2288 #ifdef HAVE_BACKTRACE_SYMBOLS
2289  {
2290         void *array [256];
2291         char **names;
2292         int i, size;
2293
2294         mono_runtime_printf_err ("\nNative stacktrace:\n");
2295
2296         size = backtrace (array, 256);
2297         names = backtrace_symbols (array, size);
2298         for (i =0; i < size; ++i) {
2299                 mono_runtime_printf_err ("\t%s", names [i]);
2300         }
2301         free (names);
2302
2303         /* Try to get more meaningful information using gdb */
2304
2305 #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
2306         if (!mini_get_debug_options ()->no_gdb_backtrace && !mono_debug_using_mono_debugger ()) {
2307                 /* From g_spawn_command_line_sync () in eglib */
2308                 pid_t pid;
2309                 int status;
2310                 pid_t crashed_pid = getpid ();
2311
2312                 //pid = fork ();
2313                 /*
2314                  * glibc fork acquires some locks, so if the crash happened inside malloc/free,
2315                  * it will deadlock. Call the syscall directly instead.
2316                  */
2317                 pid = mono_runtime_syscall_fork ();
2318
2319                 if (pid == 0) {
2320                         dup2 (STDERR_FILENO, STDOUT_FILENO);
2321
2322                         mono_gdb_render_native_backtraces (crashed_pid);
2323                         exit (1);
2324                 }
2325
2326                 mono_runtime_printf_err ("\nDebug info from gdb:\n");
2327                 waitpid (pid, &status, 0);
2328         }
2329 #endif
2330  }
2331 #endif
2332
2333         /*
2334          * A SIGSEGV indicates something went very wrong so we can no longer depend
2335          * on anything working. So try to print out lots of diagnostics, starting 
2336          * with ones which have a greater chance of working.
2337          */
2338         mono_runtime_printf_err (
2339                          "\n"
2340                          "=================================================================\n"
2341                          "Got a %s while executing native code. This usually indicates\n"
2342                          "a fatal error in the mono runtime or one of the native libraries \n"
2343                          "used by your application.\n"
2344                          "=================================================================\n",
2345                         signal_str);
2346
2347
2348 #ifdef MONO_ARCH_USE_SIGACTION
2349
2350         /* Remove our SIGABRT handler */
2351         sa.sa_handler = SIG_DFL;
2352         sigemptyset (&sa.sa_mask);
2353         sa.sa_flags = 0;
2354
2355         g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
2356
2357 #endif
2358
2359         /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
2360 #if defined (PLATFORM_ANDROID)
2361         exit (-1);
2362 #else
2363         abort ();
2364 #endif
2365 }
2366
2367 static void
2368 mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
2369 {
2370         MonoInternalThread *thread = mono_thread_internal_current ();
2371 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2372         MonoContext ctx;
2373 #endif
2374         GString* text = g_string_new (0);
2375         char *name, *wapi_desc;
2376         GError *error = NULL;
2377
2378         if (thread->name) {
2379                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
2380                 g_assert (!error);
2381                 g_string_append_printf (text, "\n\"%s\"", name);
2382                 g_free (name);
2383         }
2384         else if (thread->threadpool_thread)
2385                 g_string_append (text, "\n\"<threadpool thread>\"");
2386         else
2387                 g_string_append (text, "\n\"<unnamed thread>\"");
2388
2389 #ifndef HOST_WIN32
2390         wapi_desc = wapi_current_thread_desc ();
2391         g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
2392         free (wapi_desc);
2393 #endif
2394
2395 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2396         if (start_ctx) {
2397                 memcpy (&ctx, start_ctx, sizeof (MonoContext));
2398         } else if (!sigctx)
2399                 MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
2400         else
2401                 mono_arch_sigctx_to_monoctx (sigctx, &ctx);
2402
2403         mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
2404 #else
2405         mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
2406 #endif
2407
2408         mono_runtime_printf ("%s", text->str);
2409
2410 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
2411         OutputDebugStringA(text->str);
2412 #endif
2413
2414         g_string_free (text, TRUE);
2415         mono_runtime_stdout_fflush ();
2416 }
2417
2418 /*
2419  * mono_print_thread_dump:
2420  *
2421  *   Print information about the current thread to stdout.
2422  * SIGCTX can be NULL, allowing this to be called from gdb.
2423  */
2424 void
2425 mono_print_thread_dump (void *sigctx)
2426 {
2427         mono_print_thread_dump_internal (sigctx, NULL);
2428 }
2429
2430 void
2431 mono_print_thread_dump_from_ctx (MonoContext *ctx)
2432 {
2433         mono_print_thread_dump_internal (NULL, ctx);
2434 }
2435
2436 /*
2437  * mono_resume_unwind:
2438  *
2439  *   This is called by a trampoline from LLVM compiled finally clauses to continue
2440  * unwinding.
2441  */
2442 void
2443 mono_resume_unwind (MonoContext *ctx)
2444 {
2445         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2446         static void (*restore_context) (MonoContext *);
2447         MonoContext new_ctx;
2448
2449         MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
2450         MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
2451         new_ctx = *ctx;
2452
2453         mono_handle_exception_internal (&new_ctx, jit_tls->resume_state.ex_obj, TRUE, NULL);
2454
2455         if (!restore_context)
2456                 restore_context = mono_get_restore_context ();
2457
2458         restore_context (&new_ctx);
2459 }
2460
2461 #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
2462
2463 typedef struct {
2464         MonoJitInfo *ji;
2465         MonoContext ctx;
2466         MonoJitExceptionInfo *ei;
2467 } FindHandlerBlockData;
2468
2469 static gboolean
2470 find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
2471 {
2472         int i;
2473         gpointer ip;
2474         FindHandlerBlockData *pdata = data;
2475         MonoJitInfo *ji = frame->ji;
2476
2477         if (!ji)
2478                 return FALSE;
2479
2480         if (ji->method->wrapper_type)
2481                 return FALSE;
2482
2483         ip = MONO_CONTEXT_GET_IP (ctx);
2484
2485         for (i = 0; i < ji->num_clauses; ++i) {
2486                 MonoJitExceptionInfo *ei = ji->clauses + i;
2487                 if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2488                         continue;
2489                 /*If ip points to the first instruction it means the handler block didn't start
2490                  so we can leave its execution to the EH machinery*/
2491                 if (ei->handler_start < ip && ip < ei->data.handler_end) {
2492                         pdata->ji = ji;
2493                         pdata->ei = ei;
2494                         pdata->ctx = *ctx;
2495                         break;
2496                 }
2497         }
2498         return FALSE;
2499 }
2500
2501
2502 static gpointer
2503 install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
2504 {
2505         int i;
2506         MonoJitExceptionInfo *clause = NULL;
2507         gpointer ip;
2508
2509         ip = MONO_CONTEXT_GET_IP (ctx);
2510
2511         for (i = 0; i < ji->num_clauses; ++i) {
2512                 clause = &ji->clauses [i];
2513                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
2514                         continue;
2515                 if (clause->handler_start < ip && clause->data.handler_end > ip)
2516                         break;
2517         }
2518
2519         /*no matching finally */
2520         if (i == ji->num_clauses)
2521                 return NULL;
2522
2523         /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
2524         if (ip == clause->handler_start)
2525                 return NULL;
2526
2527         return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
2528 }
2529
2530 /*
2531  * Finds the bottom handler block running and install a block guard if needed.
2532  * FIXME add full-aot support.
2533  */
2534 gboolean
2535 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2536 {
2537         FindHandlerBlockData data = { 0 };
2538         MonoJitTlsData *jit_tls = ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
2539         gpointer resume_ip;
2540
2541         /* FIXME */
2542         if (mono_aot_only)
2543                 return FALSE;
2544
2545         /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
2546          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
2547          */
2548         if (!jit_tls || jit_tls->handler_block_return_address)
2549                 return FALSE;
2550
2551         mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_SIGNAL_SAFE, &data);
2552
2553         if (!data.ji)
2554                 return FALSE;
2555
2556         memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
2557
2558         resume_ip = install_handler_block_guard (data.ji, &data.ctx);
2559         if (resume_ip == NULL)
2560                 return FALSE;
2561
2562         jit_tls->handler_block_return_address = resume_ip;
2563         jit_tls->handler_block = data.ei;
2564
2565         return TRUE;
2566 }
2567
2568 #else
2569 gboolean
2570 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
2571 {
2572         return FALSE;
2573 }
2574
2575 #endif
2576
2577 void
2578 mono_set_cast_details (MonoClass *from, MonoClass *to)
2579 {
2580         MonoJitTlsData *jit_tls = NULL;
2581
2582         if (mini_get_debug_options ()->better_cast_details) {
2583                 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2584                 jit_tls->class_cast_from = from;
2585                 jit_tls->class_cast_to = to;
2586         }
2587 }
2588
2589
2590 /*returns false if the thread is not attached*/
2591 gboolean
2592 mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
2593 {
2594 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
2595         MonoInternalThread *thread = mono_thread_internal_current ();
2596         if (!thread || !thread->jit_data) {
2597                 ctx->valid = FALSE;
2598                 return FALSE;
2599         }
2600
2601         if (sigctx)
2602                 mono_arch_sigctx_to_monoctx (sigctx, &ctx->ctx);
2603         else
2604 #if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE)
2605                 MONO_CONTEXT_GET_CURRENT (ctx->ctx);
2606 #else
2607                 g_error ("Use a null sigctx requires a working mono-context");
2608 #endif
2609
2610         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2611         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2612         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2613         ctx->valid = TRUE;
2614         return TRUE;
2615 #else
2616         g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
2617         return FALSE;
2618 #endif
2619 }
2620
2621 gboolean
2622 mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
2623 {
2624         MonoInternalThread *thread = mono_thread_internal_current ();
2625         if (!thread || !thread->jit_data) {
2626                 ctx->valid = FALSE;
2627                 return FALSE;
2628         }
2629
2630         ctx->ctx = *mctx;
2631         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2632         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2633         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2634         ctx->valid = TRUE;
2635         return TRUE;
2636 }
2637
2638 /*returns false if the thread is not attached*/
2639 gboolean
2640 mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
2641 {
2642         MonoInternalThread *thread = mono_thread_internal_current ();
2643         MONO_ARCH_CONTEXT_DEF
2644
2645         mono_arch_flush_register_windows ();
2646
2647         if (!thread || !thread->jit_data) {
2648                 ctx->valid = FALSE;
2649                 return FALSE;
2650         }
2651 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
2652         MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
2653 #else
2654         MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
2655 #endif
2656                 
2657         ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
2658         ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
2659         ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
2660         ctx->valid = TRUE;
2661         return TRUE;
2662 }
2663
2664 static void
2665 mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
2666 {
2667         void (*restore_context) (MonoContext *);
2668         restore_context = mono_get_restore_context ();
2669
2670         mono_handle_exception (ctx, exc);
2671         restore_context (ctx);
2672 }
2673
2674 /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
2675 void
2676 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
2677 {
2678 #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
2679         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
2680         jit_tls->ex_ctx = *ctx;
2681
2682         mono_arch_setup_async_callback (ctx, async_cb, user_data);
2683 #else
2684         g_error ("This target doesn't support mono_arch_setup_async_callback");
2685 #endif
2686 }
2687
2688 void
2689 mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
2690 {
2691         unhandled_exception_hook = func;
2692         unhandled_exception_hook_data = user_data;
2693 }
2694
2695 void
2696 mono_invoke_unhandled_exception_hook (MonoObject *exc)
2697 {
2698         if (unhandled_exception_hook) {
2699                 unhandled_exception_hook (exc, unhandled_exception_hook_data);
2700         } else {
2701                 MonoObject *other = NULL;
2702                 MonoString *str = mono_object_to_string (exc, &other);
2703                 char *msg = NULL;
2704                 
2705                 if (str)
2706                         msg = mono_string_to_utf8 (str);
2707                 else
2708                         msg = g_strdup ("Nested exception trying to figure out what went wrong");
2709                 mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
2710                 g_free (msg);
2711 #if defined(__APPLE__) && defined(__arm__)
2712                 g_assertion_message ("Terminating runtime due to unhandled exception");
2713 #else
2714                 exit (mono_environment_exitcode_get ());
2715 #endif
2716         }
2717
2718         g_assert_not_reached ();
2719 }