Beispiel #1
0
/*
Convert this MonoError to an exception if it's faulty or return NULL.
The error object is cleant after.
*/
MonoException*
mono_error_convert_to_exception (MonoError *target_error)
{
	ERROR_DECL (error);
	MonoException *ex;

	/* Mempool stored error shouldn't be cleaned up */
	g_assert (!is_boxed ((MonoErrorInternal*)target_error));

	if (mono_error_ok (target_error))
		return NULL;

	ex = mono_error_prepare_exception (target_error, error);
	if (!mono_error_ok (error)) {
		ERROR_DECL (second_chance);
		/*Try to produce the exception for the second error. FIXME maybe we should log about the original one*/
		ex = mono_error_prepare_exception (error, second_chance);

		// We cannot reasonably handle double faults, maybe later.
		g_assert (mono_error_ok (second_chance));
		mono_error_cleanup (error);
	}
	mono_error_cleanup (target_error);
	return ex;
}
Beispiel #2
0
void
mono_error_set_argument_out_of_range (MonoError *error, const char *name)
{
	ERROR_DECL (error_creating_exception);
	mono_error_set_exception_handle (error, mono_new_exception_argument_out_of_range (name, error_creating_exception));
	mono_error_cleanup (error_creating_exception);
}
Beispiel #3
0
void
mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, host_mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow, gboolean preserve_ips)
{
	ERROR_DECL (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 (host_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;
		} else if (preserve_ips) {
			mono_ex->caught_in_unmanaged = TRUE;
		}
	}
	mono_error_assert_ok (error);
	mono_handle_exception (&ctx, exc);
	mono_restore_context (&ctx);

	g_assert_not_reached ();
}
Beispiel #4
0
static void
throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow, gboolean preserve_ips)
{
	ERROR_DECL (error);
	MonoContext ctx;
	static void (*restore_context) (MonoContext *);
	gpointer *window;
	
	if (!restore_context)
		restore_context = mono_get_restore_context ();

	window = MONO_SPARC_WINDOW_ADDR (sp);
	ctx.sp = (gpointer*)sp;
	ctx.ip = ip;
	ctx.fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (sp) [sparc_i6 - 16]);

	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;
		} else (preserve_ips) {
			mono_ex->caught_in_unmanaged = NULL;
		}
	}
Beispiel #5
0
/* Used by mono_error_prepare_exception - it sets its own error on mono_string_new_checked failure. */
static MonoStringHandle
string_new_cleanup (MonoDomain *domain, const char *text)
{
	ERROR_DECL (ignored_err);
	MonoStringHandle result = mono_string_new_handle (domain, text, ignored_err);
	mono_error_cleanup (ignored_err);
	return result;
}
Beispiel #6
0
/**
 * mono_get_exception_argument_internal:
 * \param type the actual type
 * \param arg the name of the argument that is invalid or null, etc.
 * \param msg optional message
 * \returns a new instance of the \c System.ArgumentException or derived
 */
static MonoException*
mono_get_exception_argument_internal (const char *type, const char *arg, const char *msg)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MonoExceptionHandle ex = mono_exception_new_argument_internal (type, arg, msg, error);
	mono_error_cleanup (error);
	HANDLE_FUNCTION_RETURN_OBJ (ex);
}
Beispiel #7
0
/**
 * mono_get_exception_file_not_found:
 * \param fname the name of the file not found.
 * \returns a new instance of the \c System.IO.FileNotFoundException
 */
MonoException *
mono_get_exception_file_not_found (MonoString *fname_raw)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MONO_HANDLE_DCL (MonoString, fname);
	MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname, error);
	mono_error_assert_ok (error);
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #8
0
/**
 * mono_exception_from_name_domain:
 * \param domain Domain where the return object will be created.
 * \param image the Mono image where to look for the class
 * \param name_space the namespace for the class
 * \param name class name
 *
 * Creates an exception object of the given namespace/name class on
 * the given domain.
 *
 * \returns the initialized exception instance.
 */
MonoException *
mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, 
				 const char* name_space, const char *name)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MonoExceptionHandle ret = mono_exception_new_by_name_domain (domain, image, name_space, name, error);
	mono_error_assert_ok (error);
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #9
0
/**
 * mono_exception_from_token_two_strings:
 *
 *   Same as mono_exception_from_name_two_strings, but lookup the exception class using
 * IMAGE and TOKEN.
 */
