Initial runtime changes for composite support (#32500)
authorTomáš Rylek <trylek@microsoft.com>
Wed, 4 Mar 2020 14:28:31 +0000 (15:28 +0100)
committerGitHub <noreply@github.com>
Wed, 4 Mar 2020 14:28:31 +0000 (15:28 +0100)
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

28 files changed:
src/coreclr/src/inc/CrstTypes.def
src/coreclr/src/inc/crsttypes.h
src/coreclr/src/inc/pedecoder.h
src/coreclr/src/inc/pedecoder.inl
src/coreclr/src/inc/readytorun.h
src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/OwnerCompositeExecutableNode.cs
src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
src/coreclr/src/tools/r2rdump/TextDumper.cs
src/coreclr/src/utilcode/pedecoder.cpp
src/coreclr/src/vm/CMakeLists.txt
src/coreclr/src/vm/assemblyloadcontext.cpp
src/coreclr/src/vm/assemblyloadcontext.h
src/coreclr/src/vm/ceeload.cpp
src/coreclr/src/vm/ceeload.h
src/coreclr/src/vm/crossgen/CMakeLists.txt
src/coreclr/src/vm/domainfile.cpp
src/coreclr/src/vm/nativeimage.cpp [new file with mode: 0644]
src/coreclr/src/vm/nativeimage.h [new file with mode: 0644]
src/coreclr/src/vm/peimage.h
src/coreclr/src/vm/peimage.inl
src/coreclr/src/vm/peimagelayout.cpp
src/coreclr/src/vm/peimagelayout.h
src/coreclr/src/vm/readytoruninfo.cpp
src/coreclr/src/vm/readytoruninfo.h
src/coreclr/src/vm/zapsig.cpp
src/coreclr/src/zap/zapreadytorun.cpp

index 57119c01959c884066d7d535c098e87e8ef9797d..cf53f5bdd24ad0d73c718bd2ab7d663f2fd00401 100644 (file)
@@ -706,3 +706,6 @@ Crst MethodDescBackpatchInfoTracker
     AcquiredBefore FuncPtrStubs ThreadStore SystemDomain
     AcquiredAfter ReJITGlobalRequest
 End
+
+Crst NativeImageEagerFixups
+End
index 79cf46b5445e05af758d9779d1682f8c294cd7f6..4bc0665602dbfe727522dbdbeff0a7a7a07e0c60 100644 (file)
@@ -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",
index 42d6eca9a50f485a479541af104156b3f0ba04ad..ad0e77e532c15759711672f41d5c21e4b9bb03bf 100644 (file)
@@ -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();
index c9ea3f7abf64e051d00817c5dc8063bcff42da8f..09bcfd76a146b9a8c199cfe91cb1ca5f2ccdd17e 100644 (file)
@@ -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
index 7df03784ced816662b5da06b804c4850421b7284..dac75daf9c2e6f1f3d7ce2822fe07720f3ea5f07 100644 (file)
 // 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
index ee0c439e6d04ed9cf8853ad1e9ee87710e89acaf..e528996a964b5e2f6f081eb2ab9ce65454ad8d2c 100644 (file)
@@ -21,11 +21,15 @@ namespace ReadyToRun.SuperIlc
         {
             "coreclr",
             "clrjit",
-            "mscorrc",
             "mscordaccore",
             "mscordbi",
         };
 
+        private static string[] s_runtimeWindowsOnlyLibraries =
+        {
+            "mscorrc",
+        };
+
         private List<string> _compilationInputFiles;
 
         private List<string> _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()));
+                    }
                 }
             }
 
index 73ce2bfe03fcb4f83fb3c9a8b2ceee079c301940..d01315059a6e16513bc15955436b5eb4e42b3585 100644 (file)
@@ -74,27 +74,28 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
             _moduleIdToAssemblyNameMap = new Dictionary<int, AssemblyName>();
             _signatureEmitters = new List<ISignatureEmitter>();
             _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)
                 {
index bc79b4402f49196f811f2c1a370a1f69750edf00..1c71fc82609198544de8961435d57009419d91f7 100644 (file)
@@ -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();
         }
     }
