Ejemplo n.º 1
0
/*
 * mono_save_xdebug_info:
 *
 *   Emit debugging info for METHOD into an assembly file which can be assembled
 * and loaded into gdb to provide debugging info for JITted code.
 * LOCKING: Acquires the loader lock.
 */
void
mono_save_xdebug_info (MonoCompile *cfg)
{
    MonoDebugMethodJitInfo *dmji;

    if (use_gdb_interface) {
        mono_loader_lock ();

        if (!xdebug_syms)
            xdebug_syms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

        /*
         * gdb is not designed to handle 1000s of symbol files (one per method). So we
         * group them into groups of 100.
         */
        if ((xdebug_method_count % 100) == 0)
            mono_xdebug_flush ();

        xdebug_method_count ++;

        dmji = mono_debug_find_method (jinfo_get_method (cfg->jit_info), mono_domain_get ());;
        mono_dwarf_writer_emit_method (xdebug_writer, cfg, jinfo_get_method (cfg->jit_info), NULL, NULL, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji);
        mono_debug_free_method_jit_info (dmji);

#if 0
        /*
         * Emit a symbol for the code by emitting it at the beginning of the text
         * segment, and setting the text segment to have an absolute address.
         * This symbol can be used to set breakpoints in gdb.
         * FIXME: This doesn't work when multiple methods are emitted into the same file.
         */
        sym = get_debug_sym (cfg->jit_info->method, "", xdebug_syms);
        img_writer_emit_section_change (w, ".text", 0);
        if (!xdebug_text_addr) {
            xdebug_text_addr = cfg->jit_info->code_start;
            img_writer_set_section_addr (w, (gssize)xdebug_text_addr);
        }
        img_writer_emit_global_with_size (w, sym, cfg->jit_info->code_size, TRUE);
        img_writer_emit_label (w, sym);
        img_writer_emit_bytes (w, cfg->jit_info->code_start, cfg->jit_info->code_size);
        g_free (sym);
#endif

        mono_loader_unlock ();
    } else {
        if (!xdebug_writer)
            return;

        mono_loader_lock ();
        dmji = mono_debug_find_method (jinfo_get_method (cfg->jit_info), mono_domain_get ());
        mono_dwarf_writer_emit_method (xdebug_writer, cfg, jinfo_get_method (cfg->jit_info), NULL, NULL, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji);
        mono_debug_free_method_jit_info (dmji);
        fflush (xdebug_fp);
        mono_loader_unlock ();
    }

}
Ejemplo n.º 2
0
MonoSecurityFrame*
mono_declsec_create_frame (MonoDomain *domain, MonoJitInfo *jinfo)
{
	MonoSecurityFrame *frame = (MonoSecurityFrame*) mono_object_new (domain, mono_defaults.runtimesecurityframe_class);
	MonoMethodCasInfo *info;
	MonoMethod *method;

	method = jinfo_get_method (jinfo);
	info = mono_jit_info_get_cas_info (jinfo);
	if (info && !info->cas_inited) {
		if (mono_method_has_declsec (method)) {
			/* Cache the stack modifiers into the MonoJitInfo structure to speed up future stack walks */
			mono_declsec_cache_stack_modifiers (jinfo);
		}
		info->cas_inited = TRUE;
	}

	MONO_OBJECT_SETREF (frame, method, mono_method_get_object (domain, method, NULL));
	MONO_OBJECT_SETREF (frame, domain, domain->domain);

	/* stack modifiers on methods have priority on (i.e. replaces) modifiers on class */

	if (info && info->cas_method_assert) {
		mono_declsec_get_method_action (method, SECURITY_ACTION_ASSERT, &frame->assert);
	} else if (info && info->cas_class_assert) {
		mono_declsec_get_class_action (method->klass, SECURITY_ACTION_ASSERT, &frame->assert);
	}

	if (info && info->cas_method_deny) {
		mono_declsec_get_method_action (method, SECURITY_ACTION_DENY, &frame->deny);
	} else if (info && info->cas_class_deny) {
		mono_declsec_get_class_action (method->klass, SECURITY_ACTION_DENY, &frame->deny);
	}

	if (info && info->cas_method_permitonly) {
		mono_declsec_get_method_action (method, SECURITY_ACTION_PERMITONLY, &frame->permitonly);
	} else if (info && info->cas_class_permitonly) {
		mono_declsec_get_class_action (method->klass, SECURITY_ACTION_PERMITONLY, &frame->permitonly);
	}

	/* g_warning ("FRAME %s A(%p,%d) D(%p,%d) PO(%p,%d)", 
	method->name, frame->assert.blob, frame->assert.size, frame->deny.blob, frame->deny.size, frame->permitonly.blob,frame->permitonly.size); */

	return frame;
}
Ejemplo n.º 3
0
/*
 * Fill actions for the specific index (which may either be an encoded class token or
 * an encoded method token) from the metadata image.
 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
 */