MonoException *
mono_exception_from_token_two_strings (MonoImage *image, guint32 token, MonoString *arg1_raw, MonoString *arg2_raw)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MONO_HANDLE_DCL (MonoString, arg1);
	MONO_HANDLE_DCL (MonoString, arg2);
	MonoExceptionHandle ret = mono_exception_from_token_two_strings_checked (image, token, arg1, arg2, error);
	mono_error_cleanup (error);
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #10
0
/**
 * mono_exception_from_name_two_strings:
 * \param image the Mono image where to look for the class
 * \param name_space the namespace for the class
 * \param name class name
 * \param a1 first string argument to pass
 * \param a2 second string argument to pass
 *
 * Creates an exception from a constructor that takes two string
 * arguments.
 *
 * \returns the initialized exception instance.
 */
MonoException *
mono_exception_from_name_two_strings (MonoImage *image, const char *name_space,
				      const char *name, MonoString *a1_raw, MonoString *a2_raw)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MONO_HANDLE_DCL (MonoString, a1);
	MONO_HANDLE_DCL (MonoString, a2);
	MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (image, name_space, name, a1, a2, error);
	mono_error_cleanup (error);
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #11
0
static MonoClass *test_mono_class_from_name (MonoImage *image,
					     const char *name_space,
					     const char *name)
{
	ERROR_DECL (error);
	MonoClass *klass;

	klass = mono_class_from_name_checked (image, name_space, name, error);
	mono_error_cleanup (error); /* FIXME Don't swallow the error */

	return klass;
}
Beispiel #12
0
/**
 * mono_get_exception_runtime_wrapped:
 */
MonoException *
mono_get_exception_runtime_wrapped (MonoObject *wrapped_exception_raw)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MONO_HANDLE_DCL (MonoObject, wrapped_exception);
	MonoExceptionHandle ret = mono_get_exception_runtime_wrapped_handle (wrapped_exception, error);
	if (!is_ok (error)) {
		mono_error_cleanup (error);
		ret = MONO_HANDLE_CAST (MonoException, mono_new_null ());
	}
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #13
0
/**
 * mono_exception_from_name_msg:
 * \param image the Mono image where to look for the class
 * \param name_space the namespace for the class
 * \param name class name
 * \param msg the message to embed inside the exception
 *
 * Creates an exception and initializes its message field.
 *
 * \returns the initialized exception instance.
 */
MonoException *
mono_exception_from_name_msg (MonoImage *image, const char *name_space,
			      const char *name, const char *msg)
{
	HANDLE_FUNCTION_ENTER ();
	MonoExceptionHandle ex;
	MONO_ENTER_GC_UNSAFE;
	ERROR_DECL (error);
	ex = mono_exception_new_by_name_msg (image, name_space, name, msg, error);
	mono_error_cleanup (error);
	MONO_EXIT_GC_UNSAFE;
	HANDLE_FUNCTION_RETURN_OBJ (ex);
}
Beispiel #14
0
/**
 * mono_get_exception_type_initialization:
 * \param type_name the name of the type that failed to initialize.
 * \param inner the inner exception.
 * \returns a new instance of the \c System.TypeInitializationException
 */
MonoException *
mono_get_exception_type_initialization (const gchar *type_name, MonoException* inner_raw)
{
	HANDLE_FUNCTION_ENTER ();
	MONO_HANDLE_DCL (MonoException, inner);
	ERROR_DECL (error);
	MonoExceptionHandle ret = mono_get_exception_type_initialization_handle (type_name, inner, error);
	if (!is_ok (error)) {
		ret = MONO_HANDLE_CAST (MonoException, mono_new_null ());
		mono_error_cleanup (error);
	}
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #15
0
/**
 * mono_get_exception_reflection_type_load:
 * \param types an array of types that were defined in the moduled loaded.
 * \param exceptions an array of exceptions that were thrown during the type loading.
 * \returns a new instance of the \c System.Reflection.ReflectionTypeLoadException
 */
MonoException *
mono_get_exception_reflection_type_load (MonoArray *types_raw, MonoArray *exceptions_raw)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MONO_HANDLE_DCL (MonoArray, types);
	MONO_HANDLE_DCL (MonoArray, exceptions);
	MonoExceptionHandle ret = mono_get_exception_reflection_type_load_checked (types, exceptions, error);
	if (!is_ok (error))
		ret = MONO_HANDLE_CAST (MonoException, mono_new_null ());
	mono_error_cleanup (error);
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #16
0
/**
 * mono_get_exception_file_not_found2:
 * \param msg an informative message for the user.
 * \param fname the name of the file not found.
 * \returns a new instance of the \c System.IO.FileNotFoundException
 */
MonoException *
mono_get_exception_file_not_found2 (const char *msg, MonoString *fname_raw)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MONO_HANDLE_DCL (MonoString, fname);
	MonoStringHandle s = NULL_HANDLE_STRING;
	if (msg) {
		s = mono_string_new_handle (mono_domain_get (), msg, error);
		mono_error_assert_ok (error);
	}
	MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname, error);
	mono_error_assert_ok (error);
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #17
0
/**
 * mono_get_exception_missing_member:
 * \param exception_type the specific exception type for the specific member type, i.e. field or method
 * \param class_name the class where the lookup was performed.
 * \param member_name the name of the missing method.
 * \returns a new instance of the \c exception_type (MissingFieldException or MissingMethodException)
 */
