From: Tomáš Rylek Date: Wed, 4 Mar 2020 14:28:31 +0000 (+0100) Subject: Initial runtime changes for composite support (#32500) X-Git-Tag: submit/tizen/20210909.063632~9357 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f0f33999dea0c1188b30c5e2705d3d3217aeae67;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Initial runtime changes for composite support (#32500) This change changes CoreCLR runtime to support running composite R2R apps with standalone MSIL produced by Crossgen2. It introduces the new concept of a NativeImage representing the composite R2R with native executable header and adds basic support for loading these native images upon loading the original MSIL assemblies and for using the R2R code information therein as the native code cache for the component MSIL assemblies. Thanks Tomas --- diff --git a/src/coreclr/src/inc/CrstTypes.def b/src/coreclr/src/inc/CrstTypes.def index 57119c01959..cf53f5bdd24 100644 --- a/src/coreclr/src/inc/CrstTypes.def +++ b/src/coreclr/src/inc/CrstTypes.def @@ -706,3 +706,6 @@ Crst MethodDescBackpatchInfoTracker AcquiredBefore FuncPtrStubs ThreadStore SystemDomain AcquiredAfter ReJITGlobalRequest End + +Crst NativeImageEagerFixups +End diff --git a/src/coreclr/src/inc/crsttypes.h b/src/coreclr/src/inc/crsttypes.h index 79cf46b5445..4bc0665602d 100644 --- a/src/coreclr/src/inc/crsttypes.h +++ b/src/coreclr/src/inc/crsttypes.h @@ -107,68 +107,69 @@ enum CrstType CrstMUThunkHash = 88, CrstNativeBinderInit = 89, CrstNativeImageCache = 90, - CrstNls = 91, - CrstNotifyGdb = 92, - CrstObjectList = 93, - CrstOnEventManager = 94, - CrstPatchEntryPoint = 95, - CrstPEImage = 96, - CrstPEImagePDBStream = 97, - CrstPendingTypeLoadEntry = 98, - CrstPinHandle = 99, - CrstPinnedByrefValidation = 100, - CrstProfilerGCRefDataFreeList = 101, - CrstProfilingAPIStatus = 102, - CrstPublisherCertificate = 103, - CrstRCWCache = 104, - CrstRCWCleanupList = 105, - CrstRCWRefCache = 106, - CrstReadyToRunEntryPointToMethodDescMap = 107, - CrstReDacl = 108, - CrstReflection = 109, - CrstReJITGlobalRequest = 110, - CrstRemoting = 111, - CrstRetThunkCache = 112, - CrstRWLock = 113, - CrstSavedExceptionInfo = 114, - CrstSaveModuleProfileData = 115, - CrstSecurityStackwalkCache = 116, - CrstSharedAssemblyCreate = 117, - CrstSigConvert = 118, - CrstSingleUseLock = 119, - CrstSpecialStatics = 120, - CrstSqmManager = 121, - CrstStackSampler = 122, - CrstStressLog = 123, - CrstStrongName = 124, - CrstStubCache = 125, - CrstStubDispatchCache = 126, - CrstStubUnwindInfoHeapSegments = 127, - CrstSyncBlockCache = 128, - CrstSyncHashLock = 129, - CrstSystemBaseDomain = 130, - CrstSystemDomain = 131, - CrstSystemDomainDelayedUnloadList = 132, - CrstThreadIdDispenser = 133, - CrstThreadpoolEventCache = 134, - CrstThreadpoolTimerQueue = 135, - CrstThreadpoolWaitThreads = 136, - CrstThreadpoolWorker = 137, - CrstThreadStaticDataHashTable = 138, - CrstThreadStore = 139, - CrstTieredCompilation = 140, - CrstTPMethodTable = 141, - CrstTypeEquivalenceMap = 142, - CrstTypeIDMap = 143, - CrstUMEntryThunkCache = 144, - CrstUMThunkHash = 145, - CrstUniqueStack = 146, - CrstUnresolvedClassLock = 147, - CrstUnwindInfoTableLock = 148, - CrstVSDIndirectionCellLock = 149, - CrstWinRTFactoryCache = 150, - CrstWrapperTemplate = 151, - kNumberOfCrstTypes = 152 + CrstNativeImageEagerFixups = 91, + CrstNls = 92, + CrstNotifyGdb = 93, + CrstObjectList = 94, + CrstOnEventManager = 95, + CrstPatchEntryPoint = 96, + CrstPEImage = 97, + CrstPEImagePDBStream = 98, + CrstPendingTypeLoadEntry = 99, + CrstPinHandle = 100, + CrstPinnedByrefValidation = 101, + CrstProfilerGCRefDataFreeList = 102, + CrstProfilingAPIStatus = 103, + CrstPublisherCertificate = 104, + CrstRCWCache = 105, + CrstRCWCleanupList = 106, + CrstRCWRefCache = 107, + CrstReadyToRunEntryPointToMethodDescMap = 108, + CrstReDacl = 109, + CrstReflection = 110, + CrstReJITGlobalRequest = 111, + CrstRemoting = 112, + CrstRetThunkCache = 113, + CrstRWLock = 114, + CrstSavedExceptionInfo = 115, + CrstSaveModuleProfileData = 116, + CrstSecurityStackwalkCache = 117, + CrstSharedAssemblyCreate = 118, + CrstSigConvert = 119, + CrstSingleUseLock = 120, + CrstSpecialStatics = 121, + CrstSqmManager = 122, + CrstStackSampler = 123, + CrstStressLog = 124, + CrstStrongName = 125, + CrstStubCache = 126, + CrstStubDispatchCache = 127, + CrstStubUnwindInfoHeapSegments = 128, + CrstSyncBlockCache = 129, + CrstSyncHashLock = 130, + CrstSystemBaseDomain = 131, + CrstSystemDomain = 132, + CrstSystemDomainDelayedUnloadList = 133, + CrstThreadIdDispenser = 134, + CrstThreadpoolEventCache = 135, + CrstThreadpoolTimerQueue = 136, + CrstThreadpoolWaitThreads = 137, + CrstThreadpoolWorker = 138, + CrstThreadStaticDataHashTable = 139, + CrstThreadStore = 140, + CrstTieredCompilation = 141, + CrstTPMethodTable = 142, + CrstTypeEquivalenceMap = 143, + CrstTypeIDMap = 144, + CrstUMEntryThunkCache = 145, + CrstUMThunkHash = 146, + CrstUniqueStack = 147, + CrstUnresolvedClassLock = 148, + CrstUnwindInfoTableLock = 149, + CrstVSDIndirectionCellLock = 150, + CrstWinRTFactoryCache = 151, + CrstWrapperTemplate = 152, + kNumberOfCrstTypes = 153 }; #endif // __CRST_TYPES_INCLUDED @@ -179,158 +180,159 @@ enum CrstType // An array mapping CrstType to level. int g_rgCrstLevelMap[] = { - 9, // CrstAllowedFiles - 9, // CrstAppDomainCache - 14, // CrstAppDomainHandleTable - 0, // CrstArgBasedStubCache - 0, // CrstAssemblyDependencyGraph - 0, // CrstAssemblyIdentityCache - 0, // CrstAssemblyList - 7, // CrstAssemblyLoader - 3, // CrstAvailableClass - 4, // CrstAvailableParamTypes - 7, // CrstBaseDomain - -1, // CrstCCompRC - 9, // CrstCer - 13, // CrstClassFactInfoHash - 8, // CrstClassInit - -1, // CrstClrNotification - 0, // CrstCLRPrivBinderMaps - 3, // CrstCLRPrivBinderMapsAdd - 6, // CrstCodeFragmentHeap - 10, // CrstCodeVersioning - 0, // CrstCOMCallWrapper - 4, // CrstCOMWrapperCache - 0, // CrstConnectionNameTable - 17, // CrstContexts - 0, // CrstCrstCLRPrivBinderLocalWinMDPath - 7, // CrstCSPCache - 3, // CrstDataTest1 - 0, // CrstDataTest2 - 0, // CrstDbgTransport - 0, // CrstDeadlockDetection - -1, // CrstDebuggerController - 3, // CrstDebuggerFavorLock - 0, // CrstDebuggerHeapExecMemLock - 0, // CrstDebuggerHeapLock - 4, // CrstDebuggerJitInfo - 11, // CrstDebuggerMutex - 0, // CrstDelegateToFPtrHash - 16, // CrstDomainLocalBlock - 0, // CrstDynamicIL - 3, // CrstDynamicMT - 3, // CrstDynLinkZapItems - 7, // CrstEtwTypeLogHash - 18, // CrstEventPipe - 0, // CrstEventStore - 0, // CrstException - 7, // CrstExecuteManLock - 0, // CrstExecuteManRangeLock - 3, // CrstFCall - 7, // CrstFriendAccessCache - 7, // CrstFuncPtrStubs - 5, // CrstFusionAppCtx - 11, // CrstGCCover - 0, // CrstGCMemoryPressure - 13, // CrstGlobalStrLiteralMap - 1, // CrstHandleTable - 0, // CrstHostAssemblyMap - 3, // CrstHostAssemblyMapAdd - 0, // CrstIbcProfile - 9, // CrstIJWFixupData - 0, // CrstIJWHash - 7, // CrstILStubGen - 3, // CrstInlineTrackingMap - 17, // CrstInstMethodHashTable - 0, // CrstInterfaceVTableMap - 18, // CrstInterop - 4, // CrstInteropData - 13, // CrstIOThreadpoolWorker - 0, // CrstIsJMCMethod - 7, // CrstISymUnmanagedReader - 8, // CrstJit - 0, // CrstJitGenericHandleCache - 16, // CrstJitInlineTrackingMap - -1, // CrstJitPerf - 6, // CrstJumpStubCache - 0, // CrstLeafLock - -1, // CrstListLock - 15, // CrstLoaderAllocator - 16, // CrstLoaderAllocatorReferences - 0, // CrstLoaderHeap - 0, // CrstMda - -1, // CrstMetadataTracker - 14, // CrstMethodDescBackpatchInfoTracker - 0, // CrstModIntPairList - 4, // CrstModule - 15, // CrstModuleFixup - 3, // CrstModuleLookupTable - 0, // CrstMulticoreJitHash - 13, // CrstMulticoreJitManager - 0, // CrstMUThunkHash - -1, // CrstNativeBinderInit - -1, // CrstNativeImageCache - 0, // CrstNls - 0, // CrstNotifyGdb - 2, // CrstObjectList - 0, // CrstOnEventManager - 0, // CrstPatchEntryPoint - 4, // CrstPEImage - 0, // CrstPEImagePDBStream - 19, // CrstPendingTypeLoadEntry - 0, // CrstPinHandle - 0, // CrstPinnedByrefValidation - 0, // CrstProfilerGCRefDataFreeList - 0, // CrstProfilingAPIStatus - 0, // CrstPublisherCertificate - 3, // CrstRCWCache - 0, // CrstRCWCleanupList - 3, // CrstRCWRefCache - 4, // CrstReadyToRunEntryPointToMethodDescMap - 0, // CrstReDacl - 9, // CrstReflection - 17, // CrstReJITGlobalRequest - 20, // CrstRemoting - 3, // CrstRetThunkCache - 0, // CrstRWLock - 3, // CrstSavedExceptionInfo - 0, // CrstSaveModuleProfileData - 0, // CrstSecurityStackwalkCache - 4, // CrstSharedAssemblyCreate - 3, // CrstSigConvert - 5, // CrstSingleUseLock - 0, // CrstSpecialStatics - 0, // CrstSqmManager - 0, // CrstStackSampler - -1, // CrstStressLog - 0, // CrstStrongName - 5, // CrstStubCache - 0, // CrstStubDispatchCache - 4, // CrstStubUnwindInfoHeapSegments - 3, // CrstSyncBlockCache - 0, // CrstSyncHashLock - 4, // CrstSystemBaseDomain - 13, // CrstSystemDomain - 0, // CrstSystemDomainDelayedUnloadList - 0, // CrstThreadIdDispenser - 0, // CrstThreadpoolEventCache - 7, // CrstThreadpoolTimerQueue - 7, // CrstThreadpoolWaitThreads - 13, // CrstThreadpoolWorker - 4, // CrstThreadStaticDataHashTable - 12, // CrstThreadStore - 9, // CrstTieredCompilation - 9, // CrstTPMethodTable - 3, // CrstTypeEquivalenceMap - 7, // CrstTypeIDMap - 3, // CrstUMEntryThunkCache - 0, // CrstUMThunkHash - 3, // CrstUniqueStack - 7, // CrstUnresolvedClassLock - 3, // CrstUnwindInfoTableLock - 3, // CrstVSDIndirectionCellLock - 3, // CrstWinRTFactoryCache - 3, // CrstWrapperTemplate + 9, // CrstAllowedFiles + 9, // CrstAppDomainCache + 14, // CrstAppDomainHandleTable + 0, // CrstArgBasedStubCache + 0, // CrstAssemblyDependencyGraph + 0, // CrstAssemblyIdentityCache + 0, // CrstAssemblyList + 7, // CrstAssemblyLoader + 3, // CrstAvailableClass + 4, // CrstAvailableParamTypes + 7, // CrstBaseDomain + -1, // CrstCCompRC + 9, // CrstCer + 13, // CrstClassFactInfoHash + 8, // CrstClassInit + -1, // CrstClrNotification + 0, // CrstCLRPrivBinderMaps + 3, // CrstCLRPrivBinderMapsAdd + 6, // CrstCodeFragmentHeap + 10, // CrstCodeVersioning + 0, // CrstCOMCallWrapper + 4, // CrstCOMWrapperCache + 0, // CrstConnectionNameTable + 17, // CrstContexts + 0, // CrstCrstCLRPrivBinderLocalWinMDPath + 7, // CrstCSPCache + 3, // CrstDataTest1 + 0, // CrstDataTest2 + 0, // CrstDbgTransport + 0, // CrstDeadlockDetection + -1, // CrstDebuggerController + 3, // CrstDebuggerFavorLock + 0, // CrstDebuggerHeapExecMemLock + 0, // CrstDebuggerHeapLock + 4, // CrstDebuggerJitInfo + 11, // CrstDebuggerMutex + 0, // CrstDelegateToFPtrHash + 16, // CrstDomainLocalBlock + 0, // CrstDynamicIL + 3, // CrstDynamicMT + 3, // CrstDynLinkZapItems + 7, // CrstEtwTypeLogHash + 18, // CrstEventPipe + 0, // CrstEventStore + 0, // CrstException + 7, // CrstExecuteManLock + 0, // CrstExecuteManRangeLock + 3, // CrstFCall + 7, // CrstFriendAccessCache + 7, // CrstFuncPtrStubs + 5, // CrstFusionAppCtx + 11, // CrstGCCover + 0, // CrstGCMemoryPressure + 13, // CrstGlobalStrLiteralMap + 1, // CrstHandleTable + 0, // CrstHostAssemblyMap + 3, // CrstHostAssemblyMapAdd + 0, // CrstIbcProfile + 9, // CrstIJWFixupData + 0, // CrstIJWHash + 7, // CrstILStubGen + 3, // CrstInlineTrackingMap + 17, // CrstInstMethodHashTable + 0, // CrstInterfaceVTableMap + 18, // CrstInterop + 4, // CrstInteropData + 13, // CrstIOThreadpoolWorker + 0, // CrstIsJMCMethod + 7, // CrstISymUnmanagedReader + 8, // CrstJit + 0, // CrstJitGenericHandleCache + 16, // CrstJitInlineTrackingMap + -1, // CrstJitPerf + 6, // CrstJumpStubCache + 0, // CrstLeafLock + -1, // CrstListLock + 15, // CrstLoaderAllocator + 16, // CrstLoaderAllocatorReferences + 0, // CrstLoaderHeap + 0, // CrstMda + -1, // CrstMetadataTracker + 14, // CrstMethodDescBackpatchInfoTracker + 0, // CrstModIntPairList + 4, // CrstModule + 15, // CrstModuleFixup + 3, // CrstModuleLookupTable + 0, // CrstMulticoreJitHash + 13, // CrstMulticoreJitManager + 0, // CrstMUThunkHash + -1, // CrstNativeBinderInit + -1, // CrstNativeImageCache + 0, // CrstNativeImageEagerFixups + 0, // CrstNls + 0, // CrstNotifyGdb + 2, // CrstObjectList + 0, // CrstOnEventManager + 0, // CrstPatchEntryPoint + 4, // CrstPEImage + 0, // CrstPEImagePDBStream + 19, // CrstPendingTypeLoadEntry + 0, // CrstPinHandle + 0, // CrstPinnedByrefValidation + 0, // CrstProfilerGCRefDataFreeList + 0, // CrstProfilingAPIStatus + 0, // CrstPublisherCertificate + 3, // CrstRCWCache + 0, // CrstRCWCleanupList + 3, // CrstRCWRefCache + 4, // CrstReadyToRunEntryPointToMethodDescMap + 0, // CrstReDacl + 9, // CrstReflection + 17, // CrstReJITGlobalRequest + 20, // CrstRemoting + 3, // CrstRetThunkCache + 0, // CrstRWLock + 3, // CrstSavedExceptionInfo + 0, // CrstSaveModuleProfileData + 0, // CrstSecurityStackwalkCache + 4, // CrstSharedAssemblyCreate + 3, // CrstSigConvert + 5, // CrstSingleUseLock + 0, // CrstSpecialStatics + 0, // CrstSqmManager + 0, // CrstStackSampler + -1, // CrstStressLog + 0, // CrstStrongName + 5, // CrstStubCache + 0, // CrstStubDispatchCache + 4, // CrstStubUnwindInfoHeapSegments + 3, // CrstSyncBlockCache + 0, // CrstSyncHashLock + 4, // CrstSystemBaseDomain + 13, // CrstSystemDomain + 0, // CrstSystemDomainDelayedUnloadList + 0, // CrstThreadIdDispenser + 0, // CrstThreadpoolEventCache + 7, // CrstThreadpoolTimerQueue + 7, // CrstThreadpoolWaitThreads + 13, // CrstThreadpoolWorker + 4, // CrstThreadStaticDataHashTable + 12, // CrstThreadStore + 9, // CrstTieredCompilation + 9, // CrstTPMethodTable + 3, // CrstTypeEquivalenceMap + 7, // CrstTypeIDMap + 3, // CrstUMEntryThunkCache + 0, // CrstUMThunkHash + 3, // CrstUniqueStack + 7, // CrstUnresolvedClassLock + 3, // CrstUnwindInfoTableLock + 3, // CrstVSDIndirectionCellLock + 3, // CrstWinRTFactoryCache + 3, // CrstWrapperTemplate }; // An array mapping CrstType to a stringized name. @@ -427,6 +429,7 @@ LPCSTR g_rgCrstNameMap[] = "CrstMUThunkHash", "CrstNativeBinderInit", "CrstNativeImageCache", + "CrstNativeImageEagerFixups", "CrstNls", "CrstNotifyGdb", "CrstObjectList", diff --git a/src/coreclr/src/inc/pedecoder.h b/src/coreclr/src/inc/pedecoder.h index 42d6eca9a50..ad0e77e532c 100644 --- a/src/coreclr/src/inc/pedecoder.h +++ b/src/coreclr/src/inc/pedecoder.h @@ -41,6 +41,7 @@ #include "corcompile.h" #include "readytorun.h" +typedef DPTR(struct READYTORUN_CORE_HEADER) PTR_READYTORUN_CORE_HEADER; typedef DPTR(struct READYTORUN_HEADER) PTR_READYTORUN_HEADER; typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION; @@ -338,6 +339,7 @@ class PEDecoder TADDR GetVirtualSectionsTable(COUNT_T *pSize = NULL) const; #endif // FEATURE_PREJIT + BOOL IsComponentAssembly() const; BOOL HasReadyToRunHeader() const; READYTORUN_HEADER *GetReadyToRunHeader() const; @@ -349,6 +351,9 @@ class PEDecoder BOOL HasNativeEntryPoint() const; void *GetNativeEntryPoint() const; + // Look up a named symbol in the export directory + void *GetExport(LPCSTR exportName) const; + #ifdef _DEBUG // Stress mode for relocations static BOOL GetForceRelocs(); diff --git a/src/coreclr/src/inc/pedecoder.inl b/src/coreclr/src/inc/pedecoder.inl index c9ea3f7abf6..09bcfd76a14 100644 --- a/src/coreclr/src/inc/pedecoder.inl +++ b/src/coreclr/src/inc/pedecoder.inl @@ -1323,7 +1323,7 @@ inline void PEDecoder::GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine) dwMachine = IMAGE_FILE_MACHINE_NATIVE; } - if ((GetReadyToRunHeader()->Flags & READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE) != 0) + if ((GetReadyToRunHeader()->CoreHeader.Flags & READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE) != 0) { // Supply the original PEKind/Machine to the assembly binder to make the full assembly name look like the original dwKind = peILonly; @@ -1355,6 +1355,21 @@ inline BOOL PEDecoder::IsPlatformNeutral() return ((dwKind & (peILonly | pe32Plus | pe32BitRequired)) == peILonly) && (dwMachine == IMAGE_FILE_MACHINE_I386); } +inline BOOL PEDecoder::IsComponentAssembly() const +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return HasReadyToRunHeader() && (m_pReadyToRunHeader->CoreHeader.Flags & READYTORUN_FLAG_COMPONENT) != 0; +} + inline BOOL PEDecoder::HasReadyToRunHeader() const { CONTRACTL diff --git a/src/coreclr/src/inc/readytorun.h b/src/coreclr/src/inc/readytorun.h index 7df03784ced..dac75daf9c2 100644 --- a/src/coreclr/src/inc/readytorun.h +++ b/src/coreclr/src/inc/readytorun.h @@ -23,12 +23,8 @@ // R2R Version 3.0 changes calling conventions to correctly handle explicit structures to spec. // R2R 3.0 is not backward compatible with 2.x. -struct READYTORUN_HEADER +struct READYTORUN_CORE_HEADER { - DWORD Signature; // READYTORUN_SIGNATURE - USHORT MajorVersion; // READYTORUN_VERSION_XXX - USHORT MinorVersion; - DWORD Flags; // READYTORUN_FLAG_XXX DWORD NumberOfSections; @@ -37,12 +33,29 @@ struct READYTORUN_HEADER // READYTORUN_SECTION Sections[]; }; +struct READYTORUN_HEADER +{ + DWORD Signature; // READYTORUN_SIGNATURE + USHORT MajorVersion; // READYTORUN_VERSION_XXX + USHORT MinorVersion; + + READYTORUN_CORE_HEADER CoreHeader; +}; + +struct READYTORUN_COMPONENT_ASSEMBLIES_ENTRY +{ + IMAGE_DATA_DIRECTORY CorHeader; + IMAGE_DATA_DIRECTORY ReadyToRunCoreHeader; +}; + enum ReadyToRunFlag { READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE = 0x00000001, // Set if the original IL assembly was platform-neutral READYTORUN_FLAG_SKIP_TYPE_VALIDATION = 0x00000002, // Set of methods with native code was determined using profile data READYTORUN_FLAG_PARTIAL = 0x00000004, - READYTORUN_FLAG_NONSHARED_PINVOKE_STUBS = 0x00000008 // PInvoke stubs compiled into image are non-shareable (no secret parameter) + READYTORUN_FLAG_NONSHARED_PINVOKE_STUBS = 0x00000008, // PInvoke stubs compiled into image are non-shareable (no secret parameter) + READYTORUN_FLAG_EMBEDDED_MSIL = 0x00000010, // MSIL is embedded in the composite R2R executable + READYTORUN_FLAG_COMPONENT = 0x00000020, // This is the header describing a component assembly of composite R2R }; enum class ReadyToRunSectionType : uint32_t @@ -62,6 +75,8 @@ enum class ReadyToRunSectionType : uint32_t ManifestMetadata = 112, // Added in V2.3 AttributePresence = 113, // Added in V3.1 InliningInfo2 = 114, // Added in V4.1 + ComponentAssemblies = 115, // Added in V4.1 + OwnerCompositeExecutable = 116, // Added in V4.1 // If you add a new section consider whether it is a breaking or non-breaking change. // Usually it is non-breaking, but if it is preferable to have older runtimes fail diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs index ee0c439e6d0..e528996a964 100644 --- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs +++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs @@ -21,11 +21,15 @@ namespace ReadyToRun.SuperIlc { "coreclr", "clrjit", - "mscorrc", "mscordaccore", "mscordbi", }; + private static string[] s_runtimeWindowsOnlyLibraries = + { + "mscorrc", + }; + private List _compilationInputFiles; private List _mainExecutables; @@ -157,9 +161,17 @@ namespace ReadyToRun.SuperIlc { passThroughFiles.Add(Path.Combine(options.CoreRootDirectory.FullName, exe.AppendOSExeSuffix())); } + string libraryPrefix = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "" : "lib"); foreach (string lib in s_runtimeLibraries) { - passThroughFiles.Add(Path.Combine(options.CoreRootDirectory.FullName, lib.AppendOSDllSuffix())); + passThroughFiles.Add(Path.Combine(options.CoreRootDirectory.FullName, (libraryPrefix + lib).AppendOSDllSuffix())); + } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + foreach (string lib in s_runtimeWindowsOnlyLibraries) + { + passThroughFiles.Add(Path.Combine(options.CoreRootDirectory.FullName, lib.AppendOSDllSuffix())); + } } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs index 73ce2bfe03f..d01315059a6 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs @@ -74,27 +74,28 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun _moduleIdToAssemblyNameMap = new Dictionary(); _signatureEmitters = new List(); _nodeFactory = nodeFactory; + _nextModuleId = 1; if (!_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode) { MetadataReader mdReader = _nodeFactory.CompilationModuleGroup.CompilationModuleSet.Single().MetadataReader; - _assemblyRefCount = mdReader.GetTableRowCount(TableIndex.AssemblyRef); - for (int assemblyRefIndex = 1; assemblyRefIndex <= _assemblyRefCount; assemblyRefIndex++) + _assemblyRefCount = mdReader.GetTableRowCount(TableIndex.AssemblyRef) + 1; + for (int assemblyRefIndex = 1; assemblyRefIndex < _assemblyRefCount; assemblyRefIndex++) { AssemblyReferenceHandle assemblyRefHandle = MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex); AssemblyReference assemblyRef = mdReader.GetAssemblyReference(assemblyRefHandle); string assemblyName = mdReader.GetString(assemblyRef.Name); _assemblyRefToModuleIdMap[assemblyName] = assemblyRefIndex; } - } - // AssemblyRefCount + 1 corresponds to ROWID 0 in the manifest metadata - _nextModuleId = _assemblyRefCount + 2; + // AssemblyRefCount + 1 corresponds to ROWID 0 in the manifest metadata + _nextModuleId += _assemblyRefCount; + } if (_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode) { // Fill in entries for all input modules right away to make sure they have parallel indices - int nextExpectedId = 2; + int nextExpectedId = 1; foreach (EcmaModule inputModule in _nodeFactory.CompilationModuleGroup.CompilationModuleSet) { int acquiredId = ModuleToIndexInternal(inputModule); @@ -134,7 +135,7 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun _assemblyRefToModuleIdMap.Add(assemblyName.Name, assemblyRefIndex); } - if ((assemblyRefIndex >= _assemblyRefCount + 2) && !_moduleIdToAssemblyNameMap.ContainsKey(assemblyRefIndex)) + if (assemblyRefIndex >= _assemblyRefCount && !_moduleIdToAssemblyNameMap.ContainsKey(assemblyRefIndex)) { if (_emissionCompleted) { diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/OwnerCompositeExecutableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/OwnerCompositeExecutableNode.cs index bc79b4402f4..1c71fc82609 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/OwnerCompositeExecutableNode.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/OwnerCompositeExecutableNode.cs @@ -37,9 +37,9 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); - builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); builder.EmitBytes(Encoding.UTF8.GetBytes(_ownerExecutableName)); + builder.EmitByte(0); // zero string terminator return builder.ToObjectData(); } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs index 983a624d43e..9705b5d3978 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs @@ -381,6 +381,7 @@ namespace ILCompiler.Reflection.ReadyToRun throw new BadImageFormatException("The file is not a ReadyToRun image"); } + Debug.Assert(!Composite); _assemblyCache.Add(metadata); DirectoryEntry r2rHeaderDirectory = PEReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory; @@ -639,7 +640,7 @@ namespace ILCompiler.Reflection.ReadyToRun { if (ReadyToRunAssemblyHeaders[assemblyIndex].Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out methodEntryPointSection)) { - ParseMethodDefEntrypointsSection(methodEntryPointSection, OpenReferenceAssembly(assemblyIndex + 2), isEntryPoint); + ParseMethodDefEntrypointsSection(methodEntryPointSection, OpenReferenceAssembly(assemblyIndex + 1), isEntryPoint); } } } @@ -816,7 +817,7 @@ namespace ILCompiler.Reflection.ReadyToRun if (_readyToRunAssemblyHeaders[assemblyIndex].Sections.TryGetValue( ReadyToRunSectionType.AvailableTypes, out availableTypesSection)) { - ParseAvailableTypesSection(availableTypesSection, OpenReferenceAssembly(assemblyIndex + 2)); + ParseAvailableTypesSection(availableTypesSection, OpenReferenceAssembly(assemblyIndex + 1)); } } } @@ -1057,9 +1058,9 @@ namespace ILCompiler.Reflection.ReadyToRun { Debug.Assert(refAsmIndex != 0); - int assemblyRefCount = (_composite ? 0 : _assemblyCache[0].GetTableRowCount(TableIndex.AssemblyRef)); + int assemblyRefCount = (_composite ? 0 : _assemblyCache[0].GetTableRowCount(TableIndex.AssemblyRef) + 1); AssemblyReferenceHandle assemblyReferenceHandle; - if (refAsmIndex <= assemblyRefCount) + if (refAsmIndex < assemblyRefCount) { metadataReader = _assemblyCache[0]; assemblyReferenceHandle = MetadataTokens.AssemblyReferenceHandle(refAsmIndex); @@ -1067,7 +1068,7 @@ namespace ILCompiler.Reflection.ReadyToRun else { metadataReader = ManifestReader; - assemblyReferenceHandle = ManifestReferences[refAsmIndex - assemblyRefCount - 2]; + assemblyReferenceHandle = ManifestReferences[refAsmIndex - assemblyRefCount - 1]; } return assemblyReferenceHandle; diff --git a/src/coreclr/src/tools/r2rdump/TextDumper.cs b/src/coreclr/src/tools/r2rdump/TextDumper.cs index 1b3cf275685..9b0d8416610 100644 --- a/src/coreclr/src/tools/r2rdump/TextDumper.cs +++ b/src/coreclr/src/tools/r2rdump/TextDumper.cs @@ -411,7 +411,7 @@ namespace R2RDump if (!_r2r.Composite) { MetadataReader globalReader = _r2r.GetGlobalMetadataReader(); - assemblyRefCount = globalReader.GetTableRowCount(TableIndex.AssemblyRef); + assemblyRefCount = globalReader.GetTableRowCount(TableIndex.AssemblyRef) + 1; _writer.WriteLine($"MSIL AssemblyRef's ({assemblyRefCount} entries):"); for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++) { @@ -425,7 +425,7 @@ namespace R2RDump int manifestAsmIndex = 0; foreach (string manifestReferenceAssembly in _r2r.ManifestReferenceAssemblies.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key)) { - _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 2:X2}]: {manifestReferenceAssembly}"); + _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 1:X2}]: {manifestReferenceAssembly}"); manifestAsmIndex++; } break; @@ -451,7 +451,7 @@ namespace R2RDump case ReadyToRunSectionType.OwnerCompositeExecutable: int oceOffset = _r2r.GetOffset(section.RelativeVirtualAddress); Decoder decoder = Encoding.UTF8.GetDecoder(); - int charLength = decoder.GetCharCount(_r2r.Image, oceOffset, section.Size); + int charLength = decoder.GetCharCount(_r2r.Image, oceOffset, section.Size - 1); // exclude the zero terminator char[] charArray = new char[charLength]; decoder.GetChars(_r2r.Image, oceOffset, section.Size, charArray, 0, flush: true); string ownerCompositeExecutable = new string(charArray); diff --git a/src/coreclr/src/utilcode/pedecoder.cpp b/src/coreclr/src/utilcode/pedecoder.cpp index 11563ddd556..3ba2f15d9c6 100644 --- a/src/coreclr/src/utilcode/pedecoder.cpp +++ b/src/coreclr/src/utilcode/pedecoder.cpp @@ -2326,7 +2326,7 @@ READYTORUN_HEADER * PEDecoder::FindReadyToRunHeader() const PTR_READYTORUN_HEADER pHeader = PTR_READYTORUN_HEADER((TADDR)GetDirectoryData(pDir)); if (pHeader->Signature == READYTORUN_SIGNATURE) { - const_cast(this)->m_pReadyToRunHeader = pHeader; + const_cast(this)->m_pReadyToRunHeader = pHeader; return pHeader; } } @@ -2335,6 +2335,41 @@ READYTORUN_HEADER * PEDecoder::FindReadyToRunHeader() const return NULL; } +#ifndef DACCESS_COMPILE +void *PEDecoder::GetExport(LPCSTR exportName) const +{ + // Get the export directory entry + PIMAGE_DATA_DIRECTORY pExportDirectoryEntry = GetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXPORT); + if (pExportDirectoryEntry->VirtualAddress == 0 || pExportDirectoryEntry->Size == 0) + { + return NULL; + } + + uint8_t *imageBase = (uint8_t *)GetBase(); + const IMAGE_EXPORT_DIRECTORY *pExportDir = (const IMAGE_EXPORT_DIRECTORY *)GetDirectoryData(pExportDirectoryEntry); + + uint32_t namePointerCount = VAL32(pExportDir->NumberOfNames); + uint32_t addressTableRVA = VAL32(pExportDir->AddressOfFunctions); + uint32_t namePointersRVA = VAL32(pExportDir->AddressOfNames); + + for (uint32_t nameIndex = 0; nameIndex < namePointerCount; nameIndex++) + { + uint32_t namePointerRVA = VAL32(*(const uint32_t *)&imageBase[namePointersRVA + sizeof(uint32_t) * nameIndex]); + if (namePointerRVA != 0) + { + const char *namePointer = (const char *)&imageBase[namePointerRVA]; + if (!strcmp(namePointer, exportName)) + { + uint32_t exportRVA = VAL32(*(const uint32_t *)&imageBase[addressTableRVA + sizeof(uint32_t) * nameIndex]); + return &imageBase[exportRVA]; + } + } + } + + return NULL; +} +#endif + // // code:PEDecoder::CheckILMethod and code:PEDecoder::ComputeILMethodSize really belong to // file:..\inc\corhlpr.cpp. Unfortunately, corhlpr.cpp is public header file that cannot be @@ -2857,7 +2892,7 @@ PTR_CVOID PEDecoder::GetNativeManifestMetadata(COUNT_T *pSize) const READYTORUN_HEADER * pHeader = GetReadyToRunHeader(); PTR_READYTORUN_SECTION pSections = dac_cast(dac_cast(pHeader) + sizeof(READYTORUN_HEADER)); - for (DWORD i = 0; i < pHeader->NumberOfSections; i++) + for (DWORD i = 0; i < pHeader->CoreHeader.NumberOfSections; i++) { // Verify that section types are sorted _ASSERTE(i == 0 || (pSections[i - 1].Type < pSections[i].Type)); diff --git a/src/coreclr/src/vm/CMakeLists.txt b/src/coreclr/src/vm/CMakeLists.txt index ac8d660428a..43b9bc34519 100644 --- a/src/coreclr/src/vm/CMakeLists.txt +++ b/src/coreclr/src/vm/CMakeLists.txt @@ -97,6 +97,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON methodimpl.cpp methoditer.cpp methodtable.cpp + nativeimage.cpp object.cpp pefile.cpp peimage.cpp diff --git a/src/coreclr/src/vm/assemblyloadcontext.cpp b/src/coreclr/src/vm/assemblyloadcontext.cpp index 40cb2432c0a..d5adfffbd09 100644 --- a/src/coreclr/src/vm/assemblyloadcontext.cpp +++ b/src/coreclr/src/vm/assemblyloadcontext.cpp @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. #include "common.h" +#include "nativeimage.h" AssemblyLoadContext::AssemblyLoadContext() { @@ -14,3 +15,58 @@ HRESULT AssemblyLoadContext::GetBinderID( *pBinderId = reinterpret_cast(this); return S_OK; } + +#ifndef DACCESS_COMPILE +NativeImage *AssemblyLoadContext::LoadNativeImage(Module *componentModule, LPCUTF8 nativeImageName) +{ + STANDARD_VM_CONTRACT; + + BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); + AssemblyLoadContext *loadContext = componentModule->GetFile()->GetAssemblyLoadContext(); + PTR_LoaderAllocator moduleLoaderAllocator = componentModule->GetLoaderAllocator(); + + int nativeImageCount = m_nativeImages.GetCount(); +#ifndef FEATURE_CASE_SENSITIVE_FILESYSTEM + SString nativeImageNameString; + nativeImageNameString.SetUTF8(nativeImageName); +#endif + for (int nativeImageIndex = 0; nativeImageIndex < nativeImageCount; nativeImageIndex++) + { + NativeImage *nativeImage = m_nativeImages[nativeImageIndex]; + LPCUTF8 existingImageFileName = nativeImage->GetFileName(); +#ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM + bool match = (strcmp(nativeImageName, existingImageFileName) == 0); +#else + bool match = SString(SString::Utf8Literal, existingImageFileName).EqualsCaseInsensitive(nativeImageNameString); +#endif + if (match) + { + return nativeImage; + } + } + + SString path = componentModule->GetPath(); + SString::Iterator lastPathSeparatorIter = path.End(); + size_t pathDirLength = 0; + if (PEAssembly::FindLastPathSeparator(path, lastPathSeparatorIter)) + { + pathDirLength = (lastPathSeparatorIter - path.Begin()) + 1; + } + + SString compositeImageFileName(SString::Utf8, nativeImageName); + SString fullPath; + fullPath.Set(path, path.Begin(), (COUNT_T)pathDirLength); + fullPath += compositeImageFileName; + + AllocMemTracker amTracker; + NativeImage *nativeImage = NativeImage::Open(fullPath, nativeImageName, moduleLoaderAllocator, &amTracker); + if (nativeImage != NULL) + { + m_nativeImages.Append(nativeImage); + amTracker.SuppressRelease(); + return nativeImage; + } + + return NULL; +} +#endif diff --git a/src/coreclr/src/vm/assemblyloadcontext.h b/src/coreclr/src/vm/assemblyloadcontext.h index 395e697562e..85b4f30d09a 100644 --- a/src/coreclr/src/vm/assemblyloadcontext.h +++ b/src/coreclr/src/vm/assemblyloadcontext.h @@ -5,6 +5,11 @@ #ifndef _ASSEMBLYLOADCONTEXT_H #define _ASSEMBLYLOADCONTEXT_H +#include "crst.h" + +class NativeImage; +class Module; + // // Unmanaged counter-part of System.Runtime.Loader.AssemblyLoadContext // @@ -15,6 +20,11 @@ public: STDMETHOD(GetBinderID)( /* [retval][out] */ UINT_PTR* pBinderId); + + NativeImage *LoadNativeImage(Module *componentModule, LPCUTF8 nativeImageName); + +private: + SArray m_nativeImages; }; #endif diff --git a/src/coreclr/src/vm/ceeload.cpp b/src/coreclr/src/vm/ceeload.cpp index 31cea51c797..df5b2ef1826 100644 --- a/src/coreclr/src/vm/ceeload.cpp +++ b/src/coreclr/src/vm/ceeload.cpp @@ -41,6 +41,7 @@ #include "metadataexports.h" #include "inlinetracking.h" #include "threads.h" +#include "nativeimage.h" #ifdef FEATURE_PREJIT #include "exceptionhandling.h" @@ -497,6 +498,19 @@ BOOL Module::IsPersistedObject(void *address) } #endif // FEATURE_PREJIT +uint32_t Module::GetNativeMetadataAssemblyCount() +{ + NativeImage *compositeImage = GetCompositeNativeImage(); + if (compositeImage != NULL) + { + return compositeImage->GetComponentAssemblyCount(); + } + else + { + return GetNativeAssemblyImport()->GetCountWithTokenKind(mdtAssemblyRef); + } +} + void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssembly) { CONTRACTL @@ -509,8 +523,7 @@ void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssemb if (m_NativeMetadataAssemblyRefMap == NULL) { - IMDInternalImport* pImport = GetNativeAssemblyImport(); - DWORD dwMaxRid = pImport->GetCountWithTokenKind(mdtAssemblyRef); + uint32_t dwMaxRid = GetNativeMetadataAssemblyCount(); _ASSERTE(dwMaxRid > 0); S_SIZE_T dwAllocSize = S_SIZE_T(sizeof(PTR_Assembly)) * S_SIZE_T(dwMaxRid); @@ -525,7 +538,7 @@ void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssemb } _ASSERTE(m_NativeMetadataAssemblyRefMap != NULL); - _ASSERTE(rid <= GetNativeAssemblyImport()->GetCountWithTokenKind(mdtAssemblyRef)); + _ASSERTE(rid <= GetNativeMetadataAssemblyCount()); m_NativeMetadataAssemblyRefMap[rid - 1] = pAssembly; } @@ -10503,6 +10516,34 @@ void Module::RunEagerFixups() // TODO: Verify that eager fixup dependency graphs can contain no cycles OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED); + NativeImage *compositeNativeImage = GetCompositeNativeImage(); + if (compositeNativeImage != NULL) + { + // For composite images, multiple modules may request initializing eager fixups + // from multiple threads so we need to lock their resolution. + if (compositeNativeImage->EagerFixupsHaveRun()) + { + return; + } + CrstHolder compositeEagerFixups(compositeNativeImage->EagerFixupsLock()); + if (compositeNativeImage->EagerFixupsHaveRun()) + { + return; + } + RunEagerFixupsUnlocked(); + compositeNativeImage->SetEagerFixupsHaveRun(); + } + else + { + // Per-module eager fixups don't need locking + RunEagerFixupsUnlocked(); + } +} + +void Module::RunEagerFixupsUnlocked() +{ + COUNT_T nSections; + PTR_CORCOMPILE_IMPORT_SECTION pSections = GetImportSections(&nSections); PEImageLayout *pNativeImage = GetNativeOrReadyToRunImage(); for (COUNT_T iSection = 0; iSection < nSections; iSection++) diff --git a/src/coreclr/src/vm/ceeload.h b/src/coreclr/src/vm/ceeload.h index 86b3fe347a2..52393b0046e 100644 --- a/src/coreclr/src/vm/ceeload.h +++ b/src/coreclr/src/vm/ceeload.h @@ -2758,6 +2758,7 @@ public: PTR_CORCOMPILE_IMPORT_SECTION pImportSections, COUNT_T nImportSections, PEDecoder * pNativeImage); void RunEagerFixups(); + void RunEagerFixupsUnlocked(); Module *GetModuleFromIndex(DWORD ix); Module *GetModuleFromIndexIfLoaded(DWORD ix); @@ -2912,7 +2913,7 @@ public: #endif // FEATURE_PREJIT - BOOL IsReadyToRun() + BOOL IsReadyToRun() const { LIMITED_METHOD_DAC_CONTRACT; @@ -2923,8 +2924,14 @@ public: #endif } + NativeImage *GetCompositeNativeImage() const + { + LIMITED_METHOD_DAC_CONTRACT; + return (m_pReadyToRunInfo != NULL ? m_pReadyToRunInfo->GetNativeImage() : NULL); + } + #ifdef FEATURE_READYTORUN - PTR_ReadyToRunInfo GetReadyToRunInfo() + PTR_ReadyToRunInfo GetReadyToRunInfo() const { LIMITED_METHOD_DAC_CONTRACT; return m_pReadyToRunInfo; @@ -3228,11 +3235,13 @@ public: if (NativeMetadataAssemblyRefMap == NULL) return NULL; - _ASSERTE(rid <= GetNativeAssemblyImport()->GetCountWithTokenKind(mdtAssemblyRef)); + _ASSERTE(rid <= GetNativeMetadataAssemblyCount()); return NativeMetadataAssemblyRefMap[rid - 1]; } void SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssembly); + + uint32_t GetNativeMetadataAssemblyCount(); #endif // !defined(DACCESS_COMPILE) // For protecting dictionary layout slot expansions diff --git a/src/coreclr/src/vm/crossgen/CMakeLists.txt b/src/coreclr/src/vm/crossgen/CMakeLists.txt index d223da0205d..6a42ab503b2 100644 --- a/src/coreclr/src/vm/crossgen/CMakeLists.txt +++ b/src/coreclr/src/vm/crossgen/CMakeLists.txt @@ -61,6 +61,7 @@ set(VM_CROSSGEN_SOURCES ../methodtablebuilder.cpp ../mlinfo.cpp ../mscorlib.cpp + ../nativeimage.cpp ../olevariant.cpp ../pefile.cpp ../peimage.cpp diff --git a/src/coreclr/src/vm/domainfile.cpp b/src/coreclr/src/vm/domainfile.cpp index 4292a440242..1045ca2304c 100644 --- a/src/coreclr/src/vm/domainfile.cpp +++ b/src/coreclr/src/vm/domainfile.cpp @@ -2358,6 +2358,4 @@ DomainAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) } } - #endif // #ifdef DACCESS_COMPILE - diff --git a/src/coreclr/src/vm/nativeimage.cpp b/src/coreclr/src/vm/nativeimage.cpp new file mode 100644 index 00000000000..7cda61993dd --- /dev/null +++ b/src/coreclr/src/vm/nativeimage.cpp @@ -0,0 +1,166 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// -------------------------------------------------------------------------------- +// NativeImage.cpp +// + +// -------------------------------------------------------------------------------- + +#include "common.h" +#include "nativeimage.h" + +// -------------------------------------------------------------------------------- +// Headers +// -------------------------------------------------------------------------------- + +#include + +BOOL AssemblyNameIndexHashTraits::Equals(LPCUTF8 a, LPCUTF8 b) +{ + WRAPPER_NO_CONTRACT; + + return SString(SString::Utf8Literal, a).Compare(SString(SString::Utf8Literal, b)) == 0; +} + +AssemblyNameIndexHashTraits::count_t AssemblyNameIndexHashTraits::Hash(LPCUTF8 s) +{ + WRAPPER_NO_CONTRACT; + + return SString(SString::Utf8Literal, s).HashCaseInsensitive(); +} + +NativeImage::NativeImage(PEImageLayout *pImageLayout, LPCUTF8 imageFileName) + : m_eagerFixupsLock(CrstNativeImageEagerFixups) +{ + CONTRACTL + { + THROWS; + CONSTRUCTOR_CHECK; + STANDARD_VM_CHECK; + INJECT_FAULT(COMPlusThrowOM();); + } + CONTRACTL_END; + + m_pImageLayout = pImageLayout; + m_fileName = imageFileName; + m_eagerFixupsHaveRun = false; +} + +void NativeImage::Initialize(READYTORUN_HEADER *pHeader, LoaderAllocator *pLoaderAllocator, AllocMemTracker *pamTracker) +{ + LoaderHeap *pHeap = pLoaderAllocator->GetHighFrequencyHeap(); + + m_pReadyToRunInfo = new ReadyToRunInfo(/*pModule*/ NULL, m_pImageLayout, pHeader, /*compositeImage*/ NULL, pamTracker); + m_pComponentAssemblies = m_pReadyToRunInfo->FindSection(ReadyToRunSectionType::ComponentAssemblies); + m_componentAssemblyCount = m_pComponentAssemblies->Size / sizeof(READYTORUN_COMPONENT_ASSEMBLIES_ENTRY); + + // Check if the current module's image has native manifest metadata, otherwise the current->GetNativeAssemblyImport() asserts. + m_pManifestMetadata = LoadManifestMetadata(); + + HENUMInternal assemblyEnum; + HRESULT hr = m_pManifestMetadata->EnumAllInit(mdtAssemblyRef, &assemblyEnum); + mdAssemblyRef assemblyRef; + int assemblyIndex = 0; + while (m_pManifestMetadata->EnumNext(&assemblyEnum, &assemblyRef)) + { + LPCSTR assemblyName; + hr = m_pManifestMetadata->GetAssemblyRefProps(assemblyRef, NULL, NULL, &assemblyName, NULL, NULL, NULL, NULL); + m_assemblySimpleNameToIndexMap.Add(AssemblyNameIndex(assemblyName, assemblyIndex)); + assemblyIndex++; + } +} + +NativeImage::~NativeImage() +{ + STANDARD_VM_CONTRACT; + + delete m_pReadyToRunInfo; + delete m_pImageLayout; + + if (m_pManifestMetadata != NULL) + { + m_pManifestMetadata->Release(); + } +} + +#ifndef DACCESS_COMPILE +NativeImage *NativeImage::Open( + LPCWSTR fullPath, + LPCUTF8 nativeImageFileName, + LoaderAllocator *pLoaderAllocator, + AllocMemTracker *pamTracker) +{ + STANDARD_VM_CONTRACT; + + NewHolder peLoadedImage = PEImageLayout::LoadNative(fullPath); + + READYTORUN_HEADER *pHeader = (READYTORUN_HEADER *)peLoadedImage->GetExport("RTR_HEADER"); + if (pHeader == NULL) + { + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); + } + if (pHeader->Signature != READYTORUN_SIGNATURE) + { + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); + } + if (pHeader->MajorVersion < MINIMUM_READYTORUN_MAJOR_VERSION || pHeader->MajorVersion > READYTORUN_MAJOR_VERSION) + { + COMPlusThrowHR(COR_E_BADIMAGEFORMAT); + } + NewHolder image = new NativeImage(peLoadedImage.Extract(), nativeImageFileName); + image->Initialize(pHeader, pLoaderAllocator, pamTracker); + return image.Extract(); +} +#endif + +#ifndef DACCESS_COMPILE +Assembly *NativeImage::LoadComponentAssembly(uint32_t rowid) +{ + STANDARD_VM_CONTRACT; + + AssemblySpec spec; + spec.InitializeSpec(TokenFromRid(rowid, mdtAssemblyRef), m_pManifestMetadata, NULL); + return spec.LoadAssembly(FILE_LOADED); +} +#endif + +#ifndef DACCESS_COMPILE +PTR_READYTORUN_CORE_HEADER NativeImage::GetComponentAssemblyHeader(LPCUTF8 simpleName) +{ + STANDARD_VM_CONTRACT; + + const AssemblyNameIndex *assemblyNameIndex = m_assemblySimpleNameToIndexMap.LookupPtr(simpleName); + if (assemblyNameIndex != NULL) + { + const BYTE *pImageBase = (const BYTE *)m_pImageLayout->GetBase(); + const READYTORUN_COMPONENT_ASSEMBLIES_ENTRY *componentAssembly = + (const READYTORUN_COMPONENT_ASSEMBLIES_ENTRY *)&pImageBase[m_pComponentAssemblies->VirtualAddress] + assemblyNameIndex->Index; + return (PTR_READYTORUN_CORE_HEADER)&pImageBase[componentAssembly->ReadyToRunCoreHeader.VirtualAddress]; + } + return NULL; +} +#endif + +#ifndef DACCESS_COMPILE +IMDInternalImport *NativeImage::LoadManifestMetadata() +{ + STANDARD_VM_CONTRACT; + + IMAGE_DATA_DIRECTORY *pMeta = m_pReadyToRunInfo->FindSection(ReadyToRunSectionType::ManifestMetadata); + + if (pMeta == NULL) + { + return NULL; + } + + IMDInternalImport *pNewImport = NULL; + IfFailThrow(GetMetaDataInternalInterface((BYTE *)m_pImageLayout->GetBase() + VAL32(pMeta->VirtualAddress), + VAL32(pMeta->Size), + ofRead, + IID_IMDInternalImport, + (void **) &pNewImport)); + + return pNewImport; +} +#endif diff --git a/src/coreclr/src/vm/nativeimage.h b/src/coreclr/src/vm/nativeimage.h new file mode 100644 index 00000000000..2c3f538043b --- /dev/null +++ b/src/coreclr/src/vm/nativeimage.h @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _NATIVEIMAGE_H +#define _NATIVEIMAGE_H + +#include "readytoruninfo.h" + +// This structure is used in NativeImage to map simple names of component assemblies +// to their indices within the component assembly header table. +struct AssemblyNameIndex +{ + LPCUTF8 Name; + int32_t Index; + + AssemblyNameIndex() : Name(NULL), Index(-1) {} + AssemblyNameIndex(LPCUTF8 name, int32_t index) : Name(name), Index(index) {} + + static AssemblyNameIndex GetNull() { return AssemblyNameIndex(); } + bool IsNull() const { return Index < 0; } +}; + +class AssemblyNameIndexHashTraits : public NoRemoveSHashTraits< DefaultSHashTraits > +{ +public: + // Similar to BaseAssemblySpec::CompareStrings, we're using temporary SStrings that throw + // for case-insensitive UTF8 assembly name comparisons. + static const bool s_NoThrow = false; + + typedef LPCUTF8 key_t; + + static AssemblyNameIndex Null() { return AssemblyNameIndex::GetNull(); } + static bool IsNull(const AssemblyNameIndex& e) { return e.IsNull(); } + + static LPCUTF8 GetKey(const AssemblyNameIndex& assemblyNameIndex) { return assemblyNameIndex.Name; } + static BOOL Equals(LPCUTF8 a, LPCUTF8 b); + static count_t Hash(LPCUTF8 a); +}; + +class AssemblyLoadContext; +class ReadyToRunInfo; +class PEFile; +class PEImage; + +// This class represents a ReadyToRun image with native OS-specific envelope. As of today, +// this file format is used as the compiled native code cache in composite R2R Crossgen2 +// build mode. Moving forward we plan to add support for OS-specific native executables +// (ELF on Linux, MachO on OSX). +// +// The native image is identified by a well-known public export 'RTR_HEADER' pointing to the +// master READYTORUN_HEADER structure for the entire file. For composite R2R executables +// built by crossgenning a larger number of input MSIL assemblies the READYTORUN_HEADER +// contains a section named ComponentAssemblies that points to READYTORUN_CORE_HEADER +// structures representing the individual component assemblies and per-assembly sections. +class NativeImage +{ +private: + // Points to the OwnerCompositeExecutable section content within the component MSIL module + LPCUTF8 m_fileName; + + ReadyToRunInfo *m_pReadyToRunInfo; + IMDInternalImport *m_pManifestMetadata; + PEImageLayout *m_pImageLayout; + + IMAGE_DATA_DIRECTORY *m_pComponentAssemblies; + uint32_t m_componentAssemblyCount; + SHash m_assemblySimpleNameToIndexMap; + + Crst m_eagerFixupsLock; + bool m_eagerFixupsHaveRun; + +private: + NativeImage(PEImageLayout *peImageLayout, LPCUTF8 imageFileName); + +protected: + void Initialize(READYTORUN_HEADER *header, LoaderAllocator *loaderAllocator, AllocMemTracker *pamTracker); + +public: + ~NativeImage(); + + static NativeImage *Open( + LPCWSTR fullPath, + LPCUTF8 nativeImageFileName, + LoaderAllocator *pLoaderAllocator, + AllocMemTracker *pamTracker); + + Crst *EagerFixupsLock() { return &m_eagerFixupsLock; } + bool EagerFixupsHaveRun() const { return m_eagerFixupsHaveRun; } + void SetEagerFixupsHaveRun() { m_eagerFixupsHaveRun = true; } + LPCUTF8 GetFileName() const { return m_fileName; } + + uint32_t GetComponentAssemblyCount() const { return m_componentAssemblyCount; } + ReadyToRunInfo *GetReadyToRunInfo() const { return m_pReadyToRunInfo; } + IMDInternalImport *GetManifestMetadata() const { return m_pManifestMetadata; } + + Assembly *LoadComponentAssembly(uint32_t rowid); + + PTR_READYTORUN_CORE_HEADER GetComponentAssemblyHeader(LPCUTF8 assemblySimpleName); + +private: + IMDInternalImport *LoadManifestMetadata(); +}; + +#endif diff --git a/src/coreclr/src/vm/peimage.h b/src/coreclr/src/vm/peimage.h index ad7a30d6c00..1edf05d8ec2 100644 --- a/src/coreclr/src/vm/peimage.h +++ b/src/coreclr/src/vm/peimage.h @@ -193,6 +193,7 @@ public: BOOL HasCorHeader(); BOOL HasReadyToRunHeader(); BOOL IsReferenceAssembly(); + BOOL IsComponentAssembly(); #ifdef FEATURE_PREJIT BOOL IsNativeILILOnly(); BOOL IsNativeILDll(); diff --git a/src/coreclr/src/vm/peimage.inl b/src/coreclr/src/vm/peimage.inl index cda9ef10066..03d8bc229ce 100644 --- a/src/coreclr/src/vm/peimage.inl +++ b/src/coreclr/src/vm/peimage.inl @@ -197,6 +197,18 @@ inline BOOL PEImage::HasCorHeader() } } +inline BOOL PEImage::IsComponentAssembly() +{ + WRAPPER_NO_CONTRACT; + if (HasLoadedLayout()) + return GetLoadedLayout()->IsComponentAssembly(); + else + { + PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); + return pLayout->IsComponentAssembly(); + } +} + inline BOOL PEImage::HasReadyToRunHeader() { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/src/vm/peimagelayout.cpp b/src/coreclr/src/vm/peimagelayout.cpp index 94f73419a40..79739716da4 100644 --- a/src/coreclr/src/vm/peimagelayout.cpp +++ b/src/coreclr/src/vm/peimagelayout.cpp @@ -60,6 +60,12 @@ PEImageLayout* PEImageLayout::LoadFlat(PEImage* pOwner) return new FlatImageLayout(pOwner); } +PEImageLayout *PEImageLayout::LoadNative(LPCWSTR fullPath) +{ + STANDARD_VM_CONTRACT; + return new NativeImageLayout(fullPath); +} + PEImageLayout* PEImageLayout::Map(PEImage* pOwner) { CONTRACT(PEImageLayout*) @@ -629,10 +635,47 @@ FlatImageLayout::FlatImageLayout(PEImage* pOwner) Init(m_FileView, size); } +NativeImageLayout::NativeImageLayout(LPCWSTR fullPath) +{ + PVOID loadedImage; +#if TARGET_UNIX + { + ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + HANDLE fileHandle = WszCreateFile( + fullPath, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (fileHandle == INVALID_HANDLE_VALUE) + { + ThrowLastError(); + } -#endif // !DACESS_COMPILE + loadedImage = PAL_LOADLoadPEFile(fileHandle); + } +#else + loadedImage = CLRLoadLibraryEx(fullPath, NULL, GetLoadWithAlteredSearchPathFlag()); +#endif + + if (loadedImage == NULL) + { + ThrowLastError(); + } +#if TARGET_UNIX + PEDecoder::Init(loadedImage, /* relocated */ false); + ApplyBaseRelocations(); + SetRelocated(); +#else // TARGET_UNIX + PEDecoder::Init(loadedImage, /* relocated */ true); +#endif // TARGET_UNIX +} +#endif // !DACESS_COMPILE #ifdef DACCESS_COMPILE void diff --git a/src/coreclr/src/vm/peimagelayout.h b/src/coreclr/src/vm/peimagelayout.h index c8f9adfc940..9ae14c4b74e 100644 --- a/src/coreclr/src/vm/peimagelayout.h +++ b/src/coreclr/src/vm/peimagelayout.h @@ -54,6 +54,7 @@ public: static PEImageLayout* LoadFromFlat(PEImageLayout* pflatimage); static PEImageLayout* Load(PEImage* pOwner, BOOL bNTSafeLoad, BOOL bThrowOnError = TRUE); static PEImageLayout* LoadFlat(PEImage* pOwner); + static PEImageLayout* LoadNative(LPCWSTR fullPath); static PEImageLayout* Map(PEImage* pOwner); #endif PEImageLayout(); @@ -168,7 +169,15 @@ public: }; +#ifndef DACCESS_COMPILE +class NativeImageLayout : public PEImageLayout +{ + VPTR_VTABLE_CLASS(NativeImageLayout, PEImageLayout) +public: + NativeImageLayout(LPCWSTR fullPath); +}; +#endif #endif // PEIMAGELAYOUT_H_ diff --git a/src/coreclr/src/vm/readytoruninfo.cpp b/src/coreclr/src/vm/readytoruninfo.cpp index 99b252056a3..0ff97ada274 100644 --- a/src/coreclr/src/vm/readytoruninfo.cpp +++ b/src/coreclr/src/vm/readytoruninfo.cpp @@ -17,10 +17,20 @@ #include "typehashingalgorithms.h" #include "method.hpp" #include "wellknownattributes.h" +#include "nativeimage.h" using namespace NativeFormat; -IMAGE_DATA_DIRECTORY * ReadyToRunInfo::FindSection(ReadyToRunSectionType type) +ReadyToRunCoreInfo::ReadyToRunCoreInfo() +{ +} + +ReadyToRunCoreInfo::ReadyToRunCoreInfo(PEImageLayout* pLayout, READYTORUN_CORE_HEADER *pCoreHeader) + : m_pLayout(pLayout), m_pCoreHeader(pCoreHeader) +{ +} + +IMAGE_DATA_DIRECTORY * ReadyToRunCoreInfo::FindSection(ReadyToRunSectionType type) const { CONTRACTL { @@ -30,8 +40,8 @@ IMAGE_DATA_DIRECTORY * ReadyToRunInfo::FindSection(ReadyToRunSectionType type) } CONTRACTL_END; - PTR_READYTORUN_SECTION pSections = dac_cast(dac_cast(m_pHeader) + sizeof(READYTORUN_HEADER)); - for (DWORD i = 0; i < m_pHeader->NumberOfSections; i++) + PTR_READYTORUN_SECTION pSections = dac_cast(dac_cast(m_pCoreHeader) + sizeof(READYTORUN_CORE_HEADER)); + for (DWORD i = 0; i < m_pCoreHeader->NumberOfSections; i++) { // Verify that section types are sorted _ASSERTE(i == 0 || (pSections[i-1].Type < pSections[i].Type)); @@ -60,10 +70,7 @@ MethodDesc * ReadyToRunInfo::GetMethodDescForEntryPoint(PCODE entryPoint) return NULL; #endif - TADDR val = (TADDR)m_entryPointToMethodDescMap.LookupValue(PCODEToPINSTR(entryPoint), (LPVOID)PCODEToPINSTR(entryPoint)); - if (val == (TADDR)INVALIDENTRY) - return NULL; - return dac_cast(val); + return m_pCompositeInfo->TryGetMethodDescForEntryPoint(entryPoint); } BOOL ReadyToRunInfo::HasHashtableOfTypes() @@ -313,7 +320,7 @@ PTR_BYTE ReadyToRunInfo::GetDebugInfo(PTR_RUNTIME_FUNCTION pRuntimeFunction) } CONTRACTL_END; - IMAGE_DATA_DIRECTORY * pDebugInfoDir = FindSection(ReadyToRunSectionType::DebugInfo); + IMAGE_DATA_DIRECTORY * pDebugInfoDir = m_pComposite->FindSection(ReadyToRunSectionType::DebugInfo); if (pDebugInfoDir == NULL) return NULL; @@ -332,11 +339,44 @@ PTR_BYTE ReadyToRunInfo::GetDebugInfo(PTR_RUNTIME_FUNCTION pRuntimeFunction) if (lookBack != 0) debugInfoOffset = offset - lookBack; - return dac_cast(m_pLayout->GetBase()) + debugInfoOffset; + return dac_cast(m_pComposite->GetLayout()->GetBase()) + debugInfoOffset; +} + +MethodDesc *ReadyToRunInfo::TryGetMethodDescForEntryPoint(TADDR entryPointRVA) +{ + CONTRACTL + { + GC_NOTRIGGER; + NOTHROW; + SUPPORTS_DAC; + PRECONDITION(!m_isComponentAssembly); + } + CONTRACTL_END; + + TADDR val = (TADDR)m_entryPointToMethodDescMap.LookupValue(PCODEToPINSTR(entryPointRVA), (LPVOID)PCODEToPINSTR(entryPointRVA)); + if (val == (TADDR)INVALIDENTRY) + return NULL; + return dac_cast(val); } #ifndef DACCESS_COMPILE +void ReadyToRunInfo::SetMethodDescForEntryPoint(TADDR entryPointRVA, MethodDesc *methodDesc) +{ + CONTRACTL + { + PRECONDITION(!m_isComponentAssembly); + } + CONTRACTL_END; + + CrstHolder ch(&m_Crst); + + if (m_entryPointToMethodDescMap.LookupValue(PCODEToPINSTR(entryPointRVA), (LPVOID)PCODEToPINSTR(entryPointRVA)) == (LPVOID)INVALIDENTRY) + { + m_entryPointToMethodDescMap.InsertValue(PCODEToPINSTR(entryPointRVA), methodDesc); + } +} + BOOL ReadyToRunInfo::IsReadyToRunEnabled() { WRAPPER_NO_CONTRACT; @@ -408,7 +448,7 @@ static bool AcquireImage(Module * pModule, PEImageLayout * pLayout, READYTORUN_H READYTORUN_IMPORT_SECTION * pImportSections = NULL; READYTORUN_IMPORT_SECTION * pImportSectionsEnd = NULL; READYTORUN_SECTION * pSections = (READYTORUN_SECTION*)(pHeader + 1); - for (DWORD i = 0; i < pHeader->NumberOfSections; i++) + for (DWORD i = 0; i < pHeader->CoreHeader.NumberOfSections; i++) { if (pSections[i].Type == ReadyToRunSectionType::ImportSections) { @@ -444,6 +484,35 @@ static bool AcquireImage(Module * pModule, PEImageLayout * pLayout, READYTORUN_H return false; } +/// +/// Try to locate composite R2R image for a given component module. +/// +static NativeImage *AcquireCompositeImage(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER *pHeader) +{ + READYTORUN_SECTION * pSections = (READYTORUN_SECTION*)(pHeader + 1); + LPCUTF8 ownerCompositeExecutableName = NULL; + for (DWORD i = 0; i < pHeader->CoreHeader.NumberOfSections; i++) + { + if (pSections[i].Type == ReadyToRunSectionType::OwnerCompositeExecutable) + { + ownerCompositeExecutableName = (LPCUTF8)pLayout->GetBase() + pSections[i].Section.VirtualAddress; + break; + } + } + + if (ownerCompositeExecutableName != NULL) + { + AssemblyLoadContext *loadContext = pModule->GetFile()->GetAssemblyLoadContext(); + if (loadContext == nullptr) + { + loadContext = (AssemblyLoadContext *)AppDomain::GetCurrentDomain()->CreateBinderContext(); + } + return loadContext->LoadNativeImage(pModule, ownerCompositeExecutableName); + } + + return NULL; +} + PTR_ReadyToRunInfo ReadyToRunInfo::Initialize(Module * pModule, AllocMemTracker *pamTracker) { STANDARD_VM_CONTRACT; @@ -521,10 +590,23 @@ PTR_ReadyToRunInfo ReadyToRunInfo::Initialize(Module * pModule, AllocMemTracker return NULL; } - if (!AcquireImage(pModule, pLayout, pHeader)) + NativeImage *nativeImage = NULL; + if (pHeader->CoreHeader.Flags & READYTORUN_FLAG_COMPONENT) { - DoLog("Ready to Run disabled - module already loaded in another AppDomain"); - return NULL; + nativeImage = AcquireCompositeImage(pModule, pLayout, pHeader); + if (nativeImage == NULL) + { + DoLog("Ready to Run disabled - composite image not found"); + return NULL; + } + } + else + { + if (!AcquireImage(pModule, pLayout, pHeader)) + { + DoLog("Ready to Run disabled - module already loaded in another AppDomain"); + return NULL; + } } LoaderHeap *pHeap = pModule->GetLoaderAllocator()->GetHighFrequencyHeap(); @@ -532,19 +614,47 @@ PTR_ReadyToRunInfo ReadyToRunInfo::Initialize(Module * pModule, AllocMemTracker DoLog("Ready to Run initialized successfully"); - return new (pMemory) ReadyToRunInfo(pModule, pLayout, pHeader, pamTracker); + return new (pMemory) ReadyToRunInfo(pModule, pLayout, pHeader, nativeImage, pamTracker); } -ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader, AllocMemTracker *pamTracker) - : m_pModule(pModule), m_pLayout(pLayout), m_pHeader(pHeader), m_Crst(CrstReadyToRunEntryPointToMethodDescMap), +ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader, NativeImage *pNativeImage, AllocMemTracker *pamTracker) + : m_pModule(pModule), + m_pHeader(pHeader), + m_pNativeImage(pNativeImage), + m_Crst(CrstReadyToRunEntryPointToMethodDescMap), m_pPersistentInlineTrackingMap(NULL) { STANDARD_VM_CONTRACT; - IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = FindSection(ReadyToRunSectionType::RuntimeFunctions); + if (pNativeImage != NULL) + { + // In multi-assembly composite images, per assembly sections are stored next to their core headers. + m_pCompositeInfo = pNativeImage->GetReadyToRunInfo(); + m_pComposite = m_pCompositeInfo->GetComponentInfo(); + if (pNativeImage->GetComponentAssemblyCount() == 1) + { + // When there's just 1 component assembly in the composite image, we're skipping the + // assembly headers and store all sections directly in the main R2R header. + m_component = *m_pComposite; + } + else + { + m_component = ReadyToRunCoreInfo(m_pComposite->GetLayout(), pNativeImage->GetComponentAssemblyHeader(pModule->GetSimpleName())); + } + m_isComponentAssembly = true; + } + else + { + m_pCompositeInfo = this; + m_component = ReadyToRunCoreInfo(pLayout, &pHeader->CoreHeader); + m_pComposite = &m_component; + m_isComponentAssembly = false; + } + + IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = m_pComposite->FindSection(ReadyToRunSectionType::RuntimeFunctions); if (pRuntimeFunctionsDir != NULL) { - m_pRuntimeFunctions = (T_RUNTIME_FUNCTION *)pLayout->GetDirectoryData(pRuntimeFunctionsDir); + m_pRuntimeFunctions = (T_RUNTIME_FUNCTION *)m_pComposite->GetLayout()->GetDirectoryData(pRuntimeFunctionsDir); m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(T_RUNTIME_FUNCTION); } else @@ -552,10 +662,10 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT m_nRuntimeFunctions = 0; } - IMAGE_DATA_DIRECTORY * pImportSectionsDir = FindSection(ReadyToRunSectionType::ImportSections); + IMAGE_DATA_DIRECTORY * pImportSectionsDir = m_pComposite->FindSection(ReadyToRunSectionType::ImportSections); if (pImportSectionsDir != NULL) { - m_pImportSections = (CORCOMPILE_IMPORT_SECTION*)pLayout->GetDirectoryData(pImportSectionsDir); + m_pImportSections = (CORCOMPILE_IMPORT_SECTION*)m_pComposite->GetLayout()->GetDirectoryData(pImportSectionsDir); m_nImportSections = pImportSectionsDir->Size / sizeof(CORCOMPILE_IMPORT_SECTION); } else @@ -563,29 +673,33 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT m_nImportSections = 0; } - m_nativeReader = NativeReader((byte *)pLayout->GetBase(), pLayout->GetVirtualSize()); + m_nativeReader = NativeReader((BYTE *)m_pComposite->GetLayout()->GetBase(), m_pComposite->GetLayout()->GetVirtualSize()); - IMAGE_DATA_DIRECTORY * pEntryPointsDir = FindSection(ReadyToRunSectionType::MethodDefEntryPoints); + IMAGE_DATA_DIRECTORY * pEntryPointsDir = m_component.FindSection(ReadyToRunSectionType::MethodDefEntryPoints); if (pEntryPointsDir != NULL) { m_methodDefEntryPoints = NativeArray(&m_nativeReader, pEntryPointsDir->VirtualAddress); } - IMAGE_DATA_DIRECTORY * pinstMethodsDir = FindSection(ReadyToRunSectionType::InstanceMethodEntryPoints); + IMAGE_DATA_DIRECTORY * pinstMethodsDir = m_pComposite->FindSection(ReadyToRunSectionType::InstanceMethodEntryPoints); if (pinstMethodsDir != NULL) { NativeParser parser = NativeParser(&m_nativeReader, pinstMethodsDir->VirtualAddress); m_instMethodEntryPoints = NativeHashtable(parser); } - IMAGE_DATA_DIRECTORY * pAvailableTypesDir = FindSection(ReadyToRunSectionType::AvailableTypes); + IMAGE_DATA_DIRECTORY * pAvailableTypesDir = m_component.FindSection(ReadyToRunSectionType::AvailableTypes); if (pAvailableTypesDir != NULL) { NativeParser parser = NativeParser(&m_nativeReader, pAvailableTypesDir->VirtualAddress); m_availableTypesHashtable = NativeHashtable(parser); } + if (!m_isComponentAssembly) { + // For component assemblies we don't initialize the reverse lookup map mapping entry points to MethodDescs; + // we need to use the global map in the composite image ReadyToRunInfo instance to be able to reverse translate + // all methods within the composite image. LockOwner lock = {&m_Crst, IsOwnerOfCrst}; m_entryPointToMethodDescMap.Init(TRUE, &lock); } @@ -593,10 +707,10 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT // For format version 4.1 and later, there is an optional inlining table if (IsImageVersionAtLeast(4, 1)) { - IMAGE_DATA_DIRECTORY* pInlineTrackingInfoDir = FindSection(ReadyToRunSectionType::InliningInfo2); + IMAGE_DATA_DIRECTORY* pInlineTrackingInfoDir = m_pComposite->FindSection(ReadyToRunSectionType::InliningInfo2); if (pInlineTrackingInfoDir != NULL) { - const BYTE* pInlineTrackingMapData = (const BYTE*)GetImage()->GetDirectoryData(pInlineTrackingInfoDir); + const BYTE* pInlineTrackingMapData = (const BYTE*)m_pComposite->GetImage()->GetDirectoryData(pInlineTrackingInfoDir); PersistentInlineTrackingMapR2R2::TryLoad(pModule, pInlineTrackingMapData, pInlineTrackingInfoDir->Size, pamTracker, (PersistentInlineTrackingMapR2R2**)&m_pPersistentInlineTrackingMap); } @@ -605,10 +719,10 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT // For format version 2.1 and later, there is an optional inlining table if (m_pPersistentInlineTrackingMap == nullptr && IsImageVersionAtLeast(2, 1)) { - IMAGE_DATA_DIRECTORY * pInlineTrackingInfoDir = FindSection(ReadyToRunSectionType::InliningInfo); + IMAGE_DATA_DIRECTORY * pInlineTrackingInfoDir = m_pComposite->FindSection(ReadyToRunSectionType::InliningInfo); if (pInlineTrackingInfoDir != NULL) { - const BYTE* pInlineTrackingMapData = (const BYTE*)GetImage()->GetDirectoryData(pInlineTrackingInfoDir); + const BYTE* pInlineTrackingMapData = (const BYTE*)m_pComposite->GetImage()->GetDirectoryData(pInlineTrackingInfoDir); PersistentInlineTrackingMapR2R::TryLoad(pModule, pInlineTrackingMapData, pInlineTrackingInfoDir->Size, pamTracker, &m_pPersistentInlineTrackingMap); } @@ -617,23 +731,23 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT // For format version 2.2 and later, there is an optional profile-data section if (IsImageVersionAtLeast(2, 2)) { - IMAGE_DATA_DIRECTORY * pProfileDataInfoDir = FindSection(ReadyToRunSectionType::ProfileDataInfo); + IMAGE_DATA_DIRECTORY * pProfileDataInfoDir = m_pComposite->FindSection(ReadyToRunSectionType::ProfileDataInfo); if (pProfileDataInfoDir != NULL) { CORCOMPILE_METHOD_PROFILE_LIST * pMethodProfileList; - pMethodProfileList = (CORCOMPILE_METHOD_PROFILE_LIST *)GetImage()->GetDirectoryData(pProfileDataInfoDir); + pMethodProfileList = (CORCOMPILE_METHOD_PROFILE_LIST *)m_pComposite->GetImage()->GetDirectoryData(pProfileDataInfoDir); pModule->SetMethodProfileList(pMethodProfileList); } } // For format version 3.1 and later, there is an optional attributes section - IMAGE_DATA_DIRECTORY *attributesPresenceDataInfoDir = FindSection(ReadyToRunSectionType::AttributePresence); + IMAGE_DATA_DIRECTORY *attributesPresenceDataInfoDir = m_component.FindSection(ReadyToRunSectionType::AttributePresence); if (attributesPresenceDataInfoDir != NULL) { NativeCuckooFilter newFilter( - (byte *)pLayout->GetBase(), - pLayout->GetVirtualSize(), + (BYTE *)m_pComposite->GetLayout()->GetBase(), + m_pComposite->GetLayout()->GetVirtualSize(), attributesPresenceDataInfoDir->VirtualAddress, attributesPresenceDataInfoDir->Size); @@ -769,7 +883,7 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig if (fFixups) { - if (!m_pModule->FixupDelayList(dac_cast(m_pLayout->GetBase()) + offset)) + if (!m_pModule->FixupDelayList(dac_cast(GetImage()->GetBase()) + offset)) { #ifndef CROSSGEN_COMPILE pConfig->SetReadyToRunRejectedPrecompiledCode(); @@ -786,14 +900,8 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig } _ASSERTE(id < m_nRuntimeFunctions); - pEntryPoint = dac_cast(m_pLayout->GetBase()) + m_pRuntimeFunctions[id].BeginAddress; - - { - CrstHolder ch(&m_Crst); - - if (m_entryPointToMethodDescMap.LookupValue(PCODEToPINSTR(pEntryPoint), (LPVOID)PCODEToPINSTR(pEntryPoint)) == (LPVOID)INVALIDENTRY) - m_entryPointToMethodDescMap.InsertValue(PCODEToPINSTR(pEntryPoint), pMD); - } + pEntryPoint = dac_cast(GetImage()->GetBase()) + m_pRuntimeFunctions[id].BeginAddress; + m_pCompositeInfo->SetMethodDescForEntryPoint(pEntryPoint, pMD); #ifndef CROSSGEN_COMPILE #ifdef PROFILING_SUPPORTED @@ -823,7 +931,6 @@ done: return pEntryPoint; } - void ReadyToRunInfo::MethodIterator::ParseGenericMethodSignatureAndRid(uint *pOffset, RID *pRid) { _ASSERTE(!m_genericParser.IsNull()); @@ -987,7 +1094,7 @@ MethodDesc * ReadyToRunInfo::MethodIterator::GetMethodDesc_NoRestore() } _ASSERTE(id < m_pInfo->m_nRuntimeFunctions); - PCODE pEntryPoint = dac_cast(m_pInfo->m_pLayout->GetBase()) + m_pInfo->m_pRuntimeFunctions[id].BeginAddress; + PCODE pEntryPoint = dac_cast(m_pInfo->GetImage()->GetBase()) + m_pInfo->m_pRuntimeFunctions[id].BeginAddress; return m_pInfo->GetMethodDescForEntryPoint(pEntryPoint); } @@ -1025,9 +1132,9 @@ DWORD ReadyToRunInfo::GetFieldBaseOffset(MethodTable * pMT) BOOL ReadyToRunInfo::IsImageVersionAtLeast(int majorVersion, int minorVersion) { - LIMITED_METHOD_CONTRACT; - return (m_pHeader->MajorVersion == majorVersion && m_pHeader->MinorVersion >= minorVersion) || - (m_pHeader->MajorVersion > majorVersion); + LIMITED_METHOD_CONTRACT; + return (m_pHeader->MajorVersion == majorVersion && m_pHeader->MinorVersion >= minorVersion) || + (m_pHeader->MajorVersion > majorVersion); } diff --git a/src/coreclr/src/vm/readytoruninfo.h b/src/coreclr/src/vm/readytoruninfo.h index 11cabd09320..e9d7d1e9f29 100644 --- a/src/coreclr/src/vm/readytoruninfo.h +++ b/src/coreclr/src/vm/readytoruninfo.h @@ -18,17 +18,43 @@ typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION; +class NativeImage; class PrepareCodeConfig; +typedef DPTR(class ReadyToRunCoreInfo) PTR_ReadyToRunCoreInfo; +class ReadyToRunCoreInfo +{ +private: + PTR_PEImageLayout m_pLayout; + PTR_READYTORUN_CORE_HEADER m_pCoreHeader; + +public: + ReadyToRunCoreInfo(); + ReadyToRunCoreInfo(PEImageLayout * pLayout, READYTORUN_CORE_HEADER * pCoreHeader); + + PEImageLayout * GetLayout() const { return m_pLayout; } + IMAGE_DATA_DIRECTORY * FindSection(ReadyToRunSectionType type) const; + + PTR_PEImageLayout GetImage() const + { + LIMITED_METHOD_CONTRACT; + return m_pLayout; + } +}; + typedef DPTR(class ReadyToRunInfo) PTR_ReadyToRunInfo; class ReadyToRunInfo { friend class ReadyToRunJitManager; PTR_Module m_pModule; - - PTR_PEImageLayout m_pLayout; PTR_READYTORUN_HEADER m_pHeader; + bool m_isComponentAssembly; + NativeImage* m_pNativeImage; + ReadyToRunInfo* m_pCompositeInfo; + + ReadyToRunCoreInfo m_component; + const ReadyToRunCoreInfo* m_pComposite; PTR_RUNTIME_FUNCTION m_pRuntimeFunctions; DWORD m_nRuntimeFunctions; @@ -40,6 +66,7 @@ class ReadyToRunInfo NativeFormat::NativeArray m_methodDefEntryPoints; NativeFormat::NativeHashtable m_instMethodEntryPoints; NativeFormat::NativeHashtable m_availableTypesHashtable; + NativeFormat::NativeHashtable m_pMetaDataHashtable; NativeFormat::NativeCuckooFilter m_attributesPresence; @@ -48,13 +75,19 @@ class ReadyToRunInfo PTR_PersistentInlineTrackingMapR2R m_pPersistentInlineTrackingMap; - ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader, AllocMemTracker *pamTracker); - public: + ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader, NativeImage * pNativeImage, AllocMemTracker *pamTracker); + static BOOL IsReadyToRunEnabled(); static PTR_ReadyToRunInfo Initialize(Module * pModule, AllocMemTracker *pamTracker); + bool IsComponentAssembly() const { return m_isComponentAssembly; } + NativeImage * GetNativeImage() const { return m_pNativeImage; } + + PTR_PEImageLayout GetImage() const { return m_pComposite->GetImage(); } + IMAGE_DATA_DIRECTORY * FindSection(ReadyToRunSectionType type) const { return m_pComposite->FindSection(type); } + PCODE GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig, BOOL fFixups); MethodDesc * GetMethodDescForEntryPoint(PCODE entryPoint); @@ -65,29 +98,21 @@ public: BOOL SkipTypeValidation() { LIMITED_METHOD_CONTRACT; - return m_pHeader->Flags & READYTORUN_FLAG_SKIP_TYPE_VALIDATION; + return m_pHeader->CoreHeader.Flags & READYTORUN_FLAG_SKIP_TYPE_VALIDATION; } BOOL IsPartial() { LIMITED_METHOD_CONTRACT; - return m_pHeader->Flags & READYTORUN_FLAG_PARTIAL; + return m_pHeader->CoreHeader.Flags & READYTORUN_FLAG_PARTIAL; } BOOL HasNonShareablePInvokeStubs() { LIMITED_METHOD_CONTRACT; - return m_pHeader->Flags & READYTORUN_FLAG_NONSHARED_PINVOKE_STUBS; + return m_pHeader->CoreHeader.Flags & READYTORUN_FLAG_NONSHARED_PINVOKE_STUBS; } - PTR_PEImageLayout GetImage() - { - LIMITED_METHOD_CONTRACT; - return m_pLayout; - } - - IMAGE_DATA_DIRECTORY * FindSection(ReadyToRunSectionType type); - PTR_CORCOMPILE_IMPORT_SECTION GetImportSections(COUNT_T * pCount) { LIMITED_METHOD_CONTRACT; @@ -171,7 +196,12 @@ private: BOOL GetTypeNameFromToken(IMDInternalImport * pImport, mdToken mdType, LPCUTF8 * ppszName, LPCUTF8 * ppszNameSpace); BOOL GetEnclosingToken(IMDInternalImport * pImport, mdToken mdType, mdToken * pEnclosingToken); BOOL CompareTypeNameOfTokens(mdToken mdToken1, IMDInternalImport * pImport1, mdToken mdToken2, IMDInternalImport * pImport2); - BOOL IsImageVersionAtLeast(int majorVersion, int minorVersion); + BOOL IsImageVersionAtLeast(int majorVersion, int minorVersion); + + MethodDesc *TryGetMethodDescForEntryPoint(TADDR entryPointRVA); + void SetMethodDescForEntryPoint(TADDR entryPointRVA, MethodDesc *methodDesc); + + ReadyToRunCoreInfo *GetComponentInfo() { return &m_component; } }; class DynamicHelpers diff --git a/src/coreclr/src/vm/zapsig.cpp b/src/coreclr/src/vm/zapsig.cpp index 766bb5c3fb3..e07520cdde2 100644 --- a/src/coreclr/src/vm/zapsig.cpp +++ b/src/coreclr/src/vm/zapsig.cpp @@ -15,6 +15,7 @@ #include "typedesc.h" #include "compile.h" #include "sigbuilder.h" +#include "nativeimage.h" #ifndef DACCESS_COMPILE @@ -625,34 +626,41 @@ Module *ZapSig::DecodeModuleFromIndex(Module *fromModule, CONTRACTL_END; Assembly *pAssembly = NULL; + NativeImage *nativeImage = fromModule->GetCompositeNativeImage(); + uint32_t assemblyRefMax = (nativeImage != NULL ? 0 : fromModule->GetAssemblyRefMax()); - if (index == 0) + if (index < assemblyRefMax) { - pAssembly = fromModule->GetAssembly(); - } - else - { - if (index < fromModule->GetAssemblyRefMax()) + if (index == 0) { - pAssembly = fromModule->LoadAssembly(RidToToken(index, mdtAssemblyRef))->GetAssembly(); + pAssembly = fromModule->GetAssembly(); } else { - index -= fromModule->GetAssemblyRefMax(); + pAssembly = fromModule->LoadAssembly(RidToToken(index, mdtAssemblyRef))->GetAssembly(); + } + } + else + { + index -= assemblyRefMax; - pAssembly = fromModule->GetNativeMetadataAssemblyRefFromCache(index); + pAssembly = fromModule->GetNativeMetadataAssemblyRefFromCache(index); - if(pAssembly == NULL) + if(pAssembly == NULL) + { + if (nativeImage != NULL) + { + pAssembly = nativeImage->LoadComponentAssembly(index); + } + else { AssemblySpec spec; spec.InitializeSpec(TokenFromRid(index, mdtAssemblyRef), - fromModule->GetNativeAssemblyImport(), - NULL); - + fromModule->GetNativeAssemblyImport(), + NULL); pAssembly = spec.LoadAssembly(FILE_LOADED); - - fromModule->SetNativeMetadataAssemblyRefInCache(index, pAssembly); } + fromModule->SetNativeMetadataAssemblyRefInCache(index, pAssembly); } } @@ -673,87 +681,92 @@ Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule, Assembly *pAssembly = NULL; mdAssemblyRef tkAssemblyRef; - if (index == 0) - pAssembly = fromModule->GetAssembly(); - else + NativeImage *nativeImage = fromModule->GetCompositeNativeImage(); + uint32_t assemblyRefMax = (nativeImage != NULL ? 0 : fromModule->GetAssemblyRefMax()); + + if (index < assemblyRefMax) { - if (index < fromModule->GetAssemblyRefMax()) + if (index == 0) { - tkAssemblyRef = RidToToken(index, mdtAssemblyRef); - pAssembly = fromModule->GetAssemblyIfLoaded(tkAssemblyRef); + pAssembly = fromModule->GetAssembly(); } else { - index -= fromModule->GetAssemblyRefMax(); - tkAssemblyRef = RidToToken(index, mdtAssemblyRef); - IMDInternalImport * pMDImportOverride = fromModule->GetNativeAssemblyImport(FALSE); - if (pMDImportOverride != NULL) + pAssembly = fromModule->GetAssemblyIfLoaded(RidToToken(index, mdtAssemblyRef)); + } + } + else + { + index -= assemblyRefMax; + tkAssemblyRef = RidToToken(index, mdtAssemblyRef); + IMDInternalImport * pMDImportOverride = (nativeImage != NULL + ? nativeImage->GetManifestMetadata() : fromModule->GetNativeAssemblyImport(FALSE)); + if (pMDImportOverride != NULL) + { + CHAR szFullName[MAX_CLASS_NAME + 1]; + LPCSTR szWinRtNamespace = NULL; + LPCSTR szWinRtClassName = NULL; + + BOOL fValidAssemblyRef = TRUE; + LPCSTR pAssemblyName; + DWORD dwFlags; + if (FAILED(pMDImportOverride->GetAssemblyRefProps(tkAssemblyRef, + NULL, + NULL, + &pAssemblyName, + NULL, + NULL, + NULL, + &dwFlags))) + { // Unexpected failure reading MetaData + fValidAssemblyRef = FALSE; + } + + if (fValidAssemblyRef && IsAfContentType_WindowsRuntime(dwFlags)) { - CHAR szFullName[MAX_CLASS_NAME + 1]; - LPCSTR szWinRtNamespace = NULL; - LPCSTR szWinRtClassName = NULL; - - BOOL fValidAssemblyRef = TRUE; - LPCSTR pAssemblyName; - DWORD dwFlags; - if (FAILED(pMDImportOverride->GetAssemblyRefProps(tkAssemblyRef, - NULL, - NULL, - &pAssemblyName, - NULL, - NULL, - NULL, - &dwFlags))) - { // Unexpected failure reading MetaData - fValidAssemblyRef = FALSE; - } + // Find the encoded type name + LPCSTR pTypeName = NULL; + if (pAssemblyName != NULL) + pTypeName = strchr(pAssemblyName, '!'); - if (fValidAssemblyRef && IsAfContentType_WindowsRuntime(dwFlags)) + if (pTypeName != NULL) { - // Find the encoded type name - LPCSTR pTypeName = NULL; - if (pAssemblyName != NULL) - pTypeName = strchr(pAssemblyName, '!'); + pTypeName++; + // pTypeName now contains the full type name (namespace + name) - if (pTypeName != NULL) + strcpy_s(szFullName, _countof(szFullName), pTypeName); + LPSTR pszName = strrchr(szFullName, '.'); + + // WinRT types must have a namespace + if (pszName != NULL) { - pTypeName++; - // pTypeName now contains the full type name (namespace + name) - - strcpy_s(szFullName, _countof(szFullName), pTypeName); - LPSTR pszName = strrchr(szFullName, '.'); - - // WinRT types must have a namespace - if (pszName != NULL) - { - // Replace . between namespace and name with null terminator. - // This breaks the string into a namespace and name pair. - *pszName = '\0'; - pszName++; - - szWinRtNamespace = szFullName; - szWinRtClassName = pszName; - } - else - { // Namespace '.' separator not found - invalid type name (namespace has to be always present) - fValidAssemblyRef = FALSE; - } + // Replace . between namespace and name with null terminator. + // This breaks the string into a namespace and name pair. + *pszName = '\0'; + pszName++; + + szWinRtNamespace = szFullName; + szWinRtClassName = pszName; } else - { // Type name separator in assembly name '!' not found + { // Namespace '.' separator not found - invalid type name (namespace has to be always present) fValidAssemblyRef = FALSE; } } - - if (fValidAssemblyRef) - { - pAssembly = fromModule->GetAssemblyIfLoaded( - tkAssemblyRef, - szWinRtNamespace, - szWinRtClassName, - pMDImportOverride); + else + { // Type name separator in assembly name '!' not found + fValidAssemblyRef = FALSE; } } + + if (fValidAssemblyRef) + { + pAssembly = fromModule->GetAssemblyIfLoaded( + tkAssemblyRef, + szWinRtNamespace, + szWinRtClassName, + pMDImportOverride); + } } } diff --git a/src/coreclr/src/zap/zapreadytorun.cpp b/src/coreclr/src/zap/zapreadytorun.cpp index be35b33c3fd..78f57814213 100644 --- a/src/coreclr/src/zap/zapreadytorun.cpp +++ b/src/coreclr/src/zap/zapreadytorun.cpp @@ -38,16 +38,16 @@ void ZapReadyToRunHeader::Save(ZapWriter * pZapWriter) readyToRunHeader.MinorVersion = READYTORUN_MINOR_VERSION; if (pImage->m_ModuleDecoder.IsPlatformNeutral()) - readyToRunHeader.Flags |= READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE; + readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE; // If all types loaded succesfully, set a flag to skip type loading sanity checks at runtime if (pImage->GetCompileInfo()->AreAllClassesFullyLoaded(pImage->GetModuleHandle())) - readyToRunHeader.Flags |= READYTORUN_FLAG_SKIP_TYPE_VALIDATION; + readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_SKIP_TYPE_VALIDATION; if (pImage->GetZapperOptions()->m_fPartialNGen) - readyToRunHeader.Flags |= READYTORUN_FLAG_PARTIAL; + readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_PARTIAL; - readyToRunHeader.NumberOfSections = m_Sections.GetCount(); + readyToRunHeader.CoreHeader.NumberOfSections = m_Sections.GetCount(); pZapWriter->Write(&readyToRunHeader, sizeof(readyToRunHeader));