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