static MonoException*
mono_get_exception_missing_member (const char *exception_type, const char *class_name, const char *member_name)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MonoDomain * const domain = mono_domain_get ();
	MonoStringHandle s1 = mono_string_new_handle (domain, class_name, error);
	mono_error_assert_ok (error);
	MonoStringHandle s2 = mono_string_new_handle (domain, member_name, error);
	mono_error_assert_ok (error);

	MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System",
									   exception_type, s1, s2, error);
	mono_error_assert_ok (error);
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #18
0
static void
mono_init_merp (const intptr_t crashed_pid, const char *signal, MonoStackHash *hashes, MERPStruct *merp, const char *version)
{
	g_assert (mono_merp_enabled ());

	// If these aren't set, icall wasn't made
	// don't do merp? / don't set the variable to use merp;
	g_assert (config.appBundleID);
	g_assert (config.appVersion);
	merp->bundleIDArg = config.appSignature;
	merp->versionArg = config.appVersion;

	merp->archArg = get_merp_arch ();
	merp->exceptionArg = parse_exception_type (signal);

	merp->serviceNameArg = config.appBundleID;

	// FIXME: Not really a posix way to associated a process with a single executable
	// path? Linux gets bogged down in /proc
	merp->servicePathArg = NULL;
	if (crashed_pid) {
		size_t servicePathSize = sizeof (gchar) * 1200;
		merp->servicePathArg = g_malloc0 (servicePathSize);
		int result = proc_pidpath (crashed_pid, (void *) merp->servicePathArg, 1200);
		if (result <= 0) {
			g_free ((void *) merp->servicePathArg);
			merp->servicePathArg = NULL;
		}
	}

	merp->moduleName = "Mono Exception";
	merp->moduleVersion = version;

	merp->moduleOffset = 0;

	ERROR_DECL (error);
	merp->uiLidArg = ves_icall_System_Threading_Thread_current_lcid (error);
	mono_error_assert_ok (error);

	merp->osVersion = os_version_string ();

	// FIXME: THis is apple-only for now
	merp->systemManufacturer = "apple";
	get_apple_model ((char *) merp->systemModel, sizeof (merp->systemModel));

	merp->hashes = *hashes;
}
Beispiel #19
0
MonoArray*
ves_icall_System_Security_Principal_WindowsIdentity_GetRoles (gpointer token)
{
	ERROR_DECL (error);
	MonoArray *array = NULL;
	MonoDomain *domain = mono_domain_get ();

	/* POSIX-compliant systems should use IsMemberOfGroupId or IsMemberOfGroupName */
	g_warning ("WindowsIdentity._GetRoles should never be called on POSIX");

	if (!array) {
		/* return empty array of string, i.e. string [0] */
		array = mono_array_new_checked (domain, mono_get_string_class (), 0, error);
		mono_error_set_pending_exception (error);
	}
	return array;
}
Beispiel #20
0
/**
 * mono_exception_from_token:
 * \param image the Mono image where to look for the class
 * \param token The type token of the class
 *
 * Creates an exception of the type given by \p token.
 *
 * \returns the initialized exception instance.
 */
MonoException *
mono_exception_from_token (MonoImage *image, guint32 token)
{
	HANDLE_FUNCTION_ENTER ();
	ERROR_DECL (error);
	MonoClass *klass;

	klass = mono_class_get_checked (image, token, error);
	mono_error_assert_ok (error);

	MonoObjectHandle o = mono_object_new_handle (mono_domain_get (), klass, error);
	mono_error_assert_ok (error);

	mono_runtime_object_init_handle (o, error);
	mono_error_assert_ok (error);

	HANDLE_FUNCTION_RETURN_OBJ (MONO_HANDLE_CAST (MonoException, o));
}
Beispiel #21
0
/**
 * mono_get_exception_type_load:
 * \param class_name the name of the class that could not be loaded
 * \param assembly_name the assembly where the class was looked up.
 * \returns a new instance of the \c System.TypeLoadException
 */