index 983a624d43ede008f235f4531720fac70886d9bb..9705b5d39789d2d7ee9fa7318ad944d3aa3804f7 100644 (file)
@@ -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;
index 1b3cf275685af12f6c087ee84621ddfadceffa85..9b0d8416610e0fe0c83159539229b4ed9d9560f8 100644 (file)
@@ -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);
index 11563ddd556f3a57093dcd75308ec374d008fbd0..3ba2f15d9c69c73d826459ab60e1325279d56dbe 100644 (file)
@@ -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<PEDecoder *>(this)->m_pReadyToRunHeader = pHeader;
+            const_cast<PEDecoder*>(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<PTR_READYTORUN_SECTION>(dac_cast<TADDR>(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));
index ac8d660428a3f65bc98ca37f08247ec67c957721..43b9bc34519615a0705cbea8e381ed5dd40522d2 100644 (file)
@@ -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
index 40cb2432c0a6c8f447631c439768380b6df3117d..d5adfffbd0943c9eb3bdeae624d9fb41926ebd8b 100644 (file)
@@ -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<UINT_PTR>(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
index 395e697562ea395f52a4c95e083320a9a1c177b4..85b4f30d09ac57c232977bece3154339154a45f1 100644 (file)
@@ -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<NativeImage *> m_nativeImages;
 };
 
 #endif
index 31cea51c7979a08f414c07f338a66d2378a38648..df5b2ef1826aee32aafa433b48f96fdfdc6ea22a 100644 (file)
@@ -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++)
index 86b3fe347a22dacb7f20937b06033c9256cc9933..52393b0046ee59786e2d16eea9f79f9637f3b63b 100644 (file)
@@ -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
index d223da0205dbed3b43fc0bf1e5d35e68443e9798..6a42ab503b21f9b30cf9201b5718da1f1eacb1c0 100644 (file)
@@ -61,6 +61,7 @@ set(VM_CROSSGEN_SOURCES
   ../methodtablebuilder.cpp
   ../mlinfo.cpp
   ../mscorlib.cpp
+  ../nativeimage.cpp
   ../olevariant.cpp
   ../pefile.cpp
   ../peimage.cpp
index 4292a440242579cdea11f17cdb3c5895dc95305e..1045ca2304c1a7b94c5595c6063555f7947c1703 100644 (file)
@@ -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 (file)
index 0000000..7cda619
--- /dev/null
@@ -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 <shlwapi.h>
+
+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<PEImageLayout> 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<NativeImage> 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 (file)
index 0000000..2c3f538
--- /dev/null
@@ -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<AssemblyNameIndex> >
+{
+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<AssemblyNameIndexHashTraits> 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
index ad7a30d6c002d4c09a7837ef7bce1683afd8255b..1edf05d8ec21759abafa0fd950eb5d99b05a2547 100644 (file)
@@ -193,6 +193,7 @@ public:
     BOOL HasCorHeader();
     BOOL HasReadyToRunHeader();
     BOOL IsReferenceAssembly();
+    BOOL IsComponentAssembly();
 #ifdef FEATURE_PREJIT
     BOOL IsNativeILILOnly();
     BOOL IsNativeILDll();
index cda9ef1006673d902c516f9a3ccc80049c2bfd70..03d8bc229ce05e92cab91f2bed469d12e2b6a48d 100644 (file)
@@ -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;
index 94f73419a40e995f578ed564fd6568a4cad32b11..79739716da430d4e9ef81ad216662f1c8fcbcd14 100644 (file)
@@ -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
index c8f9adfc9403f752b94531835cd6a2e965ac21f6..9ae14c4b74e5416f10856d32aad8109c489d436d 100644 (file)
@@ -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_
 
index 99b252056a3a732664a1523aa75700f1ec15b5c1..0ff97ada274757c4a266ad092ebeeb86c165ac82 100644 (file)
 #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<PTR_READYTORUN_SECTION>(dac_cast<TADDR>(m_pHeader) + sizeof(READYTORUN_HEADER));
-    for (DWORD i = 0; i < m_pHeader->NumberOfSections; i++)
+    PTR_READYTORUN_SECTION pSections = dac_cast<PTR_READYTORUN_SECTION>(dac_cast<TADDR>(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<PTR_MethodDesc>(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<PTR_BYTE>(m_pLayout->GetBase()) + debugInfoOffset;
+    return dac_cast<PTR_BYTE>(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<PTR_MethodDesc>(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;
 }
 
+/// <summary>
+/// Try to locate composite R2R image for a given component module.
+/// </summary>
+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<TADDR>(m_pLayout->GetBase()) + offset))
+            if (!m_pModule->FixupDelayList(dac_cast<TADDR>(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<TADDR>(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<TADDR>(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<TADDR>(m_pInfo->m_pLayout->GetBase()) + m_pInfo->m_pRuntimeFunctions[id].BeginAddress;
+    PCODE pEntryPoint = dac_cast<TADDR>(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);
 
 }
 
index 11cabd0932030bd1d28465a0eecba0bb82da833d..e9d7d1e9f29a64109689870b176547c401eb2e89 100644 (file)
 
 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
index 766bb5c3fb30de33180013ef6ef28e77820a4175..e07520cdde2609cde8fbfcb79d935e8e86360965 100644 (file)
@@ -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);
+            }
         }
     }
 
index be35b33c3fd00e6bfb38bedfd18950c017028585..78f578142139229d3d6b3a9cf2b1c08e31ef854c 100644 (file)
@@ -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));