*
* (C) 2002-2003 Ximian, Inc.
* (C) 2003-2006 Novell, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#include <mono/metadata/attach.h>
#include "mono/utils/mono-counters.h"
#include "mono/utils/mono-hwcap.h"
+#include "mono/utils/mono-logger-internals.h"
#include "mini.h"
#include "jit.h"
NULL
};
-#ifdef __native_client_codegen__
-extern gint8 nacl_align_byte;
-#endif
#ifdef __native_client__
extern char *nacl_mono_path;
#endif
if (mini_stats_fd)
fprintf (mini_stats_fd, "[");
for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
- MonoMethod *method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
- if (!method)
+ MonoError error;
+ MonoMethod *method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
+ if (!method) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
continue;
+ }
if (strncmp (method->name, "test_", 5) == 0) {
MonoCompile *cfg;
if (verbose >= 2)
g_print ("Running '%s' ...\n", method->name);
#ifdef MONO_USE_AOT_COMPILER
- if ((func = (TestMethod)mono_aot_get_method (mono_get_root_domain (), method)))
- ;
- else
-#endif
+ MonoError error;
+ func = (TestMethod)mono_aot_get_method_checked (mono_get_root_domain (), method, &error);
+ mono_error_cleanup (&error);
+ if (!func)
+ func = (TestMethod)(gpointer)cfg->native_code;
+#else
func = (TestMethod)(gpointer)cfg->native_code;
+#endif
func = (TestMethod)mono_create_ftnptr (mono_get_root_domain (), func);
result = func ();
if (result != expected) {
/* load the metadata */
for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
- method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
- if (!method)
+ MonoError error;
+ method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
+ if (!method) {
+ mono_error_cleanup (&error);
continue;
+ }
mono_class_init (method->klass);
if (!strncmp (method->name, "test_", 5) && mini_stats_fd) {
static void
jit_info_table_test (MonoDomain *domain)
{
+ MonoError error;
int i;
g_print ("testing jit_info_table\n");
sleep (2);
*/
- for (i = 0; i < num_threads; ++i)
- mono_thread_create (domain, test_thread_func, &thread_datas [i]);
+ for (i = 0; i < num_threads; ++i) {
+ mono_thread_create_checked (domain, test_thread_func, &thread_datas [i], &error);
+ mono_error_assert_ok (&error);
+ }
}
#endif
int i, count = 0, fail_count = 0;
for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
+ MonoError error;
guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
MonoMethodSignature *sig;
if (mono_metadata_has_generic_params (image, token))
continue;
- method = mono_get_method (image, token, NULL);
- if (!method)
+ method = mono_get_method_checked (image, token, NULL, NULL, &error);
+ if (!method) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
continue;
+ }
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
static void
compile_all_methods (MonoAssembly *ass, int verbose, guint32 opts, guint32 recompilation_times)
{
+ MonoError error;
CompileAllThreadArgs args;
args.ass = ass;
* Need to create a mono thread since compilation might trigger
* running of managed code.
*/
- mono_thread_create (mono_domain_get (), compile_all_methods_thread_main, &args);
+ mono_thread_create_checked (mono_domain_get (), compile_all_methods_thread_main, &args, &error);
+ mono_error_assert_ok (&error);
mono_thread_manage ();
}
int
mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
{
+ MonoError error;
MonoImage *image = mono_assembly_get_image (assembly);
MonoMethod *method;
guint32 entry = mono_image_get_entry_point (image);
return 1;
}
- method = mono_get_method (image, entry, NULL);
+ method = mono_get_method_checked (image, entry, NULL, NULL, &error);
if (method == NULL){
- g_print ("The entry point method could not be loaded\n");
+ g_print ("The entry point method could not be loaded due to %s\n", mono_error_get_message (&error));
+ mono_error_cleanup (&error);
mono_environment_exitcode_set (1);
return 1;
}
- return mono_runtime_run_main (method, argc, argv, NULL);
+ if (mono_llvm_only) {
+ MonoObject *exc;
+ int res;
+
+ res = mono_runtime_run_main (method, argc, argv, &exc);
+ if (exc) {
+ mono_unhandled_exception (exc);
+ mono_invoke_unhandled_exception_hook (exc);
+ return 1;
+ }
+ return res;
+ } else {
+ return mono_runtime_run_main (method, argc, argv, NULL);
+ }
}
typedef struct
static int
load_agent (MonoDomain *domain, char *desc)
{
+ MonoError error;
char* col = strchr (desc, ':');
char *agent, *args;
MonoAssembly *agent_assembly;
return 1;
}
- method = mono_get_method (image, entry, NULL);
+ method = mono_get_method_checked (image, entry, NULL, NULL, &error);
if (method == NULL){
- g_print ("The entry point method of assembly '%s' could not be loaded\n", agent);
+ g_print ("The entry point method of assembly '%s' could not be loaded due to %s\n", agent, mono_error_get_message (&error));
+ mono_error_cleanup (&error);
g_free (agent);
return 1;
}
mono_thread_set_main (mono_thread_current ());
if (args) {
- main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 1);
- mono_array_set (main_args, MonoString*, 0, mono_string_new (domain, args));
+ main_args = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, 1, &error);
+ if (main_args)
+ mono_array_set (main_args, MonoString*, 0, mono_string_new (domain, args));
} else {
- main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
+ main_args = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
}
-
- g_free (agent);
+ if (!main_args) {
+ g_print ("Could not allocate array for main args of assembly '%s' due to %s\n", agent, mono_error_get_message (&error));
+ mono_error_cleanup (&error);
+ g_free (agent);
+ return 1;
+ }
+
pa [0] = main_args;
/* Pass NULL as 'exc' so unhandled exceptions abort the runtime */
- mono_runtime_invoke (method, NULL, pa, NULL);
+ mono_runtime_invoke_checked (method, NULL, pa, &error);
+ if (!is_ok (&error)) {
+ g_print ("The entry point method of assembly '%s' could not execute due to %s\n", agent, mono_error_get_message (&error));
+ mono_error_cleanup (&error);
+ g_free (agent);
+ return 1;
+ }
+ g_free (agent);
return 0;
}
" --agent=ASSEMBLY[:ARG] Loads the specific agent assembly and executes its Main method with the given argument before loading the main assembly.\n"
" --no-x86-stack-align Don't align stack on x86\n"
"\n"
+ "The options supported by MONO_DEBUG can also be passed on the command line.\n"
+ "\n"
"Other options:\n"
" --graph[=TYPE] METHOD Draws a graph of the specified method:\n");
" --trace[=EXPR] Enable tracing, use --help-trace for details\n"
" --jitmap Output a jit method map to /tmp/perf-PID.map\n"
" --help-devel Shows more options available to developers\n"
-#ifdef __native_client_codegen__
- " --nacl-align-mask-off Turn off Native Client 32-byte alignment mask (for debug only)\n"
-#endif
"\n"
"Runtime:\n"
" --config FILE Loads FILE as the Mono config\n"
#else
mono_use_llvm = TRUE;
#endif
+ } else if (argv [i][0] == '-' && argv [i][1] == '-' && mini_parse_debug_option (argv [i] + 2)) {
} else {
fprintf (stderr, "Unsupported command line option: '%s'\n", argv [i]);
exit (1);
#if TARGET_OSX
darwin_change_default_file_handles ();
#endif
-
+
if (g_getenv ("MONO_NO_SMP"))
mono_set_use_smp (FALSE);
gc_descr = mono_gc_get_description ();
g_print ("\tGC: %s\n", gc_descr);
g_free (gc_descr);
- if (mini_verbose) {
- const char *cerror;
- const char *clibpath;
- mono_init ("mono");
- cerror = mono_check_corlib_version ();
- clibpath = mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown";
- if (cerror) {
- g_print ("The currently installed mscorlib doesn't match this runtime version.\n");
- g_print ("The error is: %s\n", cerror);
- g_print ("mscorlib.dll loaded at: %s\n", clibpath);
- return 1;
- }
- }
return 0;
} else if (strcmp (argv [i], "--help") == 0 || strcmp (argv [i], "-h") == 0) {
mini_usage ();
#endif
} else if (strcmp (argv [i], "--nollvm") == 0){
mono_use_llvm = FALSE;
-#ifdef __native_client_codegen__
- } else if (strcmp (argv [i], "--nacl-align-mask-off") == 0){
- nacl_align_byte = -1; /* 0xff */
-#endif
#ifdef __native_client__
} else if (strcmp (argv [i], "--nacl-mono-path") == 0){
nacl_mono_path = g_strdup(argv[++i]);
} else if (strcmp (argv [i], "--nacl-null-checks-off") == 0){
nacl_null_checks_off = TRUE;
#endif
+ } else if (argv [i][0] == '-' && argv [i][1] == '-' && mini_parse_debug_option (argv [i] + 2)) {
} else {
fprintf (stderr, "Unknown command line option: '%s'\n", argv [i]);
return 1;
}
#ifdef __native_client_codegen__
- if (g_getenv ("MONO_NACL_ALIGN_MASK_OFF"))
- {
- nacl_align_byte = -1; /* 0xff */
- }
if (!nacl_null_checks_off) {
MonoDebugOptions *opt = mini_get_debug_options ();
opt->explicit_null_checks = TRUE;
}
#endif
+#if defined(DISABLE_HW_TRAPS) || defined(MONO_ARCH_DISABLE_HW_TRAPS)
+ // Signal handlers not available
+ {
+ MonoDebugOptions *opt = mini_get_debug_options ();
+ opt->explicit_null_checks = TRUE;
+ }
+#endif
+
if (!argv [i]) {
mini_usage ();
return 1;
/* Set rootdir before loading config */
mono_set_rootdir ();
- if (enable_profile)
+ /*
+ * We only set the native name of the thread since MS.NET leaves the
+ * managed thread name for the main thread as null.
+ */
+ mono_native_thread_set_name (mono_native_thread_id_get (), "Main");
+
+ if (enable_profile) {
mono_profiler_load (profile_options);
+ mono_profiler_thread_name (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main");
+ }
mono_attach_parse_options (attach_options);
mono_do_crash_chaining = chain_crashes;
}
-void
-mono_parse_env_options (int *ref_argc, char **ref_argv [])
+/**
+ * mono_parse_options_from:
+ * @options: string containing strings
+ * @ref_argc: pointer to the argc variable that might be updated
+ * @ref_argv: pointer to the argv string vector variable that might be updated
+ *
+ * This function parses the contents of the `MONO_ENV_OPTIONS`
+ * environment variable as if they were parsed by a command shell
+ * splitting the contents by spaces into different elements of the
+ * @argv vector. This method supports quoting with both the " and '
+ * characters. Inside quoting, spaces and tabs are significant,
+ * otherwise, they are considered argument separators.
+ *
+ * The \ character can be used to escape the next character which will
+ * be added to the current element verbatim. Typically this is used
+ * inside quotes. If the quotes are not balanced, this method
+ *
+ * If the environment variable is empty, no changes are made
+ * to the values pointed by @ref_argc and @ref_argv.
+ *
+ * Otherwise the @ref_argv is modified to point to a new array that contains
+ * all the previous elements contained in the vector, plus the values parsed.
+ * The @argc is updated to match the new number of parameters.
+ *
+ * Returns: The value NULL is returned on success, otherwise a g_strdup allocated
+ * string is returned (this is an alias to malloc under normal circumstances) that
+ * contains the error message that happened during parsing.
+ */
+char *
+mono_parse_options_from (const char *options, int *ref_argc, char **ref_argv [])
{
int argc = *ref_argc;
char **argv = *ref_argv;
-
- const char *env_options = g_getenv ("MONO_ENV_OPTIONS");
- if (env_options != NULL){
- GPtrArray *array = g_ptr_array_new ();
- GString *buffer = g_string_new ("");
- const char *p;
- unsigned i;
- gboolean in_quotes = FALSE;
- char quote_char = '\0';
-
- for (p = env_options; *p; p++){
- switch (*p){
- case ' ': case '\t':
- if (!in_quotes) {
- if (buffer->len != 0){
- g_ptr_array_add (array, g_strdup (buffer->str));
- g_string_truncate (buffer, 0);
- }
- } else {
- g_string_append_c (buffer, *p);
- }
- break;
- case '\\':
- if (p [1]){
- g_string_append_c (buffer, p [1]);
- p++;
- }
- break;
- case '\'':
- case '"':
- if (in_quotes) {
- if (quote_char == *p)
- in_quotes = FALSE;
- else
- g_string_append_c (buffer, *p);
- } else {
- in_quotes = TRUE;
- quote_char = *p;
+ GPtrArray *array = g_ptr_array_new ();
+ GString *buffer = g_string_new ("");
+ const char *p;
+ unsigned i;
+ gboolean in_quotes = FALSE;
+ char quote_char = '\0';
+
+ if (options == NULL)
+ return NULL;
+
+ for (p = options; *p; p++){
+ switch (*p){
+ case ' ': case '\t':
+ if (!in_quotes) {
+ if (buffer->len != 0){
+ g_ptr_array_add (array, g_strdup (buffer->str));
+ g_string_truncate (buffer, 0);
}
- break;
- default:
+ } else {
g_string_append_c (buffer, *p);
- break;
}
+ break;
+ case '\\':
+ if (p [1]){
+ g_string_append_c (buffer, p [1]);
+ p++;
+ }
+ break;
+ case '\'':
+ case '"':
+ if (in_quotes) {
+ if (quote_char == *p)
+ in_quotes = FALSE;
+ else
+ g_string_append_c (buffer, *p);
+ } else {
+ in_quotes = TRUE;
+ quote_char = *p;
+ }
+ break;
+ default:
+ g_string_append_c (buffer, *p);
+ break;
}
- if (in_quotes) {
- fprintf (stderr, "Unmatched quotes in value of MONO_ENV_OPTIONS: [%s]\n", env_options);
- exit (1);
- }
-
- if (buffer->len != 0)
- g_ptr_array_add (array, g_strdup (buffer->str));
- g_string_free (buffer, TRUE);
+ }
+ if (in_quotes)
+ return g_strdup_printf ("Unmatched quotes in value: [%s]\n", options);
+
+ if (buffer->len != 0)
+ g_ptr_array_add (array, g_strdup (buffer->str));
+ g_string_free (buffer, TRUE);
- if (array->len > 0){
- int new_argc = array->len + argc;
- char **new_argv = g_new (char *, new_argc + 1);
- int j;
+ if (array->len > 0){
+ int new_argc = array->len + argc;
+ char **new_argv = g_new (char *, new_argc + 1);
+ int j;
- new_argv [0] = argv [0];
-
- /* First the environment variable settings, to allow the command line options to override */
- for (i = 0; i < array->len; i++)
- new_argv [i+1] = (char *)g_ptr_array_index (array, i);
- i++;
- for (j = 1; j < argc; j++)
- new_argv [i++] = argv [j];
- new_argv [i] = NULL;
-
- *ref_argc = new_argc;
- *ref_argv = new_argv;
- }
- g_ptr_array_free (array, TRUE);
+ new_argv [0] = argv [0];
+
+ /* First the environment variable settings, to allow the command line options to override */
+ for (i = 0; i < array->len; i++)
+ new_argv [i+1] = (char *)g_ptr_array_index (array, i);
+ i++;
+ for (j = 1; j < argc; j++)
+ new_argv [i++] = argv [j];
+ new_argv [i] = NULL;
+
+ *ref_argc = new_argc;
+ *ref_argv = new_argv;
}
+ g_ptr_array_free (array, TRUE);
+ return NULL;
+}
+
+/**
+ * mono_parse_env_options:
+ * @ref_argc: pointer to the argc variable that might be updated
+ * @ref_argv: pointer to the argv string vector variable that might be updated
+ *
+ * This function parses the contents of the `MONO_ENV_OPTIONS`
+ * environment variable as if they were parsed by a command shell
+ * splitting the contents by spaces into different elements of the
+ * @argv vector. This method supports quoting with both the " and '
+ * characters. Inside quoting, spaces and tabs are significant,
+ * otherwise, they are considered argument separators.
+ *
+ * The \ character can be used to escape the next character which will
+ * be added to the current element verbatim. Typically this is used
+ * inside quotes. If the quotes are not balanced, this method
+ *
+ * If the environment variable is empty, no changes are made
+ * to the values pointed by @ref_argc and @ref_argv.
+ *
+ * Otherwise the @ref_argv is modified to point to a new array that contains
+ * all the previous elements contained in the vector, plus the values parsed.
+ * The @argc is updated to match the new number of parameters.
+ *
+ * If there is an error parsing, this method will terminate the process by
+ * calling exit(1).
+ *
+ * An alternative to this method that allows an arbitrary string to be parsed
+ * and does not exit on error is the `api:mono_parse_options_from`.
+ */
+void
+mono_parse_env_options (int *ref_argc, char **ref_argv [])
+{
+ char *ret;
+
+ const char *env_options = g_getenv ("MONO_ENV_OPTIONS");
+ if (env_options == NULL)
+ return;
+ ret = mono_parse_options_from (env_options, ref_argc, ref_argv);
+ if (ret == NULL)
+ return;
+ fprintf (stderr, "%s", ret);
+ exit (1);
}
+