MonoException *
mono_get_exception_type_load (MonoString *class_name_raw, char *assembly_name)
{
	ERROR_DECL (error);
	HANDLE_FUNCTION_ENTER ();
	MONO_HANDLE_DCL (MonoString, class_name);
	MonoStringHandle s = NULL_HANDLE_STRING;
	MonoDomain * const domain = mono_domain_get ();
	if (assembly_name) {
		s = mono_string_new_handle (domain, assembly_name, error);
		mono_error_assert_ok (error);
	} else
		s = mono_string_empty_handle (domain);

	MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System",
								   "TypeLoadException", class_name, s, error);
	mono_error_assert_ok (error);
	HANDLE_FUNCTION_RETURN_OBJ (ret);
}
Beispiel #22
0
/*
 * Context propagation is required when:
 * (a) the security manager is active (1.x and later)
 * (b) other contexts needs to be propagated (2.x and later)
 *
 * returns NULL if no context propagation is required, else the returns the
 * MonoMethod to call to Capture the ExecutionContext.
 */
MonoMethod*
mono_get_context_capture_method (void)
{
	static MonoMethod *method = NULL;

	if (mono_image_get_assembly (mono_defaults.corlib)->aname.major < 2)
		return NULL;

	/* older corlib revisions won't have the class (nor the method) */
	MonoClass *execution_context = mono_class_try_get_execution_context_class ();
	if (execution_context && !method) {
		ERROR_DECL (error);
		mono_class_init_internal (execution_context);
		method = mono_class_get_method_from_name_checked (execution_context, "Capture", 0, 0, error);
		mono_error_assert_ok (error);
	}

	return method;
}
Beispiel #23
0
static void
throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow, gboolean preserve_ips)
{
	ERROR_DECL (error);
	MonoContext ctx;

#ifdef DEBUG_EXCEPTIONS
	g_print ("throw_exception: exc=%p eip=%p esp=%p rethrow=%d\n",
		 exc, (void *)eip, (void *) esp, rethrow);
#endif

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

	memset (&ctx, 0, sizeof (MonoContext));

	/*g_print  ("stack in throw: %p\n", esp);*/
	memcpy (&ctx.sc_regs, (void *)(esp + MIPS_STACK_PARAM_OFFSET),
		sizeof (gulong) * MONO_SAVED_GREGS);
	memset (&ctx.sc_fpregs, 0, sizeof (mips_freg) * MONO_SAVED_FREGS);
	MONO_CONTEXT_SET_IP (&ctx, eip);

	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;
		} if (preserve_ips) {
			mono_ex->caught_in_unmanaged = TRUE;
		}
	}
	mono_error_assert_ok (error);
	mono_handle_exception (&ctx, exc);
#ifdef DEBUG_EXCEPTIONS
	g_print ("throw_exception: restore to pc=%p sp=%p fp=%p ctx=%p\n",
		 (void *) ctx.sc_pc, (void *) ctx.sc_regs[mips_sp],
		 (void *) ctx.sc_regs[mips_fp], &ctx);
#endif
	mono_restore_context (&ctx);

	g_assert_not_reached ();
}
Beispiel #24
0
/*
 * mono_x86_throw_exception:
 *
 *   C function called from the throw trampolines.
 */
void
mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, 
						  mgreg_t eip, gboolean rethrow)
{
	ERROR_DECL (error);
	MonoContext ctx;

	ctx.esp = regs [X86_ESP];
	ctx.eip = eip;
	ctx.ebp = regs [X86_EBP];
	ctx.edi = regs [X86_EDI];
	ctx.esi = regs [X86_ESI];
	ctx.ebx = regs [X86_EBX];
	ctx.edx = regs [X86_EDX];
	ctx.ecx = regs [X86_ECX];
	ctx.eax = regs [X86_EAX];

#ifdef __APPLE__
	/* The OSX ABI specifies 16 byte alignment at call sites */
	g_assert ((ctx.esp % MONO_ARCH_FRAME_ALIGNMENT) == 0);
#endif

	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);

	/* adjust eip so that it point into the call instruction */
	ctx.eip -= 1;

	mono_handle_exception (&ctx, exc);

	mono_restore_context (&ctx);

	g_assert_not_reached ();
}
Beispiel #25
0
void
mono_invoke_unhandled_exception_hook (MonoObject *exc)
{
	if (unhandled_exception_hook) {
		unhandled_exception_hook (exc, unhandled_exception_hook_data);
	} else {
		ERROR_DECL (inner_error);
		MonoObject *other = NULL;
		MonoString *str = mono_object_try_to_string (exc, &other, inner_error);
		char *msg = NULL;
		
		if (str && is_ok (inner_error)) {
			msg = mono_string_to_utf8_checked_internal (str, inner_error);
			if (!is_ok (inner_error)) {
				msg = g_strdup_printf ("Nested exception while formatting original exception");
				mono_error_cleanup (inner_error);
			}
		} else if (other) {
			char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
			char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);

			msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
				original_backtrace, nested_backtrace);

			g_free (original_backtrace);
			g_free (nested_backtrace);
		} else {
			msg = g_strdup ("Nested exception trying to figure out what went wrong");
		}
		mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
		g_free (msg);
