Exemplo n.º 1
0
gboolean
mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only)
{
#if defined(MONO_ARCH_USE_SIGACTION)
	MonoContext mctx;
	ucontext_t *ctx = (ucontext_t*)sigctx;

	/*
	 * Handling the exception in the signal handler is problematic, since the original
	 * signal is disabled, and we could run arbitrary code though the debugger. So
	 * resume into the normal stack and do most work there if possible.
	 */
	MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);

	/* Pass the ctx parameter in TLS */
	mono_arch_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx);

	g_assert (!test_only);
	mctx = jit_tls->ex_ctx;
	mono_setup_async_callback (&mctx, handle_signal_exception, obj);
	mono_monoctx_to_sigctx (&mctx, sigctx);

	return TRUE;
#elif defined (TARGET_WIN32)
	MonoContext mctx;
	MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
	struct sigcontext *ctx = (struct sigcontext *)sigctx;

	mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);

	g_assert (!test_only);
	mctx = jit_tls->ex_ctx;
	mono_setup_async_callback (&mctx, handle_signal_exception, obj);
	mono_monoctx_to_sigctx (&mctx, sigctx);

	return TRUE;
#else
	MonoContext mctx;

	mono_arch_sigctx_to_monoctx (sigctx, &mctx);

	if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj))
		return TRUE;

	mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only);

	mono_arch_monoctx_to_sigctx (&mctx, sigctx);

	return TRUE;
#endif
}
Exemplo n.º 2
0
/*
 * This is the function called from the signal handler
 */
gboolean
mono_arch_handle_exception (void *ctx, gpointer obj)
{
#if defined(MONO_CROSS_COMPILE) || !defined(MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX)
	g_assert_not_reached ();
#elif defined(MONO_ARCH_USE_SIGACTION)
	arm_ucontext *sigctx = ctx;
	/*
	 * Handling the exception in the signal handler is problematic, since the original
	 * signal is disabled, and we could run arbitrary code though the debugger. So
	 * resume into the normal stack and do most work there if possible.
	 */
	MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
	guint64 sp = UCONTEXT_REG_SP (sigctx);

	/* Pass the ctx parameter in TLS */
	mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
	/* The others in registers */
	UCONTEXT_REG_R0 (sigctx) = (gsize)obj;

	/* Allocate a stack frame */
	sp -= 16;
	UCONTEXT_REG_SP (sigctx) = sp;

	UCONTEXT_REG_PC (sigctx) = (gsize)get_handle_signal_exception_addr ();
#ifdef UCONTEXT_REG_CPSR
	if ((gsize)UCONTEXT_REG_PC (sigctx) & 1)
		/* Transition to thumb */
		UCONTEXT_REG_CPSR (sigctx) |= (1 << 5);
	else
		/* Transition to ARM */
		UCONTEXT_REG_CPSR (sigctx) &= ~(1 << 5);
#endif

	return TRUE;
#else
	MonoContext mctx;
	gboolean result;

	mono_arch_sigctx_to_monoctx (ctx, &mctx);

	result = mono_handle_exception (&mctx, obj);
	/* restore the context so that returning from the signal handler will invoke
	 * the catch clause 
	 */
	mono_arch_monoctx_to_sigctx (&mctx, ctx);
	return result;
#endif
}
Exemplo n.º 3
0
gboolean
mono_arch_handle_exception (void *ctx, gpointer obj)
{
#if defined(MONO_ARCH_USE_SIGACTION) && defined(UCONTEXT_REG_Rn)
	/*
	 * Handling the exception in the signal handler is problematic, since the original
	 * signal is disabled, and we could run arbitrary code though the debugger. So
	 * resume into the normal stack and do most work there if possible.
	 */
	MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
	mgreg_t sp;
	void *sigctx = ctx;
	int frame_size;
	void *uc = sigctx;

	/* Pass the ctx parameter in TLS */
	mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
	/* The others in registers */
	UCONTEXT_REG_Rn (sigctx, PPC_FIRST_ARG_REG) = (gsize)obj;

	/* Allocate a stack frame below the red zone */
	/* Similar to mono_arch_handle_altstack_exception () */
	frame_size = 224;
	frame_size += 15;
	frame_size &= ~15;
	sp = (mgreg_t)(UCONTEXT_REG_Rn(uc, 1) & ~15);
	sp = (mgreg_t)(sp - frame_size);
	UCONTEXT_REG_Rn(uc, 1) = (mgreg_t)sp;
	setup_ucontext_return (uc, handle_signal_exception);

	return TRUE;
#else
	MonoContext mctx;
	gboolean result;

	mono_arch_sigctx_to_monoctx (ctx, &mctx);

	result = mono_handle_exception (&mctx, obj);
	/* restore the context so that returning from the signal handler will invoke
	 * the catch clause 
	 */
	mono_arch_monoctx_to_sigctx (&mctx, ctx);
	return result;
#endif
}
Exemplo n.º 4
0
static void
altstack_handle_and_restore (void *sigctx, gpointer obj)
{
	MonoContext mctx;

	mono_arch_sigctx_to_monoctx (sigctx, &mctx);
	mono_handle_exception (&mctx, obj);
	mono_restore_context (&mctx);
}
Exemplo n.º 5
0
/* Special hack to workaround the fact that the
 * when the SEH handler is called the stack is
 * to small to recover.
 *
 * Stack walking part of this method is from mono_handle_exception
 *
 * The idea is simple; 
 *  - walk the stack to free some space (64k)
 *  - set esp to new stack location
 *  - call mono_arch_handle_exception with stack overflow exception
 *  - set esp to SEH handlers stack
 *  - done
 */
