img_writer_emit_string (acfg->w, value);
}
+static void
+emit_local_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
+{
+ img_writer_emit_section_change (acfg->w, RODATA_SECT, 1);
+ img_writer_emit_label (acfg->w, name);
+ img_writer_emit_string (acfg->w, value);
+}
+
static G_GNUC_UNUSED void
emit_uleb128 (MonoAotCompile *acfg, guint32 value)
{
sprintf (symbol, "plt");
emit_section_change (acfg, ".text", 0);
- emit_global (acfg, symbol, TRUE);
emit_alignment (acfg, 16);
emit_label (acfg, symbol);
emit_label (acfg, acfg->plt_symbol);
emit_symbol_size (acfg, acfg->plt_symbol, ".");
sprintf (symbol, "plt_end");
- emit_global (acfg, symbol, TRUE);
emit_label (acfg, symbol);
g_hash_table_destroy (cache);
g_assert_not_reached ();
}
- emit_global (acfg, symbol, TRUE);
emit_alignment (acfg, AOT_FUNC_ALIGNMENT);
emit_label (acfg, symbol);
sprintf (symbol, "methods_end");
emit_section_change (acfg, ".text", 0);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
sprintf (symbol, "code_offsets");
emit_section_change (acfg, RODATA_SECT, 1);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
sprintf (symbol, "method_info_offsets");
emit_section_change (acfg, RODATA_SECT, 1);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
/* Emit the table */
sprintf (symbol, "extra_method_table");
emit_section_change (acfg, RODATA_SECT, 0);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
*/
sprintf (symbol, "extra_method_info_offsets");
emit_section_change (acfg, RODATA_SECT, 0);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
sprintf (symbol, "ex_info_offsets");
emit_section_change (acfg, RODATA_SECT, 1);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
emit_section_change (acfg, RODATA_SECT, 1);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
- emit_global (acfg, symbol, FALSE);
for (i = 0; i < acfg->unwind_ops->len; ++i) {
guint32 index = GPOINTER_TO_UINT (g_ptr_array_index (acfg->unwind_ops, i));
sprintf (symbol, "class_info_offsets");
emit_section_change (acfg, RODATA_SECT, 1);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
/* Emit the table */
sprintf (symbol, "class_name_table");
emit_section_change (acfg, RODATA_SECT, 0);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
* So we emit it at once, and reference its elements by an index.
*/
- sprintf (symbol, "mono_image_table");
+ sprintf (symbol, "image_table");
emit_section_change (acfg, RODATA_SECT, 1);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
/* Emit got_info_offsets table */
sprintf (symbol, "got_info_offsets");
emit_section_change (acfg, RODATA_SECT, 1);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
{
char *build_info;
- emit_string_symbol (acfg, "mono_assembly_guid" , acfg->image->guid);
-
- emit_string_symbol (acfg, "mono_aot_version", MONO_AOT_FILE_VERSION);
+ emit_local_string_symbol (acfg, "assembly_guid" , acfg->image->guid);
if (acfg->aot_opts.bind_to_runtime_version) {
build_info = mono_get_runtime_build_info ();
- emit_string_symbol (acfg, "mono_runtime_version", build_info);
+ emit_local_string_symbol (acfg, "runtime_version", build_info);
g_free (build_info);
} else {
- emit_string_symbol (acfg, "mono_runtime_version", "");
+ emit_local_string_symbol (acfg, "runtime_version", "");
}
/*
sprintf (symbol, "mem_end");
emit_section_change (acfg, ".text", 1);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
}
/* The data emitted here must match MonoAotFileInfo. */
+ emit_int32 (acfg, MONO_AOT_FILE_VERSION);
+ emit_int32 (acfg, 0);
+
/*
- * We emit these as data to avoid making these symbols global, which leads to
- * various problems
+ * We emit pointers to our data structures instead of emitting global symbols which
+ * point to them, to reduce the number of globals, and because using globals leads to
+ * various problems (i.e. arm/thumb).
*/
emit_pointer (acfg, acfg->got_symbol);
emit_pointer (acfg, "methods");
} else {
emit_pointer (acfg, NULL);
}
+ emit_pointer (acfg, "blob");
+ emit_pointer (acfg, "class_name_table");
+ emit_pointer (acfg, "class_info_offsets");
+ emit_pointer (acfg, "method_info_offsets");
+ emit_pointer (acfg, "ex_info_offsets");
+ emit_pointer (acfg, "code_offsets");
+ emit_pointer (acfg, "extra_method_info_offsets");
+ emit_pointer (acfg, "extra_method_table");
+ emit_pointer (acfg, "got_info_offsets");
+ emit_pointer (acfg, "methods_end");
+ emit_pointer (acfg, "unwind_info");
+ emit_pointer (acfg, "mem_end");
+ emit_pointer (acfg, "image_table");
+ emit_pointer (acfg, "plt");
+ emit_pointer (acfg, "plt_end");
+ emit_pointer (acfg, "assembly_guid");
+ emit_pointer (acfg, "runtime_version");
+ if (acfg->num_trampoline_got_entries) {
+ emit_pointer (acfg, "specific_trampolines");
+ emit_pointer (acfg, "static_rgctx_trampolines");
+ emit_pointer (acfg, "imt_thunks");
+ } else {
+ emit_pointer (acfg, NULL);
+ emit_pointer (acfg, NULL);
+ emit_pointer (acfg, NULL);
+ }
+ if (acfg->thumb_mixed) {
+ emit_pointer (acfg, "thumb_end");
+ } else {
+ emit_pointer (acfg, NULL);
+ }
emit_int32 (acfg, acfg->plt_got_offset_base);
emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
sprintf (symbol, "blob");
emit_section_change (acfg, RODATA_SECT, 1);
- emit_global (acfg, symbol, FALSE);
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
}
}
+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;
if (mono_compile_aot)
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);
-
- if (!aot_version || strcmp (aot_version, MONO_AOT_FILE_VERSION)) {
- msg = g_strdup_printf ("wrong file format version (expected %s got %s)", MONO_AOT_FILE_VERSION, aot_version);
- usable = FALSE;
- }
- else {
- if (!saved_guid || strcmp (assembly->image->guid, saved_guid)) {
- msg = g_strdup_printf ("doesn't match assembly");
- usable = FALSE;
- }
- }
-
- build_info = mono_get_runtime_build_info ();
- if (!runtime_version || ((strlen (runtime_version) > 0 && strcmp (runtime_version, build_info)))) {
- msg = g_strdup_printf ("compiled against runtime version '%s' while this runtime has version '%s'", 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) {
- msg = g_strdup_printf ("compiled with --aot=full");
- usable = FALSE;
- }
+ find_symbol (sofile, globals, "mono_aot_version", (gpointer *) &version_symbol);
+ find_symbol (sofile, globals, "mono_aot_file_info", (gpointer*)&info);
-#ifdef TARGET_ARM
- /* mono_arch_find_imt_method () requires this */
- if ((((MonoAotFileInfo*)file_info)->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
- msg = g_strdup_printf ("compiled against LLVM");
- usable = FALSE;
+ if (version_symbol) {
+ /* Old file format */
+ version = atoi (version_symbol);
+ } else {
+ g_assert (info);
+ version = info->version;
}
-#endif
- if (mini_get_debug_options ()->mdb_optimizations && !(file_info->flags & MONO_AOT_FILE_FLAG_DEBUG) && !full_aot) {
- msg = g_strdup_printf ("not compiled for debugging");
+ 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) {
- msg = g_strdup_printf ("compiled against GC %s, while the current runtime uses GC %s.\n", gc_name, current_gc_name);
- usable = FALSE;
- }
+ } else {
+ usable = check_usable (assembly, info, &msg);
}
if (!usable) {
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
#endif
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION "71"
+#define MONO_AOT_FILE_VERSION 72
//TODO: This is x86/amd64 specific.
#define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
/* This structure is stored in the AOT file */
typedef struct MonoAotFileInfo
{
+ /* The version number of the AOT file format, should match MONO_AOT_FILE_VERSION */
+ guint32 version;
+ /* For alignment */
+ guint32 dummy;
+
/* All the pointers should be at the start to avoid alignment problems */
+
+ /* Mono's Global Offset Table */
gpointer got;
+ /* Compiled code for methods */
gpointer methods;
+ /* Mono EH Frame created by llc when using LLVM */
gpointer mono_eh_frame;
+ /* Data blob */
+ gpointer blob;
+ gpointer class_name_table;
+ gpointer class_info_offsets;
+ gpointer method_info_offsets;
+ gpointer ex_info_offsets;
+ gpointer code_offsets;
+ gpointer extra_method_info_offsets;
+ gpointer extra_method_table;
+ gpointer got_info_offsets;
+ gpointer methods_end;
+ gpointer unwind_info;
+ gpointer mem_end;
+ gpointer image_table;
+ /* Start of Mono's Program Linkage Table */
+ gpointer plt;
+ /* End of Mono's Program Linkage Table */
+ gpointer plt_end;
+ /* The GUID of the assembly which the AOT image was generated from */
+ gpointer assembly_guid;
+ gpointer runtime_version;
+ gpointer specific_trampolines;
+ gpointer static_rgctx_trampolines;
+ gpointer imt_thunks;
+ gpointer thumb_end;
guint32 plt_got_offset_base;
guint32 got_size;