#if defined(HOST_IOS)
		g_assertion_message ("Terminating runtime due to unhandled exception");
#else
		exit (mono_environment_exitcode_get ());
#endif
	}

	g_assert_not_reached ();
}
Beispiel #26
0
__int32 STDMETHODCALLTYPE _CorExeMain(void)
{
	ERROR_DECL (error);
	MonoDomain* domain;
	MonoAssembly* assembly;
	MonoImage* image;
	MonoMethod* method;
	guint32 entry;
	gchar* file_name;
	gchar* corlib_version_error;
	int argc;
	gunichar2** argvw;
	gchar** argv;
	int i;

	file_name = mono_get_module_file_name (NULL);
	init_from_coree = TRUE;
	domain = mono_runtime_load (file_name, NULL);

	corlib_version_error = (gchar*) mono_check_corlib_version ();
	if (corlib_version_error) {
		g_free (corlib_version_error);
		g_free (file_name);
		MessageBox (NULL, L"Corlib not in sync with this runtime.", NULL, MB_ICONERROR);
		mono_runtime_quit ();
		ExitProcess (1);
	}

	MonoAssemblyOpenRequest req;
	mono_assembly_request_prepare (&req.request, sizeof (req), MONO_ASMCTX_DEFAULT);
	assembly = mono_assembly_request_open (file_name, &req, NULL);
	mono_close_exe_image ();
	if (!assembly) {
		g_free (file_name);
		MessageBox (NULL, L"Cannot open assembly.", NULL, MB_ICONERROR);
		mono_runtime_quit ();
		ExitProcess (1);
	}

	image = assembly->image;
	entry = mono_image_get_entry_point (image);
	if (!entry) {
		g_free (file_name);
		MessageBox (NULL, L"Assembly doesn't have an entry point.", NULL, MB_ICONERROR);
		mono_runtime_quit ();
		ExitProcess (1);
	}

	method = mono_get_method_checked (image, entry, NULL, NULL, error);
	if (method == NULL) {
		g_free (file_name);
		mono_error_cleanup (error); /* FIXME don't swallow the error */
		MessageBox (NULL, L"The entry point method could not be loaded.", NULL, MB_ICONERROR);
		mono_runtime_quit ();
		ExitProcess (1);
	}

	argvw = CommandLineToArgvW (GetCommandLine (), &argc);
	argv = g_new0 (gchar*, argc);
	argv [0] = file_name;
	for (i = 1; i < argc; ++i)
		argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
	LocalFree (argvw);

	mono_runtime_run_main_checked (method, argc, argv, error);
	mono_error_raise_exception_deprecated (error); /* OK, triggers unhandled exn handler */
	mono_thread_manage ();

	mono_runtime_quit ();

	/* return does not terminate the process. */
	ExitProcess (mono_environment_exitcode_get ());
}
Beispiel #27
0
/*
 * mono_debug_add_vg_method:
 *
 *  Register symbol information for the method with valgrind
 */
static void 
mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit)
{
#ifdef VALGRIND_ADD_LINE_INFO
	ERROR_DECL (error);
	MonoMethodHeader *header;
	MonoDebugMethodInfo *minfo;
	int i;
	char *filename = NULL;
	guint32 address, line_number;
	const char *full_name;
	guint32 *addresses;
	guint32 *lines;

	if (!RUNNING_ON_VALGRIND)
		return;

	header = mono_method_get_header_checked (method, error);
	mono_error_assert_ok (error); /* FIXME don't swallow the error */

	full_name = mono_method_full_name (method, TRUE);

	addresses = g_new0 (guint32, header->code_size + 1);
	lines = g_new0 (guint32, header->code_size + 1);

	/* 
	 * Very simple code to convert the addr->offset mappings that mono has
	 * into [addr-addr] ->line number mappings.
	 */

	minfo = mono_debug_lookup_method (method);
	if (minfo) {
		/* Create offset->line number mapping */
		for (i = 0; i < header->code_size; ++i) {
			MonoDebugSourceLocation *location;

			location = mono_debug_method_lookup_location (minfo, i);
			if (!location)
				continue;

			lines [i] = location.row;
			if (!filename)
				filename = location.source_file;

			mono_debug_free_source_location (location);
		}
	}

	/* Create address->offset mapping */
	for (i = 0; i < jit->num_line_numbers; ++i) {
		MonoDebugLineNumberEntry *lne = jit->line_numbers [i];

		g_assert (lne->offset <= header->code_size);

		if ((addresses [lne->offset] == 0) || (lne->address < addresses [lne->offset]))
			addresses [lne->offset] = lne->address;
	}
	/* Fill out missing addresses */
	address = 0;
	for (i = 0; i < header->code_size; ++i) {
		if (addresses [i] == 0)
			addresses [i] = address;
		else
			address = addresses [i];
	}
	
	address = 0;
	line_number = 0;
	i = 0;
	while (i < header->code_size) {
		if (lines [i] == line_number)
			i ++;
		else {
			if (line_number > 0) {
				//g_assert (addresses [i] - 1 >= address);
				
				if (addresses [i] - 1 >= address) {
					VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + addresses [i] - 1, filename, line_number);
					//printf ("[%d-%d] -> %d.\n", address, addresses [i] - 1, line_number);
				}
			}
			address = addresses [i];
			line_number = lines [i];
		}
	}

	if (line_number > 0) {
		VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + jit->code_size - 1, filename, line_number);
		//printf ("[%d-%d] -> %d.\n", address, jit->code_size - 1, line_number);
	}

	VALGRIND_ADD_SYMBOL (jit->code_start, jit->code_size, full_name);

	g_free (addresses);
	g_free (lines);
	mono_metadata_free_mh (header);
