diff --git a/src/coreclr/vm/ClrEtwAll.man b/src/coreclr/vm/ClrEtwAll.man
index 761d650be7e51d..12841164e9daf9 100644
--- a/src/coreclr/vm/ClrEtwAll.man
+++ b/src/coreclr/vm/ClrEtwAll.man
@@ -611,6 +611,7 @@
+
@@ -4309,6 +4310,7 @@
+
@@ -8678,6 +8680,7 @@
+
@@ -8808,6 +8811,7 @@
+
diff --git a/src/mono/mono/metadata/image-internals.h b/src/mono/mono/metadata/image-internals.h
index a424c125987baf..2caaebb2b768d7 100644
--- a/src/mono/mono/metadata/image-internals.h
+++ b/src/mono/mono/metadata/image-internals.h
@@ -10,8 +10,8 @@
#include
typedef struct {
- int dont_care_about_cli : 1;
- int dont_care_about_pecoff : 1;
+ gboolean dont_care_about_cli : 1;
+ gboolean dont_care_about_pecoff : 1;
} MonoImageLoadOptions;
typedef struct {
diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c
index a4b1e021ad2ba8..5fb5076a9f1064 100644
--- a/src/mono/mono/mini/aot-compiler.c
+++ b/src/mono/mono/mini/aot-compiler.c
@@ -13314,25 +13314,25 @@ add_mibc_group_method_methods (MonoAotCompile *acfg, MonoMethod *mibcGroupMethod
int count = 0;
MibcGroupMethodEntryState state = FIND_METHOD_TYPE_ENTRY_START;
- uint8_t *cur = (uint8_t*)mibcGroupMethodHeader->code;
- uint8_t *end = (uint8_t*)mibcGroupMethodHeader->code + mibcGroupMethodHeader->code_size;
+ const unsigned char *cur = mibcGroupMethodHeader->code;
+ const unsigned char *end = mibcGroupMethodHeader->code + mibcGroupMethodHeader->code_size;
while (cur < end) {
MonoOpcodeEnum il_op;
- const unsigned char *opcodeIp = (unsigned char*)cur;
- const unsigned char *opcodeEnd = (unsigned char*)end;
- cur += mono_opcode_value_and_size (&opcodeIp, opcodeEnd, &il_op);
+ const int op_size = mono_opcode_value_and_size (&cur, end, &il_op);
if (state == FIND_METHOD_TYPE_ENTRY_END) {
if (il_op == MONO_CEE_POP)
state = FIND_METHOD_TYPE_ENTRY_START;
+ cur += op_size;
continue;
}
g_assert (il_op == MONO_CEE_LDTOKEN);
state = FIND_METHOD_TYPE_ENTRY_END;
- g_assert (opcodeIp + 4 < opcodeEnd);
- guint32 mibcGroupMethodEntryToken = read32 (opcodeIp + 1);
+ g_assert (cur + 4 < end); // Assert that there is atleast a 32 bit token before the end
+ guint32 mibcGroupMethodEntryToken = read32 (cur + 1);
g_assertf ((mono_metadata_token_table (mibcGroupMethodEntryToken) == MONO_TABLE_MEMBERREF || mono_metadata_token_table (mibcGroupMethodEntryToken) == MONO_TABLE_METHODSPEC), "token %x is not MemberRef or MethodSpec.\n", mibcGroupMethodEntryToken);
+ cur += op_size;
MonoMethod *methodEntry = mono_get_method_checked (image, mibcGroupMethodEntryToken, mibcModuleClass, context, error);
mono_error_assert_ok (error);
@@ -13350,6 +13350,109 @@ add_mibc_group_method_methods (MonoAotCompile *acfg, MonoMethod *mibcGroupMethod
return count;
}
+typedef enum {
+ PARSING_MIBC_CONFIG_NONE,
+ PARSING_MIBC_CONFIG_RUNTIME_FIELD,
+} MibcConfigParserState;
+
+//---------------------------------------------------------------------------------------
+//
+// compatible_mibc_profile_config is responsible for ensuring that the .mibc profile
+// used is compatible with Mono. An incompatible .mibc profile contains types that
+// cannot be found on Mono, exemplified by a .mibc generated from a .nettrace collected
+// from a CoreCLR based app, as it will contain Canon types not found on Mono. If the
+// MibcConfig can be found and the associated runtime is not Mono, return false. If there
+// is no MibcConfig, consider the .mibc having been generated prior to the introduction of
+// the MibcConfig and permit it.
+//
+// Sample MibcConfig format
+//
+// Method 'MibcConfig' (#1443) (0x06000001)
+// {
+// // Code size 49 (0x31)
+// .maxstack 8
+// IL_0000: ldstr 0x70000001 // FormatVersion
+// IL_0005: ldstr 0x7000001D // 1.0
+// IL_000a: pop
+// IL_000b: pop
+// IL_000c: ldstr 0x70000025 // Os
+// IL_0011: ldstr 0x7000002B // macOS
+// IL_0016: pop
+// IL_0017: pop
+// IL_0018: ldstr 0x70000037 // Arch
+// IL_001d: ldstr 0x70000041 // arm64
+// IL_0022: pop
+// IL_0023: pop
+// IL_0024: ldstr 0x7000004D // Runtime
+// IL_0029: ldstr 0x7000005D // Mono (or 4)
+// IL_002e: pop
+// IL_002f: pop
+// IL_0030: ret
+// }
+//
+// Arguments:
+// * image - the MonoImage corresponding to the .mibc
+// * mibcModuleClass - the MonoClass containing the MibcConfig
+//
+// Return Value:
+// gboolean pertaining to the compatibility of the provided mibc with mono runtime
+//
+
+static gboolean
+compatible_mibc_profile_config (MonoImage *image, MonoClass *mibcModuleClass)
+{
+ ERROR_DECL (error);
+
+ MonoMethod *mibcConfig = mono_class_get_method_from_name_checked (mibcModuleClass, "MibcConfig", 0, 0, error);
+ mono_error_assert_ok (error);
+
+ // If there is no MibcConfig, assume it was a .mibc generated prior to MibcConfig addition
+ if (!mibcConfig)
+ return TRUE;
+
+ MonoMethodHeader *mibcConfigHeader = mono_method_get_header_internal (mibcConfig, error);
+ mono_error_assert_ok (error);
+
+ gboolean isConfigCompatible = FALSE;
+ MibcConfigParserState state = PARSING_MIBC_CONFIG_NONE;
+ const unsigned char *cur = mibcConfigHeader->code;
+ const unsigned char *end = mibcConfigHeader->code + mibcConfigHeader->code_size;
+ while (cur < end && !isConfigCompatible) {
+ MonoOpcodeEnum il_op;
+ const int op_size = mono_opcode_value_and_size (&cur, end, &il_op);
+
+ // MibcConfig ends with a Ret
+ if (il_op == MONO_CEE_RET)
+ break;
+
+ // we only care about args of ldstr, which are 32bits/4bytes
+ // ldstr arg is cur + 1
+ if (il_op != MONO_CEE_LDSTR) {
+ cur += op_size;
+ continue;
+ }
+
+ g_assert (cur + 4 < end); // Assert that there is atleast a 32 bit token before the end
+ guint32 token = read32 (cur + 1);
+ cur += op_size;
+
+ char *value = mono_ldstr_utf8 (image, mono_metadata_token_index (token), error);
+ mono_error_assert_ok (error);
+
+ if (state == PARSING_MIBC_CONFIG_RUNTIME_FIELD)
+ isConfigCompatible = !strcmp(value, "Mono") || !strcmp(value, "4");
+
+ if (!strcmp(value, "Runtime"))
+ state = PARSING_MIBC_CONFIG_RUNTIME_FIELD;
+ else
+ state = PARSING_MIBC_CONFIG_NONE;
+
+ g_free (value);
+ }
+
+ return isConfigCompatible;
+}
+
//---------------------------------------------------------------------------------------
//
// add_mibc_profile_methods is the overarching method that adds methods within a .mibc
@@ -13357,7 +13460,8 @@ add_mibc_group_method_methods (MonoAotCompile *acfg, MonoMethod *mibcGroupMethod
// methods grouped under mibcGroupMethods, which are summarized within the global
// function AssemblyDictionary. This method obtains the AssemblyDictionary and iterates
// over il opcodes and arguments to retrieve mibcGroupMethods and thereafter calls
-// add_mibc_group_method_methods.
+// add_mibc_group_method_methods. A .mibc also may contain a MibcConfig, which we
+// check for compatibility with mono.
//
// Sample AssemblyDictionary format
//
@@ -13389,6 +13493,11 @@ add_mibc_profile_methods (MonoAotCompile *acfg, char *filename)
MonoClass *mibcModuleClass = mono_class_from_name_checked (image, "", "", error);
mono_error_assert_ok (error);
+ if (!compatible_mibc_profile_config (image, mibcModuleClass)) {
+ aot_printf (acfg, "Skipping .mibc profile '%s' as it is not compatible with the mono runtime. The MibcConfig within the .mibc does not record the Runtime flavor 'Mono'.\n", filename);
+ return;
+ }
+
MonoMethod *assemblyDictionary = mono_class_get_method_from_name_checked (mibcModuleClass, "AssemblyDictionary", 0, 0, error);
MonoGenericContext *context = mono_method_get_context (assemblyDictionary);
mono_error_assert_ok (error);
@@ -13397,21 +13506,22 @@ add_mibc_profile_methods (MonoAotCompile *acfg, char *filename)
mono_error_assert_ok (error);
int count = 0;
- uint8_t *cur = (uint8_t*)header->code;
- uint8_t *end = (uint8_t*)header->code + header->code_size;
+ const unsigned char *cur = header->code;
+ const unsigned char *end = header->code + header->code_size;
while (cur < end) {
MonoOpcodeEnum il_op;
- const unsigned char *opcodeIp = (unsigned char*)cur;
- const unsigned char *opcodeEnd = (unsigned char*)end;
- cur += mono_opcode_value_and_size (&opcodeIp, opcodeEnd, &il_op);
- // opcodeIp gets moved to point at end of opcode
- // il opcode arg is opcodeIp + 1
+ const int op_size = mono_opcode_value_and_size (&cur, end, &il_op);
+
// we only care about args of ldtoken's, which are 32bits/4bytes
- if (il_op != MONO_CEE_LDTOKEN)
+ // ldtoken arg is cur + 1
+ if (il_op != MONO_CEE_LDTOKEN) {
+ cur += op_size;
continue;
+ }
- g_assert (opcodeIp + 4 < opcodeEnd);
- guint32 token = read32 (opcodeIp + 1);
+ g_assert (cur + 4 < end); // Assert that there is atleast a 32 bit token before the end
+ guint32 token = read32 (cur + 1);
+ cur += op_size;
MonoMethod *mibcGroupMethod = mono_get_method_checked (image, token, mibcModuleClass, context, error);
mono_error_assert_ok (error);