void
mono_declsec_cache_stack_modifiers (MonoJitInfo *jinfo)
{
	MonoMethodCasInfo *info = mono_jit_info_get_cas_info (jinfo);
	MonoMethod *method;
	guint32 flags;

	if (!info)
		return;

	method = jinfo_get_method (jinfo);
	/* first find the stack modifiers applied to the method */
	flags = mono_declsec_flags_from_method (method);
	info->cas_method_assert = (flags & MONO_DECLSEC_FLAG_ASSERT) != 0;
	info->cas_method_deny = (flags & MONO_DECLSEC_FLAG_DENY) != 0;
	info->cas_method_permitonly = (flags & MONO_DECLSEC_FLAG_PERMITONLY) != 0;

	/* then find the stack modifiers applied to the class */
	flags = mono_declsec_flags_from_class (method->klass);
	info->cas_class_assert = (flags & MONO_DECLSEC_FLAG_ASSERT) != 0;
	info->cas_class_deny = (flags & MONO_DECLSEC_FLAG_DENY) != 0;
	info->cas_class_permitonly = (flags & MONO_DECLSEC_FLAG_PERMITONLY) != 0;
}
Ejemplo n.º 4
0
static MonoException*
continuation_mark_frame (MonoContinuation *cont)
{
	MonoJitTlsData *jit_tls;
	MonoLMF *lmf;
	MonoContext ctx, new_ctx;
	MonoJitInfo *ji, rji;
	int endloop = FALSE;

	if (cont->domain)
		return mono_get_exception_argument ("cont", "Already marked");

	jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
	lmf = mono_get_lmf();
	cont->domain = mono_domain_get ();
	cont->thread_id = mono_native_thread_id_get ();

	/* get to the frame that called Mark () */
	memset (&rji, 0, sizeof (rji));
	memset (&ctx, 0, sizeof (ctx));
	do {
		ji = mono_find_jit_info (cont->domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
		if (!ji || ji == (gpointer)-1) {
			return mono_get_exception_not_supported ("Invalid stack frame");
		}
		ctx = new_ctx;
		if (endloop)
			break;
		if (!ji->is_trampoline && strcmp (jinfo_get_method (ji)->name, "Mark") == 0)
			endloop = TRUE;
	} while (1);

	cont->top_sp = MONO_CONTEXT_GET_SP (&ctx);
	/*g_print ("method: %s, sp: %p\n", jinfo_get_method (ji)->name, cont->top_sp);*/

	return NULL;
}
Ejemplo n.º 5
0
void
mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, gpointer fault_addr, gboolean stack_ovf)
{
#ifdef MONO_CROSS_COMPILE
	g_assert_not_reached ();
#else
#ifdef MONO_ARCH_USE_SIGACTION
	os_ucontext *uc = (ucontext_t*)sigctx;
	os_ucontext *uc_copy;
	MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (sigctx), NULL);
	gpointer *sp;
	int frame_size;

	if (stack_ovf) {
		const char *method;
		/* we don't do much now, but we can warn the user with a useful message */
		fprintf (stderr, "Stack overflow: IP: %p, SP: %p\n", mono_arch_ip_from_context (sigctx), (gpointer)UCONTEXT_REG_Rn(uc, 1));
		if (ji && !ji->is_trampoline && jinfo_get_method (ji))
			method = mono_method_full_name (jinfo_get_method (ji), TRUE);
		else
			method = "Unmanaged";
		fprintf (stderr, "At %s\n", method);
		abort ();
	}
	if (!ji)
		mono_handle_native_crash ("SIGSEGV", sigctx, siginfo);
	/* setup a call frame on the real stack so that control is returned there
	 * and exception handling can continue.
	 * The frame looks like:
	 *   ucontext struct
	 *   ...
	 * 224 is the size of the red zone
	 */
	frame_size = sizeof (ucontext_t) + sizeof (gpointer) * 16 + 224;
	frame_size += 15;
	frame_size &= ~15;
	sp = (gpointer)(UCONTEXT_REG_Rn(uc, 1) & ~15);
	sp = (gpointer)((char*)sp - frame_size);
	/* may need to adjust pointers in the new struct copy, depending on the OS */
	uc_copy = (ucontext_t*)(sp + 16);
	memcpy (uc_copy, uc, sizeof (os_ucontext));