#endif /* VALGRIND_ADD_LINE_INFO */
}
Beispiel #28
0
/* 
 * actually, we might want to queue the finalize requests in a separate thread,
 * but we need to be careful about the execution domain of the thread...
 */
void
mono_gc_run_finalize (void *obj, void *data)
{
	ERROR_DECL (error);
	MonoObject *exc = NULL;
	MonoObject *o;
#ifndef HAVE_SGEN_GC
	MonoObject *o2;
#endif
	MonoMethod* finalizer = NULL;
	MonoDomain *caller_domain = mono_domain_get ();
	MonoDomain *domain;

	// This function is called from the innards of the GC, so our best alternative for now is to do polling here
	mono_threads_safepoint ();

	o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data));

	const char *o_ns = m_class_get_name_space (mono_object_class (o));
	const char *o_name = m_class_get_name (mono_object_class (o));

	if (mono_do_not_finalize) {
		if (!mono_do_not_finalize_class_names)
			return;

		size_t namespace_len = strlen (o_ns);
		for (int i = 0; mono_do_not_finalize_class_names [i]; ++i) {
			const char *name = mono_do_not_finalize_class_names [i];
			if (strncmp (name, o_ns, namespace_len))
				break;
			if (name [namespace_len] != '.')
				break;
			if (strcmp (name + namespace_len + 1, o_name))
				break;
			return;
		}
	}

	if (mono_log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_DEBUG, "<%s at %p> Starting finalizer checks.", o_name, o);

	if (suspend_finalizers)
		return;

	domain = o->vtable->domain;

#ifndef HAVE_SGEN_GC
	mono_domain_finalizers_lock (domain);

	o2 = (MonoObject *)g_hash_table_lookup (domain->finalizable_objects_hash, o);

	mono_domain_finalizers_unlock (domain);

	if (!o2)
		/* Already finalized somehow */
		return;
