Example #1
0
void
mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
{
	MonoContext ctx;
	gboolean rethrow = pc & 1;

	pc &= ~1; /* clear the optional rethrow bit */
	/* adjust eip so that it point into the call instruction */
	pc -= 4;

	/*printf ("stack in throw: %p\n", esp);*/
	MONO_CONTEXT_SET_BP (&ctx, int_regs [ARMREG_FP - 4]);
	MONO_CONTEXT_SET_SP (&ctx, sp);
	MONO_CONTEXT_SET_IP (&ctx, pc);
	memcpy (((guint8*)&ctx.regs) + (ARMREG_R4 * sizeof (mgreg_t)), int_regs, 8 * sizeof (mgreg_t));
	memcpy (&ctx.fregs, fp_regs, sizeof (double) * 16);

	if (mono_object_isinst (exc, mono_defaults.exception_class)) {
		MonoException *mono_ex = (MonoException*)exc;
		if (!rethrow)
			mono_ex->stack_trace = NULL;
	}
	mono_handle_exception (&ctx, exc);
	mono_restore_context (&ctx);
	g_assert_not_reached ();
}
Example #2
0
void
mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow)
{
	MonoError error;
	MonoContext ctx;

	/* adjust eip so that it point into the call instruction */
	eip -= 4;

	setup_context (&ctx);

	/*printf ("stack in throw: %p\n", esp);*/
	MONO_CONTEXT_SET_BP (&ctx, esp);
	MONO_CONTEXT_SET_IP (&ctx, eip);
	memcpy (&ctx.regs, int_regs, sizeof (mgreg_t) * MONO_MAX_IREGS);
	memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_MAX_FREGS);

	if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
		MonoException *mono_ex = (MonoException*)exc;
		if (!rethrow) {
			mono_ex->stack_trace = NULL;
			mono_ex->trace_ips = NULL;
		}
	}
	mono_error_assert_ok (&error);
	mono_handle_exception (&ctx, exc);
	mono_restore_context (&ctx);

	g_assert_not_reached ();
}
void
mono_arm_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gulong *int_regs, gdouble *fp_regs)
{
	static void (*restore_context) (MonoContext *);
	MonoContext ctx;
	gboolean rethrow = eip & 1;

	if (!restore_context)
		restore_context = mono_get_restore_context ();

	eip &= ~1; /* clear the optional rethrow bit */
	/* adjust eip so that it point into the call instruction */
	eip -= 4;

	/*printf ("stack in throw: %p\n", esp);*/
	MONO_CONTEXT_SET_BP (&ctx, int_regs [ARMREG_FP - 4]);
	MONO_CONTEXT_SET_SP (&ctx, esp);
	MONO_CONTEXT_SET_IP (&ctx, eip);
	memcpy (((guint8*)&ctx.regs) + (4 * 4), int_regs, sizeof (gulong) * 8);
	/* memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_SAVED_FREGS); */

	if (mono_object_isinst (exc, mono_defaults.exception_class)) {
		MonoException *mono_ex = (MonoException*)exc;
		if (!rethrow)
			mono_ex->stack_trace = NULL;
	}
	mono_handle_exception (&ctx, exc, (gpointer)(eip + 4), FALSE);
	restore_context (&ctx);
	g_assert_not_reached ();
}
Example #4
0
// FIX ME: This is not complete
void
mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
{
	uintptr_t sp = (uintptr_t) MONO_CONTEXT_GET_SP(ctx);
	sp -= PPC_MINIMAL_STACK_SIZE;
	*(unsigned long *)sp = MONO_CONTEXT_GET_SP(ctx);
	MONO_CONTEXT_SET_BP(ctx, sp);
	MONO_CONTEXT_SET_IP(ctx, (unsigned long) async_cb);
}
Example #5
0
// FIX ME: This is not complete
void
mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
{
	uintptr_t sp = (uintptr_t) MONO_CONTEXT_GET_SP(ctx);
	ctx->regs [PPC_FIRST_ARG_REG] = user_data;
	sp -= PPC_MINIMAL_STACK_SIZE;
	*(unsigned long *)sp = MONO_CONTEXT_GET_SP(ctx);
	MONO_CONTEXT_SET_BP(ctx, sp);
	mono_arch_setup_resume_sighandler_ctx(ctx, (unsigned long) async_cb);
}
Example #6
0
void
mono_arm_resume_unwind (guint32 dummy1, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
{
	MonoContext ctx;

	pc &= ~1; /* clear the optional rethrow bit */
	/* adjust eip so that it point into the call instruction */
	pc -= 4;

	MONO_CONTEXT_SET_BP (&ctx, int_regs [ARMREG_FP - 4]);
	MONO_CONTEXT_SET_SP (&ctx, sp);
	MONO_CONTEXT_SET_IP (&ctx, pc);
	memcpy (((guint8*)&ctx.regs) + (ARMREG_R4 * sizeof (mgreg_t)), int_regs, 8 * sizeof (mgreg_t));

	mono_resume_unwind (&ctx);
}
static void
mono_arm_resume_unwind (guint32 dummy1, unsigned long eip, unsigned long esp, gulong *int_regs, gdouble *fp_regs)
{
	MonoContext ctx;

	eip &= ~1; /* clear the optional rethrow bit */
	/* adjust eip so that it point into the call instruction */
	eip -= 4;

	MONO_CONTEXT_SET_BP (&ctx, int_regs [ARMREG_FP - 4]);
	MONO_CONTEXT_SET_SP (&ctx, esp);
	MONO_CONTEXT_SET_IP (&ctx, eip);
	memcpy (((guint8*)&ctx.regs) + (4 * 4), int_regs, sizeof (gulong) * 8);

	mono_resume_unwind (&ctx);
}
Example #8
0
/*
 * mono_arch_unwind_frame:
 *
 * See exceptions-amd64.c for docs.
 */
gboolean
mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, 
							 MonoJitInfo *ji, MonoContext *ctx, 
							 MonoContext *new_ctx, MonoLMF **lmf,
							 mgreg_t **save_locations,
							 StackFrameInfo *frame)
{
	gpointer ip = MONO_CONTEXT_GET_IP (ctx);
	MonoPPCStackFrame *sframe;

	memset (frame, 0, sizeof (StackFrameInfo));
	frame->ji = ji;

	*new_ctx = *ctx;
	setup_context (new_ctx);

	if (ji != NULL) {
		int i;
		mgreg_t regs [ppc_lr + 1];
		guint8 *cfa;
		guint32 unwind_info_len;
		guint8 *unwind_info;

		if (ji->is_trampoline)
			frame->type = FRAME_TYPE_TRAMPOLINE;
		else
			frame->type = FRAME_TYPE_MANAGED;

		unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);

		sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx);
		MONO_CONTEXT_SET_BP (new_ctx, sframe->sp);
		if (!ji->is_trampoline && jinfo_get_method (ji)->save_lmf) {
			/* sframe->sp points just past the end of the LMF */
			guint8 *lmf_addr = (guint8*)sframe->sp - sizeof (MonoLMF);
			memcpy (&new_ctx->fregs [MONO_PPC_FIRST_SAVED_FREG], lmf_addr + G_STRUCT_OFFSET (MonoLMF, fregs), sizeof (double) * MONO_SAVED_FREGS);
			memcpy (&new_ctx->regs [MONO_PPC_FIRST_SAVED_GREG], lmf_addr + G_STRUCT_OFFSET (MonoLMF, iregs), sizeof (mgreg_t) * MONO_SAVED_GREGS);
			/* the calling IP is in the parent frame */
			sframe = (MonoPPCStackFrame*)sframe->sp;
			/* we substract 4, so that the IP points into the call instruction */
			MONO_CONTEXT_SET_IP (new_ctx, sframe->lr - 4);
		} else {
			regs [ppc_lr] = ctx->sc_ir;
			regs [ppc_sp] = ctx->sc_sp;
			for (i = MONO_PPC_FIRST_SAVED_GREG; i < MONO_MAX_IREGS; ++i)
				regs [i] = ctx->regs [i];

			mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, 
							   (guint8*)ji->code_start + ji->code_size,
							   ip, NULL, regs, ppc_lr + 1,
							   save_locations, MONO_MAX_IREGS, &cfa);

			/* we substract 4, so that the IP points into the call instruction */
			MONO_CONTEXT_SET_IP (new_ctx, regs [ppc_lr] - 4);
			MONO_CONTEXT_SET_BP (new_ctx, cfa);

			for (i = MONO_PPC_FIRST_SAVED_GREG; i < MONO_MAX_IREGS; ++i)
				new_ctx->regs [i] = regs [i];
		}

		return TRUE;
	} else if (*lmf) {
		
		if ((ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL))) {
		} else {
			if (!(*lmf)->method)
				return FALSE;

			/* Trampoline lmf frame */
			frame->method = (*lmf)->method;
		}

		/*sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx);
		MONO_CONTEXT_SET_BP (new_ctx, sframe->sp);
		MONO_CONTEXT_SET_IP (new_ctx, sframe->lr);*/
		MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
		MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
		memcpy (&new_ctx->regs [MONO_PPC_FIRST_SAVED_GREG], (*lmf)->iregs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
		memcpy (&new_ctx->fregs [MONO_PPC_FIRST_SAVED_FREG], (*lmf)->fregs, sizeof (double) * MONO_SAVED_FREGS);

		frame->ji = ji;
		frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;

		/* FIXME: what about trampoline LMF frames?  see exceptions-x86.c */

		*lmf = (*lmf)->previous_lmf;

		return TRUE;
	}

	return FALSE;
}
Example #9
0
/* mono_arch_find_jit_info:
 *
 * This function is used to gather information from @ctx. It returns the 
 * MonoJitInfo of the corresponding function, unwinds one stack frame and
 * stores the resulting context into @new_ctx. It also stores a string 
 * describing the stack location into @trace (if not NULL), and modifies
 * the @lmf if necessary. @native_offset return the IP offset from the 
 * start of the function or -1 if that info is not available.
 */