static void 
win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx) 
{
	SYSTEM_INFO si;
	DWORD page_size;
	MonoDomain *domain = mono_domain_get ();
	MonoJitInfo rji;
	MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
	MonoLMF *lmf = jit_tls->lmf;		
	MonoContext initial_ctx;
	MonoContext ctx;
	guint32 free_stack = 0;
	StackFrameInfo frame;

	/* convert sigcontext to MonoContext (due to reuse of stack walking helpers */
	mono_arch_sigctx_to_monoctx (sctx, &ctx);
	
	/* get our os page size */
	GetSystemInfo(&si);
	page_size = si.dwPageSize;

	/* Let's walk the stack to recover
	 * the needed stack space (if possible)
	 */
	memset (&rji, 0, sizeof (rji));

	initial_ctx = ctx;
	free_stack = (guint8*)(MONO_CONTEXT_GET_BP (&ctx)) - (guint8*)(MONO_CONTEXT_GET_BP (&initial_ctx));

	/* try to free 64kb from our stack */
	do {
		MonoContext new_ctx;

		mono_arch_find_jit_info (domain, jit_tls, &rji, &ctx, &new_ctx, &lmf, NULL, &frame);
		if (!frame.ji) {
			g_warning ("Exception inside function without unwind info");
			g_assert_not_reached ();
		}

		if (frame.ji != (gpointer)-1) {
			free_stack = (guint8*)(MONO_CONTEXT_GET_BP (&ctx)) - (guint8*)(MONO_CONTEXT_GET_BP (&initial_ctx));
		}

		/* todo: we should call abort if ji is -1 */
		ctx = new_ctx;
	} while (free_stack < 64 * 1024 && frame.ji != (gpointer) -1);

	/* convert into sigcontext to be used in mono_arch_handle_exception */
	mono_arch_monoctx_to_sigctx (&ctx, sctx);

	/* todo: install new stack-guard page */

	/* use the new stack and call mono_arch_handle_exception () */
	restore_stack (sctx);
}
Exemplo n.º 6
0
/*
 * This is the function called from the signal handler
 */
gboolean
mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only)
{
#if defined(MONO_CROSS_COMPILE)
	g_assert_not_reached ();
#elif defined(MONO_ARCH_USE_SIGACTION)
	arm_ucontext *sigctx = ctx;
	/*
	 * Handling the exception in the signal handler is problematic, since the original
	 * signal is disabled, and we could run arbitrary code though the debugger. So
	 * resume into the normal stack and do most work there if possible.
	 */
	MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
	guint64 sp = UCONTEXT_REG_SP (sigctx);

	/* Pass the ctx parameter in TLS */
	mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
	/* The others in registers */
	UCONTEXT_REG_R0 (sigctx) = (gsize)obj;
	UCONTEXT_REG_R1 (sigctx) = test_only;

	/* Allocate a stack frame */
	sp -= 16;
	UCONTEXT_REG_SP (sigctx) = sp;

	UCONTEXT_REG_PC (sigctx) = (gsize)handle_signal_exception;

	return TRUE;
#else
	MonoContext mctx;
	gboolean result;

	mono_arch_sigctx_to_monoctx (ctx, &mctx);

	result = mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only);
	/* restore the context so that returning from the signal handler will invoke
	 * the catch clause 
	 */
	mono_arch_monoctx_to_sigctx (&mctx, ctx);
	return result;