#if defined(__linux__) && !defined(__mono_ppc64__)
	uc_copy->uc_mcontext.uc_regs = (gpointer)((char*)uc_copy + ((char*)uc->uc_mcontext.uc_regs - (char*)uc));
#endif
	g_assert (mono_arch_ip_from_context (uc) == mono_arch_ip_from_context (uc_copy));
	/* at the return form the signal handler execution starts in altstack_handle_and_restore() */
	UCONTEXT_REG_LNK(uc) = UCONTEXT_REG_NIP(uc);
#ifdef PPC_USES_FUNCTION_DESCRIPTOR
	{
		MonoPPCFunctionDescriptor *handler_ftnptr = (MonoPPCFunctionDescriptor*)altstack_handle_and_restore;

		UCONTEXT_REG_NIP(uc) = (gulong)handler_ftnptr->code;
		UCONTEXT_REG_Rn(uc, 2) = (gulong)handler_ftnptr->toc;
	}
#else
	UCONTEXT_REG_NIP(uc) = (unsigned long)altstack_handle_and_restore;
#if _CALL_ELF == 2
	/* ELF v2 ABI calling convention requires to put the target address into
	* r12 if we use the global entry point of a function. */
	UCONTEXT_REG_Rn(uc, 12) = (unsigned long) altstack_handle_and_restore;
#endif
#endif
	UCONTEXT_REG_Rn(uc, 1) = (unsigned long)sp;
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG) = (unsigned long)(sp + 16);
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG + 1) = 0;
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG + 2) = 0;
#endif

#endif /* !MONO_CROSS_COMPILE */
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/*
 * mini_add_method_trampoline:
 *
 *   Add static rgctx/gsharedvt_in/unbox trampolines to M/COMPILED_METHOD if needed. Return the trampoline address, or
 * COMPILED_METHOD if no trampoline is needed.
 * ORIG_METHOD is the method the caller originally called i.e. an iface method, or NULL.
 */
gpointer
mini_add_method_trampoline (MonoMethod *orig_method, MonoMethod *m, gpointer compiled_method, gboolean add_static_rgctx_tramp, gboolean add_unbox_tramp)
{
	gpointer addr = compiled_method;
	gboolean callee_gsharedvt, callee_array_helper;
	MonoMethod *jmethod = NULL;
	MonoJitInfo *ji = 
		mini_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (compiled_method), NULL);

	// FIXME: This loads information from AOT
	callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);

	callee_array_helper = FALSE;
	if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
		WrapperInfo *info = mono_marshal_get_wrapper_info (m);

		/*
		 * generic array helpers.
		 * Have to replace the wrappers with the original generic instances.
		 */
		if (info && info->subtype == WRAPPER_SUBTYPE_GENERIC_ARRAY_HELPER) {
			callee_array_helper = TRUE;
			m = info->d.generic_array_helper.method;
		}
	} else if (m->wrapper_type == MONO_WRAPPER_UNKNOWN) {
		WrapperInfo *info = mono_marshal_get_wrapper_info (m);

		/* Same for synchronized inner wrappers */
		if (info && info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
			m = info->d.synchronized_inner.method;
		}
	}

	if (!orig_method)
		orig_method = m;

	if (callee_gsharedvt)
		g_assert (m->is_inflated);

	addr = compiled_method;

	if (add_unbox_tramp) {
		/* 
		 * The unbox trampolines call the method directly, so need to add
		 * an rgctx tramp before them.
		 */
		if (mono_aot_only) {
			addr = mono_aot_get_unbox_trampoline (m);
		} else {
			unbox_trampolines ++;
			addr = mono_arch_get_unbox_trampoline (m, addr);
		}
	}

	if (ji)
		jmethod = jinfo_get_method (ji);
	if (callee_gsharedvt && mini_is_gsharedvt_variable_signature (mono_method_signature (jmethod))) {
		MonoGenericSharingContext *gsctx;
		MonoMethodSignature *sig, *gsig;

		/* Here m is a generic instance, while ji->method is the gsharedvt method implementing it */

		/* Call from normal/gshared code to gsharedvt code with variable signature */
		gsctx = mono_jit_info_get_generic_sharing_context (ji);

		sig = mono_method_signature (m);
		gsig = mono_method_signature (jmethod);

		addr = mini_get_gsharedvt_wrapper (TRUE, addr, sig, gsig, gsctx, -1, FALSE);

		//printf ("IN: %s\n", mono_method_full_name (m, TRUE));
	}

	if (add_static_rgctx_tramp && !callee_array_helper)
		addr = mono_create_static_rgctx_trampoline (m, addr);

	return addr;
}