}
}
+static gboolean
+check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, char **out_msg)
+{
+ char *build_info;
+ char *msg = NULL;
+ gboolean usable = TRUE;
+ gboolean full_aot;
+ guint8 *blob;
+
+ if (strcmp (assembly->image->guid, info->assembly_guid)) {
+ msg = g_strdup_printf ("doesn't match assembly");
+ usable = FALSE;
+ }
+
+ build_info = mono_get_runtime_build_info ();
+ if (strlen (info->runtime_version) > 0 && strcmp (info->runtime_version, build_info)) {
+ msg = g_strdup_printf ("compiled against runtime version '%s' while this runtime has version '%s'", info->runtime_version, build_info);
+ usable = FALSE;
+ }
+ g_free (build_info);
+
+ full_aot = info->flags & MONO_AOT_FILE_FLAG_FULL_AOT;
+
+ if (mono_aot_only && !full_aot) {
+ msg = g_strdup_printf ("not compiled with --aot=full");
+ usable = FALSE;
+ }
+ if (!mono_aot_only && full_aot) {
+ msg = g_strdup_printf ("compiled with --aot=full");
+ usable = FALSE;
+ }
+#ifdef TARGET_ARM
+ /* mono_arch_find_imt_method () requires this */
+ if ((info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
+ msg = g_strdup_printf ("compiled against LLVM");
+ usable = FALSE;
+ }
+#endif
+ if (mini_get_debug_options ()->mdb_optimizations && !(info->flags & MONO_AOT_FILE_FLAG_DEBUG) && !full_aot) {
+ msg = g_strdup_printf ("not compiled for debugging");
+ usable = FALSE;
+ }
+
+ blob = info->blob;
+
+ if (info->gc_name_index != -1) {
+ char *gc_name = (char*)&blob [info->gc_name_index];
+ const char *current_gc_name = mono_gc_get_gc_name ();
+
+ if (strcmp (current_gc_name, gc_name) != 0) {
+ msg = g_strdup_printf ("compiled against GC %s, while the current runtime uses GC %s.\n", gc_name, current_gc_name);
+ usable = FALSE;
+ }
+ }
+
+ *out_msg = msg;
+ return usable;
+}
+
static void
load_aot_module (MonoAssembly *assembly, gpointer user_data)
{
MonoAotModule *amodule;
MonoDl *sofile;
gboolean usable = TRUE;
- char *saved_guid = NULL;
- char *aot_version = NULL;
- char *runtime_version, *build_info;
- char *opt_flags = NULL;
+ char *version_symbol = NULL;
+ char *msg = NULL;
gpointer *globals;
- gboolean full_aot = FALSE;
- MonoAotFileInfo *file_info = NULL;
- int i;
+ MonoAotFileInfo *info = NULL;
+ int i, version;
guint8 *blob;
+ gboolean do_load_image = TRUE;
if (mono_compile_aot)
return;
return;
}
- find_symbol (sofile, globals, "mono_assembly_guid", (gpointer *) &saved_guid);
- find_symbol (sofile, globals, "mono_aot_version", (gpointer *) &aot_version);
- find_symbol (sofile, globals, "mono_aot_opt_flags", (gpointer *)&opt_flags);
- find_symbol (sofile, globals, "mono_runtime_version", (gpointer *)&runtime_version);
+ find_symbol (sofile, globals, "mono_aot_version", (gpointer *) &version_symbol);
+ find_symbol (sofile, globals, "mono_aot_file_info", (gpointer*)&info);
- if (!aot_version || strcmp (aot_version, MONO_AOT_FILE_VERSION)) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s has wrong file format version (expected %s got %s)\n", aot_name, MONO_AOT_FILE_VERSION, aot_version);
- usable = FALSE;
- }
- else {
- if (!saved_guid || strcmp (assembly->image->guid, saved_guid)) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is out of date.\n", aot_name);
- usable = FALSE;
- }
- }
-
- build_info = mono_get_runtime_build_info ();
- if (!runtime_version || ((strlen (runtime_version) > 0 && strcmp (runtime_version, build_info)))) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is compiled against runtime version '%s' while this runtime has version '%s'.\n", aot_name, runtime_version, build_info);
- usable = FALSE;
- }
- g_free (build_info);
-
- find_symbol (sofile, globals, "mono_aot_file_info", (gpointer*)&file_info);
- g_assert (file_info);
-
- full_aot = ((MonoAotFileInfo*)file_info)->flags & MONO_AOT_FILE_FLAG_FULL_AOT;
-
- if (mono_aot_only && !full_aot) {
- fprintf (stderr, "Can't use AOT image '%s' in aot-only mode because it is not compiled with --aot=full.\n", aot_name);
- exit (1);
- }
- if (!mono_aot_only && full_aot) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is compiled with --aot=full.\n", aot_name);
- usable = FALSE;
- }
-
- /* This is no longer needed, LLVM and non-LLVM runtimes should be compatible.
- if ((((MonoAotFileInfo*)file_info)->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is compiled with LLVM.\n", aot_name);
- usable = FALSE;
+ if (version_symbol) {
+ /* Old file format */
+ version = atoi (version_symbol);
+ } else {
+ g_assert (info);
+ version = info->version;
}
- */
- if (mini_get_debug_options ()->mdb_optimizations && !(file_info->flags & MONO_AOT_FILE_FLAG_DEBUG) && !full_aot) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is not compiled for debugging.\n", aot_name);
+ if (version != MONO_AOT_FILE_VERSION) {
+ msg = g_strdup_printf ("wrong file format version (expected %d got %d)", MONO_AOT_FILE_VERSION, version);
usable = FALSE;
- }
-
- find_symbol (sofile, globals, "blob", (gpointer*)&blob);
-
- if (usable && ((MonoAotFileInfo*)file_info)->gc_name_index != -1) {
- char *gc_name = (char*)&blob [((MonoAotFileInfo*)file_info)->gc_name_index];
- const char *current_gc_name = mono_gc_get_gc_name ();
-
- if (strcmp (current_gc_name, gc_name) != 0) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is compiled against GC %s, while the current runtime uses GC %s.\n", aot_name, gc_name, current_gc_name);
- usable = FALSE;
- }
+ } else {
+ usable = check_usable (assembly, info, &msg);
}
if (!usable) {
if (mono_aot_only) {
- fprintf (stderr, "Failed to load AOT module '%s' while running in aot-only mode.\n", aot_name);
+ fprintf (stderr, "Failed to load AOT module '%s' while running in aot-only mode: %s.\n", aot_name, msg);
exit (1);
} else {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is unusable.\n", aot_name);
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is unusable: %s.\n", aot_name, msg);
}
+ g_free (msg);
g_free (aot_name);
if (sofile)
mono_dl_close (sofile);
return;
}
+ blob = info->blob;
+
amodule = g_new0 (MonoAotModule, 1);
amodule->aot_name = aot_name;
amodule->assembly = assembly;
- memcpy (&amodule->info, file_info, sizeof (*file_info));
+ memcpy (&amodule->info, info, sizeof (*info));
amodule->got = amodule->info.got;
amodule->got [0] = assembly->image;
guint32 table_len, i;
char *table = NULL;
- find_symbol (sofile, globals, "mono_image_table", (gpointer *)&table);
+ table = info->image_table;
g_assert (table);
table_len = *(guint32*)table;
}
}
- /* Read method and method_info tables */
- find_symbol (sofile, globals, "code_offsets", (gpointer*)&amodule->code_offsets);
- amodule->code = amodule->info.methods;
+ amodule->code_offsets = info->code_offsets;
+ amodule->code = info->methods;
#ifdef TARGET_ARM
/* Mask out thumb interop bit */
amodule->code = (void*)((mgreg_t)amodule->code & ~1);
#endif
- find_symbol (sofile, globals, "methods_end", (gpointer*)&amodule->code_end);
- find_symbol (sofile, globals, "method_info_offsets", (gpointer*)&amodule->method_info_offsets);
- find_symbol (sofile, globals, "ex_info_offsets", (gpointer*)&amodule->ex_info_offsets);
- find_symbol (sofile, globals, "class_info_offsets", (gpointer*)&amodule->class_info_offsets);
- find_symbol (sofile, globals, "class_name_table", (gpointer *)&amodule->class_name_table);
- find_symbol (sofile, globals, "extra_method_table", (gpointer *)&amodule->extra_method_table);
- find_symbol (sofile, globals, "extra_method_info_offsets", (gpointer *)&amodule->extra_method_info_offsets);
- find_symbol (sofile, globals, "got_info_offsets", (gpointer*)&amodule->got_info_offsets);
- find_symbol (sofile, globals, "specific_trampolines", (gpointer*)&(amodule->trampolines [MONO_AOT_TRAMP_SPECIFIC]));
- find_symbol (sofile, globals, "static_rgctx_trampolines", (gpointer*)&(amodule->trampolines [MONO_AOT_TRAMP_STATIC_RGCTX]));
- find_symbol (sofile, globals, "imt_thunks", (gpointer*)&(amodule->trampolines [MONO_AOT_TRAMP_IMT_THUNK]));
- find_symbol (sofile, globals, "unwind_info", (gpointer)&amodule->unwind_info);
- find_symbol (sofile, globals, "mem_end", (gpointer*)&amodule->mem_end);
- find_symbol (sofile, globals, "thumb_end", (gpointer*)&amodule->thumb_end);
-
+ amodule->code_end = info->methods_end;
+ amodule->method_info_offsets = info->method_info_offsets;
+ amodule->ex_info_offsets = info->ex_info_offsets;
+ amodule->class_info_offsets = info->class_info_offsets;
+ amodule->class_name_table = info->class_name_table;
+ amodule->extra_method_table = info->extra_method_table;
+ amodule->extra_method_info_offsets = info->extra_method_info_offsets;
+ amodule->got_info_offsets = info->got_info_offsets;
+ amodule->unwind_info = info->unwind_info;
+ amodule->mem_end = info->mem_end;
amodule->mem_begin = amodule->code;
-
- find_symbol (sofile, globals, "plt", (gpointer*)&amodule->plt);
- find_symbol (sofile, globals, "plt_end", (gpointer*)&amodule->plt_end);
-
- amodule->mono_eh_frame = amodule->info.mono_eh_frame;
+ amodule->plt = info->plt;
+ amodule->plt_end = info->plt_end;
+ amodule->mono_eh_frame = info->mono_eh_frame;
+ amodule->trampolines [MONO_AOT_TRAMP_SPECIFIC] = info->specific_trampolines;
+ amodule->trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = info->static_rgctx_trampolines;
+ amodule->trampolines [MONO_AOT_TRAMP_IMT_THUNK] = info->imt_thunks;
+ amodule->thumb_end = info->thumb_end;
if (make_unreadable) {
#ifndef TARGET_WIN32
* non-lazily, since we can't handle out-of-date errors later.
* The cached class info also depends on the exact assemblies.
*/
- for (i = 0; i < amodule->image_table_len; ++i)
- load_image (amodule, i, FALSE);
+#if defined(__native_client__)
+ /* TODO: Don't 'load_image' on mscorlib due to a */
+ /* recursive loading problem. This should be */
+ /* removed if mscorlib is loaded from disk. */
+ if (strncmp(assembly->aname.name, "mscorlib", 8)) {
+ do_load_image = TRUE;
+ } else {
+ do_load_image = FALSE;
+ }
+#endif
+ if (do_load_image) {
+ for (i = 0; i < amodule->image_table_len; ++i)
+ load_image (amodule, i, FALSE);
+ }
if (amodule->out_of_date) {
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT Module %s is unusable because a dependency is out-of-date.\n", assembly->image->name);
/* Compute a sorted table mapping code offsets to method indexes. */
if (!amodule->sorted_code_offsets) {
-
code_offsets = g_new0 (gint32, nmethods * 2);
offsets_len = 0;
for (i = 0; i < nmethods; ++i) {
#ifdef TARGET_ARM
if (amodule->thumb_end && code < amodule->thumb_end) {
- int s, j1, j2, imm10, imm11, i1, i2, imm32;
- guint8 *bl, *base;
- guint16 t1, t2;
-
- /*
- * This is code generated by LLVM:
- * bl <plt entry stub>
- * ...
- * <plt entry stub>:
- * bx pc
- * nop
- * <real plt entry>
- */
-
- /* code should be right after a BL */
- code = (guint8*)((mgreg_t)code & ~1);
- base = (guint8*)((mgreg_t)code & ~3);
- bl = code - 4;
- t1 = ((guint16*)bl) [0];
- t2 = ((guint16*)bl) [1];
-
- g_assert ((t1 >> 11) == 0b11110);
-
- s = (t1 >> 10) & 0x1;
- imm10 = (t1 >> 0) & 0x3ff;
- j1 = (t2 >> 13) & 0x1;
- j2 = (t2 >> 11) & 0x1;
- imm11 = t2 & 0x7ff;
-
- i1 = (s ^ j1) ? 0 : 1;
- i2 = (s ^ j2) ? 0 : 1;
-
- imm32 = (imm11 << 1) | (imm10 << 12) | (i2 << 22) | (i1 << 23);
- // FIXME:
- g_assert (s == 0);
-
- target = code + imm32;
-
- /* target now points to the thumb->arm stub */
- /* bx pc */
- g_assert (((guint16*)target) [0] == 0x4778);
- /* nop */
- g_assert (((guint16*)target) [1] == 0x46c0);
-
- target += 4;
-
- return target;
+ return mono_arm_get_thumb_plt_entry (code);
}
#endif