Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/coreclr/vm/ClrEtwAll.man
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@
<bitMap name="RuntimeSkuMap">
<map value="0x1" message="$(string.RuntimePublisher.RuntimeSku.DesktopCLRMapMessage)"/>
<map value="0x2" message="$(string.RuntimePublisher.RuntimeSku.CoreCLRMapMessage)"/>
<map value="0x4" message="$(string.RuntimePublisher.RuntimeSku.MonoMapMessage)"/>
</bitMap>
<bitMap name="ExceptionThrownFlagsMap">
<map value="0x1" message="$(string.RuntimePublisher.ExceptionThrown.HasInnerExceptionMapMessage)"/>
Expand Down Expand Up @@ -4309,6 +4310,7 @@
<bitMap name="RuntimeSkuMap">
<map value="0x1" message="$(string.RundownPublisher.RuntimeSku.DesktopCLRMapMessage)"/>
<map value="0x2" message="$(string.RundownPublisher.RuntimeSku.CoreCLRMapMessage)"/>
<map value="0x4" message="$(string.RundownPublisher.RuntimeSku.MonoMapMessage)"/>
</bitMap>
<bitMap name="StartupFlagsMap">
<map value="0x000001" message="$(string.RundownPublisher.Startup.CONCURRENT_GCMapMessage)"/>
Expand Down Expand Up @@ -8678,6 +8680,7 @@
<string id="RuntimePublisher.StartupMode.OtherMapMessage" value="Other" />
<string id="RuntimePublisher.RuntimeSku.DesktopCLRMapMessage" value="DesktopClr" />
<string id="RuntimePublisher.RuntimeSku.CoreCLRMapMessage" value="CoreClr" />
<string id="RuntimePublisher.RuntimeSku.MonoMapMessage" value="Mono" />
<string id="RuntimePublisher.ExceptionThrown.HasInnerExceptionMapMessage" value="HasInnerException" />
<string id="RuntimePublisher.ExceptionThrown.NestedMapMessage" value="Nested" />
<string id="RuntimePublisher.ExceptionThrown.ReThrownMapMessage" value="ReThrown" />
Expand Down Expand Up @@ -8808,6 +8811,7 @@
<string id="RundownPublisher.StartupMode.OtherMapMessage" value="Other" />
<string id="RundownPublisher.RuntimeSku.DesktopCLRMapMessage" value="DesktopClr" />
<string id="RundownPublisher.RuntimeSku.CoreCLRMapMessage" value="CoreClr" />
<string id="RundownPublisher.RuntimeSku.MonoMapMessage" value="Mono" />
<string id="RundownPublisher.Startup.CONCURRENT_GCMapMessage" value="CONCURRENT_GC" />
<string id="RundownPublisher.Startup.LOADER_OPTIMIZATION_SINGLE_DOMAINMapMessage" value="LOADER_OPTIMIZATION_SINGLE_DOMAIN" />
<string id="RundownPublisher.Startup.LOADER_OPTIMIZATION_MULTI_DOMAINMapMessage" value="LOADER_OPTIMIZATION_MULTI_DOMAIN" />
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/metadata/image-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include <mono/metadata/loader-internals.h>

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 {
Expand Down
109 changes: 108 additions & 1 deletion src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -13350,14 +13350,116 @@ 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;
uint8_t *cur = (uint8_t*)mibcConfigHeader->code;
uint8_t *end = (uint8_t*)mibcConfigHeader->code + mibcConfigHeader->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
// we only care about args of ldstr, which are 32bits/4bytes
if (il_op == MONO_CEE_POP)
continue;

if (il_op == MONO_CEE_RET)
break;

g_assert (opcodeIp + 4 < opcodeEnd);
guint32 token = read32 (opcodeIp + 1);

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
// profile file to be compiled ahead of time. .mibc is a portable executable with
// 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
//
Expand Down Expand Up @@ -13389,6 +13491,11 @@ add_mibc_profile_methods (MonoAotCompile *acfg, char *filename)
MonoClass *mibcModuleClass = mono_class_from_name_checked (image, "", "<Module>", 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);
Expand Down