MonoJitInfo *
mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
			 MonoJitInfo *res, MonoJitInfo *prev_ji,
			 MonoContext *ctx, MonoContext *new_ctx,
			 MonoLMF **lmf, gboolean *managed)
{
	MonoJitInfo *ji;
	gpointer ip = MONO_CONTEXT_GET_IP (ctx);
	gpointer fp = MONO_CONTEXT_GET_BP (ctx);
	guint32 sp;

	/* Avoid costly table lookup during stack overflow */
	if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
		ji = prev_ji;
	else
		ji = mini_jit_info_table_find (domain, ip, NULL);

	if (managed)
		*managed = FALSE;

	memcpy (new_ctx, ctx, sizeof (MonoContext));

	if (ji != NULL) {
		int i;
		gint32 address;
		int offset = 0;

		if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
			/* remove any unused lmf */
			*lmf = (*lmf)->previous_lmf;
		}

		address = (char *)ip - (char *)ji->code_start;

		if (managed)
			if (!ji->method->wrapper_type)
				*managed = TRUE;

		/* My stack frame */
		fp = MONO_CONTEXT_GET_BP (ctx);

		/* Compute the previous stack frame */
		sp = (guint32)(fp) - (short)(*(guint32 *)(ji->code_start));

		/* Sanity check the frame */
		if (!sp || (sp == 0xffffffff)
		    || (sp & 0x07) || (sp < 64*1024)) {
#ifdef DEBUG_EXCEPTIONS
			g_print ("mono_arch_find_jit_info: bad stack sp=%p\n", (void *) sp);
#endif
			return (gpointer)-1;
		}

		if (ji->method->save_lmf && 0) {
			/* only enable this when prologue stops emitting
			 * normal save of s-regs when save_lmf is true.
			 * Will have to sync with prologue code at that point.
			 */
			memcpy (&new_ctx->sc_fpregs,
				(char*)sp - sizeof (float) * MONO_SAVED_FREGS,
				sizeof (float) * MONO_SAVED_FREGS);
			memcpy (&new_ctx->sc_regs,
				(char*)sp - sizeof (float) * MONO_SAVED_FREGS - sizeof (gulong) * MONO_SAVED_GREGS,
				sizeof (gulong) * MONO_SAVED_GREGS);
		} else if (ji->used_regs) {
			guint32 *insn;
			guint32 mask = ji->used_regs;

			/* these all happen before adjustment of fp */
			/* Look for sw ??, ????(sp) */
			insn = ((guint32 *)ji->code_start) + 1;
			while (!*insn || ((*insn & 0xffe00000) == 0xafa00000) || ((*insn & 0xffe00000) == 0xffa00000)) {
				int reg = (*insn >> 16) & 0x1f;
				guint32 addr = (((guint32)fp) + (short)(*insn & 0x0000ffff));

				mask &= ~(1 << reg);
				if ((*insn & 0xffe00000) == 0xafa00000)
					new_ctx->sc_regs [reg] = *(guint32 *)addr;
				else
					new_ctx->sc_regs [reg] = *(guint64 *)addr;
				insn++;
			}
			MONO_CONTEXT_SET_SP (new_ctx, sp);
			MONO_CONTEXT_SET_BP (new_ctx, sp);
			/* assert that we found all registers we were supposed to */
			g_assert (!mask);
		}