#include <mono/metadata/mono-config.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/verify.h>
+#include <mono/metadata/verify-internals.h>
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/security-manager.h>
#include <mono/metadata/security-core-clr.h>
#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/coree.h>
+#include <mono/metadata/attach.h>
#include "mono/utils/mono-counters.h"
+#include <mono/utils/gc_wrapper.h>
#include "mini.h"
#include "jit.h"
#include <string.h>
#include <ctype.h>
-#include "inssel.h"
#include <locale.h>
#include "version.h"
+#include "debugger-agent.h"
static FILE *mini_stats_fd = NULL;
NULL
};
+
#define DEFAULT_OPTIMIZATIONS ( \
MONO_OPT_PEEPHOLE | \
MONO_OPT_CFOLD | \
MONO_OPT_INLINE | \
MONO_OPT_CONSPROP | \
MONO_OPT_COPYPROP | \
- MONO_OPT_TREEPROP | \
MONO_OPT_DEADCE | \
MONO_OPT_BRANCH | \
MONO_OPT_LINEARS | \
MONO_OPT_INTRINS | \
MONO_OPT_LOOP | \
MONO_OPT_EXCEPTION | \
+ MONO_OPT_CMOV | \
+ MONO_OPT_GSHARED | \
+ MONO_OPT_SIMD | \
MONO_OPT_AOT)
#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP)
return opt;
}
+static gboolean
+parse_debug_options (const char* p)
+{
+ MonoDebugOptions *opt = mini_get_debug_options ();
+
+ do {
+ if (!*p) {
+ fprintf (stderr, "Syntax error; expected debug option name\n");
+ return FALSE;
+ }
+
+ if (!strncmp (p, "casts", 5)) {
+ opt->better_cast_details = TRUE;
+ p += 5;
+ } else if (!strncmp (p, "mdb-optimizations", 17)) {
+ opt->mdb_optimizations = TRUE;
+ p += 17;
+ } else if (!strncmp (p, "gdb", 3)) {
+ opt->gdb = TRUE;
+ p += 3;
+ } else {
+ fprintf (stderr, "Invalid debug option `%s', use --help-debug for details\n", p);
+ return FALSE;
+ }
+
+ if (*p == ',') {
+ p++;
+ if (!*p) {
+ fprintf (stderr, "Syntax error; expected debug option name\n");
+ return FALSE;
+ }
+ }
+ } while (*p);
+
+ return TRUE;
+}
+
typedef struct {
const char name [6];
const char desc [18];
MONO_OPT_BRANCH,
MONO_OPT_CFOLD,
MONO_OPT_FCMOV,
+#ifdef MONO_ARCH_SIMD_INTRINSICS
+ MONO_OPT_SIMD,
+ MONO_OPT_SSE2,
+ MONO_OPT_SIMD | MONO_OPT_SSE2,
+#endif
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_INTRINS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_SSA,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_EXCEPTION,
+ MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_EXCEPTION | MONO_OPT_CMOV,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_EXCEPTION | MONO_OPT_ABCREM,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_EXCEPTION | MONO_OPT_ABCREM | MONO_OPT_SSAPRE,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_ABCREM,
- MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_TREEPROP,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_SSAPRE,
- MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_ABCREM | MONO_OPT_SHARED
+ MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_ABCREM | MONO_OPT_SHARED,
+ DEFAULT_OPTIMIZATIONS,
};
typedef int (*TestMethod) (void);
#endif
static int
-mini_regression (MonoImage *image, int verbose, int *total_run) {
+mini_regression (MonoImage *image, int verbose, int *total_run)
+{
guint32 i, opt, opt_flags;
MonoMethod *method;
MonoCompile *cfg;
int result, expected, failed, cfailed, run, code_size, total;
TestMethod func;
GTimer *timer = g_timer_new ();
+ MonoDomain *domain = mono_domain_get ();
+ guint32 exclude = 0;
+
+ mono_arch_cpu_optimizazions (&exclude);
if (mini_stats_fd) {
fprintf (mini_stats_fd, "$stattitle = \'Mono Benchmark Results (various optimizations)\';\n");
/* 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);
+ method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
+ if (!method)
+ continue;
mono_class_init (method->klass);
if (!strncmp (method->name, "test_", 5) && mini_stats_fd) {
for (opt = 0; opt < G_N_ELEMENTS (opt_sets); ++opt) {
double elapsed, comp_time, start_time;
- opt_flags = opt_sets [opt];
+ opt_flags = opt_sets [opt] & ~exclude;
mono_set_defaults (verbose, opt_flags);
n = opt_descr (opt_flags);
g_print ("Test run: image=%s, opts=%s\n", mono_image_get_filename (image), n);
comp_time = elapsed = 0.0;
/* fixme: ugly hack - delete all previously compiled methods */
- g_hash_table_destroy (mono_domain_get ()->jit_trampoline_hash);
- mono_domain_get ()->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
- mono_internal_hash_table_destroy (&(mono_domain_get ()->jit_code_hash));
- mono_jit_code_hash_init (&(mono_domain_get ()->jit_code_hash));
+ g_hash_table_destroy (domain_jit_info (domain)->jit_trampoline_hash);
+ domain_jit_info (domain)->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+ mono_internal_hash_table_destroy (&(domain->jit_code_hash));
+ mono_jit_code_hash_init (&(domain->jit_code_hash));
g_timer_start (timer);
if (mini_stats_fd)
fprintf (mini_stats_fd, "[");
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);
+ method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
+ if (!method)
+ continue;
if (strncmp (method->name, "test_", 5) == 0) {
expected = atoi (method->name + 5);
run++;
while (free->next != NULL) {
JitInfoData *next = free->next->next;
- g_free (free->next->ji);
+ //g_free (free->next->ji);
g_free (free->next);
free->next = next;
if (region->num_datas > 0) {
JitInfoData **data = choose_random_data (region);
guint pos = (*data)->start + random () % (*data)->length;
- MonoJitInfo *ji = mono_jit_info_table_find (domain, (char*)(gulong) pos);
+ MonoJitInfo *ji;
+
+ ji = mono_jit_info_table_find (domain, (char*)(gulong) pos);
- g_assert ((*data)->ji == ji);
g_assert (ji->cas_inited);
+ g_assert ((*data)->ji == ji);
}
} else {
int pos = random () % MAX_ADDR;
char *addr = (char*)(gulong) pos;
- MonoJitInfo *ji = mono_jit_info_table_find (domain, addr);
+ MonoJitInfo *ji;
+
+ ji = mono_jit_info_table_find (domain, addr);
+ /*
+ * FIXME: We are actually not allowed
+ * to do this. By the time we examine
+ * the ji another thread might already
+ * have removed it.
+ */
if (ji != NULL) {
g_assert (addr >= (char*)ji->code_start && addr < (char*)ji->code_start + ji->code_size);
++lookup_successes;
mono_jit_info_table_remove (domain, (*data)->ji);
- (*data)->ji->cas_inited = 0; /* marks a free jit info */
+ //(*data)->ji->cas_inited = 0; /* marks a free jit info */
free = *data;
*data = (*data)->next;
MonoImage *image = mono_assembly_get_image (ass);
MonoMethod *method;
MonoCompile *cfg;
- int i, count = 0;
+ int i, count = 0, fail_count = 0;
for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
continue;
method = mono_get_method (image, token, NULL);
+ if (!method)
+ continue;
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
g_free (desc);
}
cfg = mini_method_compile (method, args->opts, mono_get_root_domain (), FALSE, FALSE, 0);
+ if (cfg->exception_type != MONO_EXCEPTION_NONE) {
+ printf ("Compilation of %s failed with exception '%s':\n", mono_method_full_name (cfg->method, TRUE), cfg->exception_message);
+ fail_count ++;
+ }
mono_destroy_compile (cfg);
}
+ if (fail_count)
+ exit (1);
}
static void
MainThreadArgs *main_args = user_data;
MonoAssembly *assembly;
- assembly = mono_domain_assembly_open (main_args->domain, main_args->file);
- if (!assembly){
- fprintf (stderr, "Can not open image %s\n", main_args->file);
- exit (1);
- }
-
if (mono_compile_aot) {
- int res = mono_compile_assembly (assembly, main_args->opts, main_args->aot_options);
- printf ("AOT RESULT %d\n", res);
+ int i, res;
+
+ /* Treat the other arguments as assemblies to compile too */
+ for (i = 0; i < main_args->argc; ++i) {
+ assembly = mono_domain_assembly_open (main_args->domain, main_args->argv [i]);
+ if (!assembly) {
+ fprintf (stderr, "Can not open image %s\n", main_args->argv [i]);
+ exit (1);
+ }
+ /* Check that the assembly loaded matches the filename */
+ {
+ MonoImageOpenStatus status;
+ MonoImage *img;
+
+ img = mono_image_open (main_args->argv [i], &status);
+ if (img && strcmp (img->name, assembly->image->name)) {
+ fprintf (stderr, "Error: Loaded assembly '%s' doesn't match original file name '%s'. Set MONO_PATH to the assembly's location.\n", assembly->image->name, img->name);
+ exit (1);
+ }
+ }
+ res = mono_compile_assembly (assembly, main_args->opts, main_args->aot_options);
+ if (res != 0) {
+ fprintf (stderr, "AOT of image %s failed.\n", main_args->argv [i]);
+ exit (1);
+ }
+ }
} else {
+ assembly = mono_domain_assembly_open (main_args->domain, main_args->file);
+ if (!assembly){
+ fprintf (stderr, "Can not open image %s\n", main_args->file);
+ exit (1);
+ }
+
/*
* This must be done in a thread managed by mono since it can invoke
* managed code.
}
}
+static int
+load_agent (MonoDomain *domain, char *desc)
+{
+ char* col = strchr (desc, ':');
+ char *agent, *args;
+ MonoAssembly *agent_assembly;
+ MonoImage *image;
+ MonoMethod *method;
+ guint32 entry;
+ MonoArray *main_args;
+ gpointer pa [1];
+ MonoImageOpenStatus open_status;
+
+ if (col) {
+ agent = g_memdup (desc, col - desc + 1);
+ agent [col - desc] = '\0';
+ args = col + 1;
+ } else {
+ agent = g_strdup (desc);
+ args = NULL;
+ }
+
+ agent_assembly = mono_assembly_open (agent, &open_status);
+ if (!agent_assembly) {
+ fprintf (stderr, "Cannot open agent assembly '%s': %s.\n", agent, mono_image_strerror (open_status));
+ g_free (agent);
+ return 2;
+ }
+
+ /*
+ * Can't use mono_jit_exec (), as it sets things which might confuse the
+ * real Main method.
+ */
+ image = mono_assembly_get_image (agent_assembly);
+ entry = mono_image_get_entry_point (image);
+ if (!entry) {
+ g_print ("Assembly '%s' doesn't have an entry point.\n", mono_image_get_filename (image));
+ g_free (agent);
+ return 1;
+ }
+
+ method = mono_get_method (image, entry, NULL);
+ if (method == NULL){
+ g_print ("The entry point method of assembly '%s' could not be loaded\n", agent);
+ 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));
+ } else {
+ main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
+ }
+
+ g_free (agent);
+
+ pa [0] = main_args;
+ /* Pass NULL as 'exc' so unhandled exceptions abort the runtime */
+ mono_runtime_invoke (method, NULL, pa, NULL);
+
+ return 0;
+}
+
static void
mini_usage_jitdeveloper (void)
{
"Runtime and JIT debugging options:\n"
" --breakonex Inserts a breakpoint on exceptions\n"
" --break METHOD Inserts a breakpoint at METHOD entry\n"
+ " --break-at-bb METHOD N Inserts a breakpoint in METHOD at BB N\n"
" --compile METHOD Just compile METHOD in assembly\n"
" --compile-all Compiles all the methods in the assembly\n"
" --ncompile N Number of times to compile METHOD (default: 1)\n"
" --regression Runs the regression test contained in the assembly\n"
" --statfile FILE Sets the stat file to FILE\n"
" --stats Print statistics about the JIT operations\n"
- " --wapi=hps|semdel IO-layer maintenance\n"
+ " --wapi=hps|semdel|seminfo IO-layer maintenance\n"
" --inject-async-exc METHOD OFFSET Inject an asynchronous exception at METHOD\n"
+ " --verify-all Run the verifier on all methods\n"
+ " --full-aot Avoid JITting any code\n"
+ " --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"
"Other options:\n"
" --graph[=TYPE] METHOD Draws a graph of the specified method:\n");
"\n"
"Development:\n"
" --aot Compiles the assembly to native code\n"
- " --debug Enable debugging support\n"
+ " --debug[=<options>] Enable debugging support, use --help-debug for details\n"
+ " --debugger-agent=options Enable the debugger agent\n"
" --profile[=profiler] Runs in profiling mode with the specified profiler module\n"
" --trace[=EXPR] Enable tracing, use --help-trace for details\n"
" --help-devel Shows more options available to developers\n"
" --optimize=OPT Turns on or off a specific optimization\n"
" Use --list-opt to get a list of optimizations\n"
" --security[=mode] Turns on the unsupported security manager (off by default)\n"
- " mode is one of cas or core-clr\n");
+ " mode is one of cas, core-clr, verifiable or validil\n"
+ " --attach=OPTIONS Pass OPTIONS to the attach agent in the runtime.\n"
+ " Currently the only supported option is 'disable'.\n"
+ );
}
static void
" M:Type:Method Specifies a method\n"
" N:Namespace Specifies a namespace\n"
" T:Type Specifies a type\n"
- " +EXPR Includes expression\n"
+ " EXPR Includes expression\n"
" -EXPR Excludes expression\n"
+ " EXPR,EXPR Multiple expressions\n"
" disabled Don't print any output until toggled via SIGUSR2\n");
}
+static void
+mini_debug_usage (void)
+{
+ fprintf (stdout,
+ "Debugging options:\n"
+ " --debug[=OPTIONS] Enable debugging support, optional OPTIONS is a comma\n"
+ " separated list of options\n"
+ "\n"
+ "OPTIONS is composed of:\n"
+ " casts Enable more detailed InvalidCastException messages.\n"
+ " mdb-optimizations Disable some JIT optimizations which are normally\n"
+ " disabled when running inside the debugger.\n"
+ " This is useful if you plan to attach to the running\n"
+ " process with the debugger.\n");
+}
+
+#if defined(MONO_ARCH_ARCHITECTURE)
+/* Redefine ARCHITECTURE to include more information */
+#undef ARCHITECTURE
+#define ARCHITECTURE MONO_ARCH_ARCHITECTURE
+#endif
+
static const char info[] =
#ifdef HAVE_KW_THREAD
"\tTLS: __thread\n"
#define error_if_aot_unsupported()
#endif
+#ifdef PLATFORM_WIN32
+BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
+{
+ if (!GC_DllMain (module_handle, reason, reserved))
+ return FALSE;
+
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ mono_install_runtime_load (mini_init);
+ break;
+ case DLL_PROCESS_DETACH:
+ if (coree_module_handle)
+ FreeLibrary (coree_module_handle);
+ break;
+ }
+ return TRUE;
+}
+#endif
+
int
mono_main (int argc, char* argv[])
{
MonoMethod *method;
MonoCompile *cfg;
MonoDomain *domain;
+ MonoImageOpenStatus open_status;
const char* aname, *mname = NULL;
char *config_file = NULL;
int i, count = 1;
char *profile_options = NULL;
char *aot_options = NULL;
char *forced_version = NULL;
+ GPtrArray *agents = NULL;
+ char *attach_options = NULL;
#ifdef MONO_JIT_INFO_TABLE_TEST
int test_jit_info_table = FALSE;
#endif
} else if (strcmp (argv [i], "--verbose") == 0 || strcmp (argv [i], "-v") == 0) {
mini_verbose++;
} else if (strcmp (argv [i], "--version") == 0 || strcmp (argv [i], "-V") == 0) {
- g_print ("Mono JIT compiler version %s (%s)\nCopyright (C) 2002-2007 Novell, Inc and Contributors. www.mono-project.com\n", VERSION, FULL_VERSION);
+ char *build = mono_get_runtime_build_info ();
+ g_print ("Mono JIT compiler version %s (%s)\nCopyright (C) 2002-2009 Novell, Inc and Contributors. www.mono-project.com\n", VERSION, build);
+ g_free (build);
g_print (info);
if (mini_verbose) {
const char *cerror;
} else if (strcmp (argv [i], "--help-devel") == 0){
mini_usage_jitdeveloper ();
return 0;
+ } else if (strcmp (argv [i], "--help-debug") == 0){
+ mini_debug_usage ();
+ return 0;
} else if (strcmp (argv [i], "--list-opt") == 0){
mini_usage_list_opt ();
return 0;
if (!mono_debugger_insert_breakpoint (argv [++i], FALSE))
fprintf (stderr, "Error: invalid method name '%s'\n", argv [i]);
+ } else if (strcmp (argv [i], "--break-at-bb") == 0) {
+ if (i + 2 >= argc) {
+ fprintf (stderr, "Missing method name or bb num in --break-at-bb command line option.");
+ return 1;
+ }
+ mono_break_at_bb_method = mono_method_desc_new (argv [++i], TRUE);
+ if (mono_break_at_bb_method == NULL) {
+ fprintf (stderr, "Method name is in a bad format in --break-at-bb command line option.");
+ return 1;
+ }
+ mono_break_at_bb_bb_num = atoi (argv [++i]);
} else if (strcmp (argv [i], "--inject-async-exc") == 0) {
if (i + 2 >= argc) {
fprintf (stderr, "Missing method name or position in --inject-async-exc command line option\n");
return 1;
}
mono_inject_async_exc_pos = atoi (argv [++i]);
+ } else if (strcmp (argv [i], "--verify-all") == 0) {
+ mono_verifier_enable_verify_all ();
+ } else if (strcmp (argv [i], "--full-aot") == 0) {
+ mono_aot_only = TRUE;
} else if (strcmp (argv [i], "--print-vtable") == 0) {
mono_print_vtable = TRUE;
} else if (strcmp (argv [i], "--stats") == 0) {
} else if (strncmp (argv [i], "--profile=", 10) == 0) {
enable_profile = TRUE;
profile_options = argv [i] + 10;
+ } else if (strncmp (argv [i], "--agent=", 8) == 0) {
+ if (agents == NULL)
+ agents = g_ptr_array_new ();
+ g_ptr_array_add (agents, argv [i] + 8);
+ } else if (strncmp (argv [i], "--attach=", 9) == 0) {
+ attach_options = argv [i] + 9;
} else if (strcmp (argv [i], "--compile") == 0) {
if (i + 1 >= argc){
fprintf (stderr, "error: --compile option requires a method name argument\n");
action = DO_DRAW;
} else if (strcmp (argv [i], "--debug") == 0) {
enable_debugging = TRUE;
+ } else if (strncmp (argv [i], "--debug=", 8) == 0) {
+ enable_debugging = TRUE;
+ if (!parse_debug_options (argv [i] + 8))
+ return 1;
+ } else if (strncmp (argv [i], "--debugger-agent=", 17) == 0) {
+ MonoDebugOptions *opt = mini_get_debug_options ();
+
+ mono_debugger_agent_parse_options (argv [i] + 17);
+ opt->mdb_optimizations = TRUE;
+ enable_debugging = TRUE;
} else if (strcmp (argv [i], "--security") == 0) {
+ mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE);
mono_security_set_mode (MONO_SECURITY_MODE_CAS);
mono_activate_security_manager ();
} else if (strncmp (argv [i], "--security=", 11) == 0) {
if (strcmp (argv [i] + 11, "temporary-smcs-hack") == 0) {
mono_security_set_mode (MONO_SECURITY_MODE_SMCS_HACK);
} else if (strcmp (argv [i] + 11, "core-clr") == 0) {
+ mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE);
mono_security_set_mode (MONO_SECURITY_MODE_CORE_CLR);
} else if (strcmp (argv [i] + 11, "core-clr-test") == 0) {
+ /* fixme should we enable verifiable code here?*/
mono_security_set_mode (MONO_SECURITY_MODE_CORE_CLR);
mono_security_core_clr_test = TRUE;
} else if (strcmp (argv [i] + 11, "cas") == 0){
+ mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE);
mono_security_set_mode (MONO_SECURITY_MODE_CAS);
mono_activate_security_manager ();
- } else {
- fprintf (stderr, "error: --security= option has invalid argument (cas or core-clr)\n");
+ } else if (strcmp (argv [i] + 11, "validil") == 0) {
+ mono_verifier_set_mode (MONO_VERIFIER_MODE_VALID);
+ } else if (strcmp (argv [i] + 11, "verifiable") == 0) {
+ mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE);
+ } else {
+ fprintf (stderr, "error: --security= option has invalid argument (cas, core-clr, verifiable or validil)\n");
return 1;
}
} else if (strcmp (argv [i], "--desktop") == 0) {
fprintf (stderr, "Invalid --wapi suboption: '%s'\n", argv [i]);
return 1;
}
+ } else if (strcmp (argv [i], "--no-x86-stack-align") == 0) {
+ mono_do_x86_stack_align = FALSE;
#ifdef MONO_JIT_INFO_TABLE_TEST
} else if (strcmp (argv [i], "--test-jit-info-table") == 0) {
test_jit_info_table = TRUE;
return 1;
}
- if ((action == DO_EXEC) && g_getenv ("MONO_INSIDE_MDB"))
+ if (getenv ("MONO_XDEBUG"))
+ enable_debugging = TRUE;
+
+#ifdef MONO_CROSS_COMPILE
+ if (!mono_compile_aot) {
+ fprintf (stderr, "This mono runtime is compiled for cross-compiling. Only the --aot option is supported.");
+ exit (1);
+ }
+#if SIZEOF_VOID_P == 8 && defined(TARGET_ARM)
+ fprintf (stderr, "Can't cross-compile on 64 bit platforms to arm.\n");
+ exit (1);
+#endif
+#endif
+
+ if ((action == DO_EXEC) && mono_debug_using_mono_debugger ())
action = DO_DEBUGGER;
if (mono_compile_aot || action == DO_EXEC || action == DO_DEBUGGER) {
g_set_prgname (argv[i]);
}
- if (enable_profile) {
- /* Needed because of TLS accesses in mono_profiler_load () */
- mono_gc_base_init ();
+ if (enable_profile)
mono_profiler_load (profile_options);
- }
+
+ mono_attach_parse_options (attach_options);
if (trace_options != NULL){
/*
exit (1);
}
+#ifdef DISABLE_JIT
+ if (!mono_aot_only) {
+ fprintf (stderr, "This runtime has been configured with --enable-minimal=jit, so the --full-aot command line option is required.\n");
+ exit (1);
+ }
+#endif
+
if (action == DO_DEBUGGER) {
- // opt |= MONO_OPT_SHARED;
- opt &= ~MONO_OPT_INLINE;
- opt &= ~MONO_OPT_COPYPROP;
- opt &= ~MONO_OPT_CONSPROP;
enable_debugging = TRUE;
#ifdef MONO_DEBUGGER_SUPPORTED
mono_debug_init (MONO_DEBUG_FORMAT_DEBUGGER);
- mono_debugger_init ();
#else
g_print ("The Mono Debugger is not supported on this platform.\n");
return 1;
} else if (enable_debugging)
mono_debug_init (MONO_DEBUG_FORMAT_MONO);
+#ifdef MONO_DEBUGGER_SUPPORTED
+ if (enable_debugging) {
+ if ((opt & MONO_OPT_GSHARED) == 0)
+ mini_debugger_set_attach_ok ();
+ }
+#endif
+
mono_set_defaults (mini_verbose, opt);
+ mono_setup_vtable_in_class_init = FALSE;
domain = mini_init (argv [i], forced_version);
+
+ if (agents) {
+ int i;
+
+ for (i = 0; i < agents->len; ++i) {
+ int res = load_agent (domain, (char*)g_ptr_array_index (agents, i));
+ if (res) {
+ g_ptr_array_free (agents, TRUE);
+ mini_cleanup (domain);
+ return 1;
+ }
+ }
+
+ g_ptr_array_free (agents, TRUE);
+ }
switch (action) {
case DO_REGRESSION:
jit_info_table_test (domain);
#endif
- assembly = mono_assembly_open (aname, NULL);
+ assembly = mono_assembly_open (aname, &open_status);
if (!assembly) {
- fprintf (stderr, "Cannot open assembly %s.\n", aname);
+ fprintf (stderr, "Cannot open assembly '%s': %s.\n", aname, mono_image_strerror (open_status));
mini_cleanup (domain);
return 2;
}
main_thread_handler (&main_args);
mono_thread_manage ();
#endif
+
+ /*
+ * On unix, WaitForMultipleObjects for threads is implemented by waiting on
+ * a cond variable, which is set by the thread when it exits _mono code_,
+ * but it could still be running libc code. On amd64, the libc thread exit
+ * code does a stack unwind, and if it encounters a frame pointing to native
+ * code which is in memory which is no longer mapped (because the runtime has
+ * shut down), it will crash:
+ * http://mail-archives.apache.org/mod_mbox/harmony-dev/200801.mbox/%3C200801130327.41572.gshimansky@apache.org%3E
+ * Testcase: tests/main-exit-background-change.exe.
+ * To make this race less frequent, we avoid freeing the global code manager.
+ * Since mono_main () is hopefully only used by the runtime executable, this
+ * will only cause a shutdown leak. This workaround also has the advantage
+ * that it can be back-ported to 2.0 safely.
+ * FIXME: Fix this properly by waiting for threads to really exit using
+ * pthread_join (). This cannot be done currently as the io-layer calls
+ * pthread_detach ().
+ */
+#ifdef __x86_64__
+ mono_dont_free_global_codeman = TRUE;
+#endif
+
mini_cleanup (domain);
/* Look up return value from System.Environment.ExitCode */
exit (1);
}
- mono_debugger_main (domain, assembly, argc - i, argv + i);
+ mini_debugger_main (domain, assembly, argc - i, argv + i);
mini_cleanup (domain);
return 0;
#else
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
MonoMethod *nm;
- nm = mono_marshal_get_native_wrapper (method);
+ nm = mono_marshal_get_native_wrapper (method, TRUE, FALSE);
cfg = mini_method_compile (nm, opt, mono_get_root_domain (), FALSE, FALSE, part);
}
else
for (i = 0; i < count; ++i) {
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
- method = mono_marshal_get_native_wrapper (method);
+ method = mono_marshal_get_native_wrapper (method, TRUE, FALSE);
cfg = mini_method_compile (method, opt, mono_get_root_domain (), FALSE, FALSE, 0);
mono_destroy_compile (cfg);
/**
* mono_jit_init_version:
- * @file: the initial assembly to load
+ * @domain_name: the name of the root domain
* @runtime_version: the version of the runtime to load
*
* Use this version when you want to force a particular runtime
* was loaded.
*/
MonoDomain *
-mono_jit_init_version (const char *file, const char *runtime_version)
+mono_jit_init_version (const char *domain_name, const char *runtime_version)
{
- return mini_init (file, runtime_version);
+ return mini_init (domain_name, runtime_version);
}
void
{
mini_cleanup (domain);
}
+
+void
+mono_jit_set_aot_only (gboolean val)
+{
+ mono_aot_only = val;
+}
+
+/**
+ * mono_jit_set_trace_options:
+ * @options: string representing the trace options
+ *
+ * Set the options of the tracing engine. This function can be called before initializing
+ * the mono runtime. See the --trace mono(1) manpage for the options format.
+ *
+ * Returns: #TRUE if the options where parsed and set correctly, #FALSE otherwise.
+ */
+gboolean
+mono_jit_set_trace_options (const char* options)
+{
+ MonoTraceSpec *trace_opt = mono_trace_parse_options (options);
+ if (trace_opt == NULL)
+ return FALSE;
+ mono_jit_trace_calls = trace_opt;
+ return TRUE;
+}
+
+/**
+ * mono_set_signal_chaining:
+ *
+ * Enable/disable signal chaining. This should be called before mono_jit_init ().
+ * If signal chaining is enabled, the runtime saves the original signal handlers before
+ * installing its own handlers, and calls the original ones in the following cases:
+ * - a SIGSEGV/SIGABRT signal received while executing native (i.e. not JITted) code.
+ * - SIGPROF
+ * - SIGFPE
+ * - SIGQUIT
+ * - SIGUSR2
+ * Signal chaining only works on POSIX platforms.
+ */
+void
+mono_set_signal_chaining (gboolean chain_signals)
+{
+ mono_do_signal_chaining = chain_signals;
+}