#endif
}
Exemplo n.º 7
0
gboolean
mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only)
{
	MonoContext mctx;

	mono_arch_sigctx_to_monoctx (sigctx, &mctx);

	if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj))
		return TRUE;

	mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only);

	mono_arch_monoctx_to_sigctx (&mctx, sigctx);

	return TRUE;
}
Exemplo n.º 8
0
static void
altstack_handle_and_restore (void *sigctx, gpointer obj, gboolean stack_ovf)
{
	void (*restore_context) (MonoContext *);
	MonoContext mctx;

	restore_context = mono_get_restore_context ();
	mono_arch_sigctx_to_monoctx (sigctx, &mctx);

	if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj)) {
		if (stack_ovf)
			prepare_for_guard_pages (&mctx);
		restore_context (&mctx);
	}

	mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, FALSE);
	if (stack_ovf)
		prepare_for_guard_pages (&mctx);
	restore_context (&mctx);
}
Exemplo n.º 9
0
gboolean
mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only)
{
#if defined(MONO_ARCH_USE_SIGACTION)
	ucontext_t *ctx = (ucontext_t*)sigctx;

	/*
	 * Handling the exception in the signal handler is problematic, since the original
	 * signal is disabled, and we could run arbitrary code though the debugger. So
	 * resume into the normal stack and do most work there if possible.
	 */
	MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
	guint64 sp = UCONTEXT_REG_ESP (ctx);

	/* Pass the ctx parameter in TLS */
	mono_arch_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx);
	/*
	 * Can't pass the obj on the stack, since we are executing on the
	 * same stack. Can't save it into MonoJitTlsData, since it needs GC tracking.
	 * So put it into a register, and branch to a trampoline which
	 * pushes it.
	 */
	g_assert (!test_only);
	UCONTEXT_REG_EAX (ctx) = (gsize)obj;
	UCONTEXT_REG_ECX (ctx) = UCONTEXT_REG_EIP (ctx);
	UCONTEXT_REG_EDX (ctx) = (gsize)handle_signal_exception;

	/* Allocate a stack frame, align it to 16 bytes which is needed on apple */
	sp -= 16;
	sp &= ~15;
	UCONTEXT_REG_ESP (ctx) = sp;

	UCONTEXT_REG_EIP (ctx) = (gsize)signal_exception_trampoline;

	return TRUE;
#elif defined (TARGET_WIN32)
	MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
	struct sigcontext *ctx = (struct sigcontext *)sigctx;
	guint64 sp = ctx->SC_ESP;

	mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);

	/*
	 * Can't pass the obj on the stack, since we are executing on the
	 * same stack. Can't save it into MonoJitTlsData, since it needs GC tracking.
	 * So put it into a register, and branch to a trampoline which
	 * pushes it.
	 */
	g_assert (!test_only);
	ctx->SC_EAX = (gsize)obj;
	ctx->SC_ECX = ctx->SC_EIP;
	ctx->SC_EDX = (gsize)handle_signal_exception;

	/* Allocate a stack frame, align it to 16 bytes which is needed on apple */
	sp -= 16;
	sp &= ~15;
	ctx->SC_ESP = sp;

	ctx->SC_EIP = (gsize)signal_exception_trampoline;

	return TRUE;
#else
	MonoContext mctx;

	mono_arch_sigctx_to_monoctx (sigctx, &mctx);

	if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj))
		return TRUE;

	mono_handle_exception (&mctx, obj, (gpointer)mctx.eip, test_only);

	mono_arch_monoctx_to_sigctx (&mctx, sigctx);

	return TRUE;
#endif
}
Exemplo n.º 10
0
static void
SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
{
	int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
	MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
	GET_CONTEXT;
	
	if (call_chain_depth == 0) {
		mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
	} else {
		MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
		int current_frame_index = 1;
		MonoContext mono_context;
		guchar *ips [call_chain_depth + 1];

		mono_arch_sigctx_to_monoctx (ctx, &mono_context);
		ips [0] = MONO_CONTEXT_GET_IP (&mono_context);
		
		if (jit_tls != NULL) {
			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
#if FULL_STAT_PROFILER_BACKTRACE
			guchar *current_frame;
			guchar *stack_bottom;
			guchar *stack_top;
			
			stack_bottom = jit_tls->end_of_stack;
			stack_top = MONO_CONTEXT_GET_SP (&mono_context);
			current_frame = MONO_CONTEXT_GET_BP (&mono_context);
			
			while ((current_frame_index <= call_chain_depth) &&
					(stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
					((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
				ips [current_frame_index] = CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
				current_frame_index ++;
				stack_top = current_frame;
				current_frame = CURRENT_FRAME_GET_BASE_POINTER (current_frame);
			}
#else
				call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
#endif
			}
			
			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
#if GLIBC_PROFILER_BACKTRACE
				current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
#else
				call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
#endif
			}

			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
				MonoDomain *domain = mono_domain_get ();
				if (domain != NULL) {
					MonoLMF *lmf = NULL;
					MonoJitInfo *ji;
					MonoJitInfo res;
					MonoContext new_mono_context;
					int native_offset;
					ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
							&new_mono_context, NULL, &lmf, &native_offset, NULL);
					while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
						ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context);
						current_frame_index ++;
						mono_context = new_mono_context;
						ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
								&new_mono_context, NULL, &lmf, &native_offset, NULL);
					}
				}
			}
		}
		
		mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
	}

	mono_chain_signal (SIG_HANDLER_PARAMS);
}