#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 <ctype.h>
#include <locale.h>
#include "version.h"
+#include "debugger-agent.h"
static FILE *mini_stats_fd = NULL;
static void mini_usage (void);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
/* Need this to determine whether to detach console */
#include <mono/metadata/cil-coff.h>
/* This turns off command line globbing under win32 */
NULL
};
+#ifdef __native_client_codegen__
+extern gint8 nacl_align_byte;
+#endif
+#ifdef __native_client__
+extern char *nacl_mono_path;
+#endif
#define DEFAULT_OPTIMIZATIONS ( \
MONO_OPT_PEEPHOLE | \
MONO_OPT_INLINE | \
MONO_OPT_CONSPROP | \
MONO_OPT_COPYPROP | \
- MONO_OPT_TREEPROP | \
MONO_OPT_DEADCE | \
MONO_OPT_BRANCH | \
MONO_OPT_LINEARS | \
MONO_OPT_SIMD | \
MONO_OPT_AOT)
-#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP)
+#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP | MONO_OPT_UNSAFE)
static guint32
parse_optimizations (const char* p)
} 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;
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_CFOLD,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE,
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_TAILC,
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,
DEFAULT_OPTIMIZATIONS,
/* 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) {
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++;
if (method->klass->generic_container)
continue;
sig = mono_method_signature (method);
+ if (!sig) {
+ char * desc = mono_method_full_name (method, TRUE);
+ g_print ("Could not retrieve method signature for %s\n", desc);
+ g_free (desc);
+ fail_count ++;
+ continue;
+ }
+
if (sig->has_type_parameters)
continue;
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]);
" --stats Print statistics about the JIT operations\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"
+ " --verify-all Run the verifier on all assemblies and 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"
"Usage is: mono [options] program [program-options]\n"
"\n"
"Development:\n"
- " --aot Compiles the assembly to native code\n"
+ " --aot[=<options>] Compiles the assembly to native code\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"
+ " --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"
" 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"
+ " --llvm, --nollvm Controls whenever the runtime uses LLVM to compile code.\n"
+ " --gc=[sgen,boehm] Select SGen or Boehm GC (runs mono or mono-sgen)\n"
+#ifdef HOST_WIN32
+ " --mixed-mode Enable mixed-mode image support.\n"
+#endif
);
}
#else
"\tTLS: normal\n"
#endif /* HAVE_KW_THREAD */
- "\tGC: " USED_GC_NAME "\n"
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
"\tSIGSEGV: altstack\n"
#else
#endif
#ifdef HAVE_EPOLL
"\tNotifications: epoll\n"
+#elif defined(HAVE_KQUEUE)
+ "\tNotification: kqueue\n"
#else
"\tNotification: Thread + polling\n"
#endif
"\tArchitecture: " ARCHITECTURE "\n"
"\tDisabled: " DISABLED_FEATURES "\n"
+ "\tMisc: "
+#ifdef MONO_SMALL_CONFIG
+ "smallconfig "
+#endif
+#ifdef MONO_BIG_ARRAYS
+ "bigarrays "
+#endif
+#ifdef MONO_DEBUGGER_SUPPORTED
+ "debugger "
+#endif
+#if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && !defined(DISABLE_SOFT_DEBUG)
+ "softdebug "
+#endif
+ "\n"
+#ifdef MONO_ARCH_LLVM_SUPPORTED
+#ifdef ENABLE_LLVM
+ "\tLLVM: yes(" LLVM_VERSION ")\n"
+#else
+ "\tLLVM: supported, not enabled.\n"
+#endif
+#endif
"";
#ifndef MONO_ARCH_AOT_SUPPORTED
#define error_if_aot_unsupported()
#endif
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
{
- if (!GC_DllMain (module_handle, reason, reserved))
+ int dummy;
+ if (!mono_gc_dllmain (module_handle, reason, reserved))
return FALSE;
switch (reason)
if (coree_module_handle)
FreeLibrary (coree_module_handle);
break;
+ case DLL_THREAD_ATTACH:
+ mono_thread_info_attach (&dummy);
+ break;
+ case DLL_THREAD_DETACH:
+ mono_thread_info_dettach ();
+ break;
+
}
return TRUE;
}
#endif
+static gboolean enable_debugging;
+
+/*
+ * mono_jit_parse_options:
+ *
+ * Process the command line options in ARGV as done by the runtime executable.
+ * This should be called before mono_jit_init ().
+ */
+void
+mono_jit_parse_options (int argc, char * argv[])
+{
+ int i;
+
+ /*
+ * Some options have no effect here, since they influence the behavior of
+ * mono_main ().
+ */
+
+ /* FIXME: Avoid code duplication */
+ for (i = 0; i < argc; ++i) {
+ if (argv [i] [0] != '-')
+ break;
+ 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], "--soft-breakpoints")) {
+ MonoDebugOptions *opt = mini_get_debug_options ();
+
+ opt->soft_breakpoints = TRUE;
+ opt->explicit_null_checks = TRUE;
+ } else {
+ fprintf (stderr, "Unsupported command line option: '%s'\n", argv [i]);
+ exit (1);
+ }
+ }
+}
+
+static void
+mono_set_use_smp (int use_smp)
+{
+#if HAVE_SCHED_SETAFFINITY
+ if (!use_smp) {
+ unsigned long proc_mask = 1;
+#ifdef GLIBC_BEFORE_2_3_4_SCHED_SETAFFINITY
+ sched_setaffinity (getpid(), (gpointer)&proc_mask);
+#else
+ sched_setaffinity (getpid(), sizeof (unsigned long), (gpointer)&proc_mask);
+#endif
+ }
+#endif
+}
+
+
+/**
+ * mono_main:
+ * @argc: number of arguments in the argv array
+ * @argv: array of strings containing the startup arguments
+ *
+ * Launches the Mono JIT engine and parses all the command line options
+ * in the same way that the mono command line VM would.
+ */
int
mono_main (int argc, char* argv[])
{
const char* aname, *mname = NULL;
char *config_file = NULL;
int i, count = 1;
- int enable_debugging = FALSE;
guint32 opt, action = DO_EXEC;
MonoGraphOptions mono_graph_options = 0;
int mini_verbose = 0;
char *attach_options = NULL;
#ifdef MONO_JIT_INFO_TABLE_TEST
int test_jit_info_table = FALSE;
+#endif
+#ifdef HOST_WIN32
+ int mixed_mode = FALSE;
+#endif
+
+#ifdef MOONLIGHT
+#ifndef HOST_WIN32
+ /* stdout defaults to block buffering if it's not writing to a terminal, which
+ * happens with our test harness: we redirect stdout to capture it. Force line
+ * buffering in all cases. */
+ setlinebuf (stdout);
+#endif
#endif
setlocale (LC_ALL, "");
-#if HAVE_SCHED_SETAFFINITY
- if (getenv ("MONO_NO_SMP")) {
- unsigned long proc_mask = 1;
- sched_setaffinity (getpid(), sizeof (unsigned long), (gpointer)&proc_mask);
- }
-#endif
+ if (getenv ("MONO_NO_SMP"))
+ mono_set_use_smp (FALSE);
+
if (!g_thread_supported ())
g_thread_init (NULL);
mini_verbose++;
} else if (strcmp (argv [i], "--version") == 0 || strcmp (argv [i], "-V") == 0) {
char *build = mono_get_runtime_build_info ();
- g_print ("Mono JIT compiler version %s (%s)\nCopyright (C) 2002-2008 Novell, Inc and Contributors. www.mono-project.com\n", VERSION, build);
+ char *gc_descr;
+
+ g_print ("Mono JIT compiler version %s\nCopyright (C) 2002-2011 Novell, Inc, Xamarin, Inc and Contributors. www.mono-project.com\n", build);
g_free (build);
g_print (info);
+ 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;
opt = parse_optimizations (argv [i] + 11);
} else if (strncmp (argv [i], "-O=", 3) == 0) {
opt = parse_optimizations (argv [i] + 3);
+ } else if (strcmp (argv [i], "--gc=sgen") == 0) {
+ if (!strcmp (mono_gc_get_gc_name (), "boehm")) {
+ GString *path = g_string_new (argv [0]);
+ g_string_append (path, "-sgen");
+ argv [0] = path->str;
+#ifdef HAVE_EXECVP
+ execvp (path->str, argv);
+#else
+ fprintf (stderr, "Error: --gc=<NAME> option not supported on this platform.\n");
+#endif
+ }
+ } else if (strcmp (argv [i], "--gc=boehm") == 0) {
+ if (!strcmp (mono_gc_get_gc_name (), "sgen")) {
+ char *copy = g_strdup (argv [0]);
+ char *p = strstr (copy, "-sgen");
+ if (p == NULL){
+ fprintf (stderr, "Error, this process is not named mono-sgen and the command line option --boehm was passed");
+ exit (1);
+ }
+ *p = 0;
+ argv [0] = p;
+#ifdef HAVE_EXECVP
+ execvp (p, argv);
+#else
+ fprintf (stderr, "Error: --gc=<NAME> option not supported on this platform.\n");
+#endif
+ }
} else if (strcmp (argv [i], "--config") == 0) {
if (i +1 >= argc){
fprintf (stderr, "error: --config requires a filename argument\n");
return 1;
}
config_file = argv [++i];
+#ifdef HOST_WIN32
+ } else if (strcmp (argv [i], "--mixed-mode") == 0) {
+ mixed_mode = TRUE;
+#endif
} else if (strcmp (argv [i], "--ncompile") == 0) {
if (i + 1 >= argc){
fprintf (stderr, "error: --ncompile requires an argument\n");
action = DO_COMPILE;
} else if (strncmp (argv [i], "--runtime=", 10) == 0) {
forced_version = &argv [i][10];
+ } else if (strcmp (argv [i], "--jitmap") == 0) {
+ mono_enable_jit_map ();
} else if (strcmp (argv [i], "--profile") == 0) {
enable_profile = TRUE;
profile_options = NULL;
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);
return 1;
}
} else if (strcmp (argv [i], "--desktop") == 0) {
-#if defined (HAVE_BOEHM_GC)
- GC_dont_expand = 1;
-#endif
+ mono_gc_set_desktop_mode ();
/* Put desktop-specific optimizations here */
} else if (strcmp (argv [i], "--server") == 0){
/* Put server-specific optimizations here */
#ifdef MONO_JIT_INFO_TABLE_TEST
} else if (strcmp (argv [i], "--test-jit-info-table") == 0) {
test_jit_info_table = TRUE;
+#endif
+ } else if (strcmp (argv [i], "--llvm") == 0) {
+#ifndef MONO_ARCH_LLVM_SUPPORTED
+ fprintf (stderr, "Mono Warning: --llvm not supported on this platform.\n");
+#else
+ mono_use_llvm = TRUE;
+#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]);
#endif
} else {
fprintf (stderr, "Unknown command line option: '%s'\n", argv [i]);
}
}
+#ifdef __native_client_codegen__
+ if (getenv ("MONO_NACL_ALIGN_MASK_OFF"))
+ {
+ nacl_align_byte = -1; /* 0xff */
+ }
+#endif
+
if (!argv [i]) {
mini_usage ();
return 1;
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.\n");
+ 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;
#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
+
+#ifdef HOST_WIN32
+ if (mixed_mode)
+ mono_load_coree (argv [i]);
+#endif
+
mono_set_defaults (mini_verbose, opt);
- mono_setup_vtable_in_class_init = FALSE;
domain = mini_init (argv [i], forced_version);
if (agents) {
exit (1);
}
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
/* Detach console when executing IMAGE_SUBSYSTEM_WINDOWS_GUI on win32 */
if (!enable_debugging && !mono_compile_aot && ((MonoCLIImageInfo*)(mono_assembly_get_image (assembly)->image_info))->cli_header.nt.pe_subsys_required == IMAGE_SUBSYSTEM_WINDOWS_GUI)
FreeConsole ();
* 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.
+ * Testcase: test/main-returns-background-abort-resetabort.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
* 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 ().
+ *
+ * This used to be an amd64 only crash, but it looks like now most glibc targets do unwinding
+ * that requires reading the target code.
*/
-#ifdef __x86_64__
+#ifdef __linux__
mono_dont_free_global_codeman = TRUE;
#endif
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
return 3;
}
+#ifndef DISABLE_JIT
if (action == DO_DRAW) {
int part = 0;
cfg = mini_method_compile (method, opt, mono_get_root_domain (), FALSE, FALSE, 0);
mono_destroy_compile (cfg);
}
+#endif
mini_cleanup (domain);
return 0;