#endif

	/* make sure the finalizer is not called again if the object is resurrected */
	object_register_finalizer ((MonoObject *)obj, NULL);

	if (mono_log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Registered finalizer as processed.", o_name, o);

	if (o->vtable->klass == mono_defaults.internal_thread_class) {
		MonoInternalThread *t = (MonoInternalThread*)o;

		if (mono_gc_is_finalizer_internal_thread (t))
			/* Avoid finalizing ourselves */
			return;
	}

	if (m_class_get_image (mono_object_class (o)) == mono_defaults.corlib && !strcmp (o_name, "DynamicMethod") && finalizing_root_domain) {
		/*
		 * These can't be finalized during unloading/shutdown, since that would
		 * free the native code which can still be referenced by other
		 * finalizers.
		 * FIXME: This is not perfect, objects dying at the same time as 
		 * dynamic methods can still reference them even when !shutdown.
		 */
		return;
	}

	if (mono_runtime_get_no_exec ())
		return;

	/* speedup later... and use a timeout */
	/* g_print ("Finalize run on %p %s.%s\n", o, mono_object_class (o)->name_space, mono_object_class (o)->name); */

	/* Use _internal here, since this thread can enter a doomed appdomain */
	mono_domain_set_internal (mono_object_domain (o));

	/* delegates that have a native function pointer allocated are
	 * registered for finalization, but they don't have a Finalize
	 * method, because in most cases it's not needed and it's just a waste.
	 */
	if (m_class_is_delegate (mono_object_class (o))) {
		MonoDelegate* del = (MonoDelegate*)o;
		if (del->delegate_trampoline)
			mono_delegate_free_ftnptr ((MonoDelegate*)o);
		mono_domain_set_internal (caller_domain);
		return;
	}

	finalizer = mono_class_get_finalizer (o->vtable->klass);

	/* If object has a CCW but has no finalizer, it was only
	 * registered for finalization in order to free the CCW.
	 * Else it needs the regular finalizer run.
	 * FIXME: what to do about ressurection and suppression
	 * of finalizer on object with CCW.
	 */
	if (mono_marshal_free_ccw (o) && !finalizer) {
		mono_domain_set_internal (caller_domain);
		return;
	}

	/* 
	 * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (),
	 * create and precompile a wrapper which calls the finalize method using
	 * a CALLVIRT.
	 */
	if (mono_log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Compiling finalizer.", o_name, o);

#ifndef HOST_WASM
	if (!domain->finalize_runtime_invoke) {
		MonoMethod *finalize_method = mono_class_get_method_from_name_checked (mono_defaults.object_class, "Finalize", 0, 0, error);
		mono_error_assert_ok (error);
		MonoMethod *invoke = mono_marshal_get_runtime_invoke (finalize_method, TRUE);

		domain->finalize_runtime_invoke = mono_compile_method_checked (invoke, error);
		mono_error_assert_ok (error); /* expect this not to fail */
	}

	RuntimeInvokeFunction runtime_invoke = (RuntimeInvokeFunction)domain->finalize_runtime_invoke;
#endif

	mono_runtime_class_init_full (o->vtable, error);
	goto_if_nok (error, unhandled_error);

	if (G_UNLIKELY (MONO_GC_FINALIZE_INVOKE_ENABLED ())) {
		MONO_GC_FINALIZE_INVOKE ((unsigned long)o, mono_object_get_size_internal (o),
				o_ns, o_name);
	}

	if (mono_log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o_name, o);

	MONO_PROFILER_RAISE (gc_finalizing_object, (o));

#ifdef HOST_WASM
	if (finalizer) { // null finalizers work fine when using the vcall invoke as Object has an empty one
		gpointer params [1];
		params [0] = NULL;
		mono_runtime_try_invoke (finalizer, o, params, &exc, error);
	}
#else
	runtime_invoke (o, NULL, &exc, NULL);
#endif

	MONO_PROFILER_RAISE (gc_finalized_object, (o));

	if (mono_log_finalizers)
		g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o_name, o);

unhandled_error:
	if (!is_ok (error))
		exc = (MonoObject*)mono_error_convert_to_exception (error);
	if (exc)
		mono_thread_internal_unhandled_exception (exc);

	mono_domain_set_internal (caller_domain);
}
Beispiel #29
0
static int
dump_verify_info (MonoImage *image, int flags, gboolean valid_only)
{
	GSList *errors, *tmp;
	int count = 0, verifiable = 0;
	const char* desc [] = {
		"Ok", "Error", "Warning", NULL, "CLS", NULL, NULL, NULL, "Not Verifiable"
	};

	if (verify_code) { /* verify code */
		int i;
		MonoTableInfo *m = &image->tables [MONO_TABLE_METHOD];

		for (i = 0; i < m->rows; ++i) {
			MonoMethod *method;
			ERROR_DECL (error);

			method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i+1), NULL, NULL, error);
			if (!method) {
				g_print ("Warning: Cannot lookup method with token 0x%08x due to %s\n", i + 1, mono_error_get_message (error));
				mono_error_cleanup (error);
				continue;
			}
			errors = mono_method_verify (method, flags);
			if (errors) {
				MonoClass *klass = mono_method_get_class (method);
				char *name = mono_type_full_name (m_class_get_byval_arg (klass));
				if (mono_method_signature_internal (method) == NULL) {
					g_print ("In method: %s::%s(ERROR)\n", name, mono_method_get_name (method));
				} else {
					char *sig;
					sig = mono_signature_get_desc (mono_method_signature_internal (method), FALSE);	
					g_print ("In method: %s::%s(%s)\n", name, mono_method_get_name (method), sig);
					g_free (sig);
				}
				g_free (name);
			}

			for (tmp = errors; tmp; tmp = tmp->next) {
				MonoVerifyInfo *info = (MonoVerifyInfo *)tmp->data;
				if (info->status == MONO_VERIFY_NOT_VERIFIABLE && valid_only)
					continue;

				g_print ("%s: %s\n", desc [info->status], info->message);
				if (info->status == MONO_VERIFY_ERROR) {
					count++;
					verifiable = 3;
				}
				if(info->status == MONO_VERIFY_NOT_VERIFIABLE) {
					if (verifiable < 2)
						verifiable = 2;	
				}
			}
			mono_free_verify_list (errors);
		}
	}

	if (count)
		g_print ("Error count: %d\n", count);
	return verifiable;
}
Beispiel #30
0
static int
verify_image_file (const char *fname)
{
	ERROR_DECL (error);

	MonoImage *image;
	MonoTableInfo *table;
	MonoAssembly *assembly;
	MonoImageOpenStatus status;
	int i, count = 0;

	if (!strstr (fname, "mscorlib.dll")) {
		image = mono_image_open_raw (fname, &status);
		if (!image) {
			printf ("Could not open %s\n", fname);
			return 1;
		}

		if (!mono_verifier_verify_pe_data (image, error))
			goto invalid_image;

		if (!mono_image_load_pe_data (image)) {
			printf ("Could not load pe data for assembly %s\n", fname);
			return 1;
		}

		if (!mono_verifier_verify_cli_data (image, error))
			goto invalid_image;

		if (!mono_image_load_cli_data (image)) {
			printf ("Could not load cli data for assembly %s\n", fname);
			return 1;
		}

		if (!mono_verifier_verify_table_data (image, error))
			goto invalid_image;

		mono_image_load_names (image);

		/*fake an assembly for class loading to work*/
		assembly = g_new0 (MonoAssembly, 1);
		assembly->in_gac = FALSE;
		assembly->image = image;
		image->assembly = assembly;
		mono_assembly_fill_assembly_name (image, &assembly->aname);

		/*Finish initializing the runtime*/
		mono_install_assembly_load_hook (pedump_assembly_load_hook, NULL);
		mono_install_assembly_search_hook (pedump_assembly_search_hook, NULL);

		mono_init_version ("pedump", image->version);

		mono_install_assembly_preload_hook (pedump_preload, GUINT_TO_POINTER (FALSE));

		mono_icall_init ();
		mono_marshal_init ();
	} else {
		/*Finish initializing the runtime*/
		mono_install_assembly_load_hook (pedump_assembly_load_hook, NULL);
		mono_install_assembly_search_hook (pedump_assembly_search_hook, NULL);

		mono_init_version ("pedump", NULL);

		mono_install_assembly_preload_hook (pedump_preload, GUINT_TO_POINTER (FALSE));

		mono_icall_init ();
		mono_marshal_init ();
		image = mono_get_corlib ();

		if (!mono_verifier_verify_pe_data (image, error))
			goto invalid_image;

		if (!mono_image_load_pe_data (image)) {
			printf ("Could not load pe data for assembly %s\n", fname);
			return 1;
		}

		if (!mono_verifier_verify_cli_data (image, error))
			goto invalid_image;

		if (!mono_image_load_cli_data (image)) {
			printf ("Could not load cli data for assembly %s\n", fname);
			return 1;
		}

		if (!mono_verifier_verify_table_data (image, error))
			goto invalid_image;
	}

	if (!verify_partial_md && !mono_verifier_verify_full_table_data (image, error))
		goto invalid_image;


	table = &image->tables [MONO_TABLE_TYPEDEF];
	for (i = 1; i <= table->rows; ++i) {
		ERROR_DECL (error);
		guint32 token = i | MONO_TOKEN_TYPE_DEF;
		MonoClass *klass = mono_class_get_checked (image, token, error);
		if (!klass) {
			printf ("Could not load class with token %x due to %s\n", token, mono_error_get_message (error));
			mono_error_cleanup (error);
			continue;
		}
		mono_class_init_internal (klass);
		if (mono_class_has_failure (klass)) {
			ERROR_DECL (type_load_error);
			mono_error_set_for_class_failure (type_load_error, klass);
			printf ("Could not initialize class(0x%08x) %s.%s due to %s\n", token, m_class_get_name_space (klass), m_class_get_name (klass), mono_error_get_message (type_load_error));
			mono_error_cleanup (type_load_error);
			++count;
		}

		mono_class_setup_vtable (klass);
		if (mono_class_has_failure (klass)) {
			ERROR_DECL (type_load_error);
			mono_error_set_for_class_failure (type_load_error, klass);
			printf ("Could not initialize vtable of class(0x%08x) %s.%s due to %s\n", token, m_class_get_name_space (klass), m_class_get_name (klass), mono_error_get_message (type_load_error));
			mono_error_cleanup (type_load_error);
			++count;
		}
	}
	if (count)
		return 5;
	return 0;

invalid_image:
	if (!is_ok (error)) {
		g_print ("FAIL: %s\n", mono_error_get_message (error));
		mono_error_cleanup (error);
		++count;
	}
	if (count)
		g_print ("Error count: %d\n", count);
	return 1;
}