1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-09 17:44:48 +09:00

Runtime composite support, 2nd attempt (fixing DAC) (#33304)

[2nd attempt after the initial version was rolled back]

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
This commit is contained in:
Tomáš Rylek 2020-03-07 01:59:23 +01:00 committed by GitHub
parent 3d6f8a26cb
commit 0c610c5de7
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1103 additions and 405 deletions

View file

@ -706,3 +706,6 @@ Crst MethodDescBackpatchInfoTracker
AcquiredBefore FuncPtrStubs ThreadStore SystemDomain
AcquiredAfter ReJITGlobalRequest
End
Crst NativeImageEagerFixups
End

View 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",

View 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();

View 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

View file

@ -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

View 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()));
}
}
}

View 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)
{

View 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();
}
}

View 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;
@ -640,7 +641,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);
}
}
}
@ -817,7 +818,7 @@ namespace ILCompiler.Reflection.ReadyToRun
if (_readyToRunAssemblyHeaders[assemblyIndex].Sections.TryGetValue(
ReadyToRunSectionType.AvailableTypes, out availableTypesSection))
{
ParseAvailableTypesSection(availableTypesSection, OpenReferenceAssembly(assemblyIndex + 2));
ParseAvailableTypesSection(availableTypesSection, OpenReferenceAssembly(assemblyIndex + 1));
}
}
}
@ -1058,9 +1059,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);
@ -1068,7 +1069,7 @@ namespace ILCompiler.Reflection.ReadyToRun
else
{
metadataReader = ManifestReader;
assemblyReferenceHandle = ManifestReferences[refAsmIndex - assemblyRefCount - 2];
assemblyReferenceHandle = ManifestReferences[refAsmIndex - assemblyRefCount - 1];
}
return assemblyReferenceHandle;

View 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);

View 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));

View 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

View 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

View 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

View 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;
}
@ -10451,6 +10464,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++)

View 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;
@ -3226,11 +3233,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

View file

@ -61,6 +61,7 @@ set(VM_CROSSGEN_SOURCES
../methodtablebuilder.cpp
../mlinfo.cpp
../mscorlib.cpp
../nativeimage.cpp
../olevariant.cpp
../pefile.cpp
../peimage.cpp

View file

@ -2314,6 +2314,4 @@ DomainAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
}
}
#endif // #ifdef DACCESS_COMPILE

View file

@ -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

View file

@ -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

View file

@ -193,6 +193,7 @@ public:
BOOL HasCorHeader();
BOOL HasReadyToRunHeader();
BOOL IsReferenceAssembly();
BOOL IsComponentAssembly();
#ifdef FEATURE_PREJIT
BOOL IsNativeILILOnly();
BOOL IsNativeILDll();

View 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;

View 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,11 +635,48 @@ 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();
}
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
PEImageLayout::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)

View 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_

View file

@ -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<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));
@ -43,7 +53,7 @@ IMAGE_DATA_DIRECTORY * ReadyToRunInfo::FindSection(ReadyToRunSectionType type)
return NULL;
}
MethodDesc * ReadyToRunInfo::GetMethodDescForEntryPoint(PCODE entryPoint)
PTR_MethodDesc ReadyToRunInfo::GetMethodDescForEntryPoint(PCODE entryPoint)
{
CONTRACTL
{
@ -53,17 +63,7 @@ MethodDesc * ReadyToRunInfo::GetMethodDescForEntryPoint(PCODE entryPoint)
}
CONTRACTL_END;
#if defined(TARGET_AMD64) || (defined(TARGET_X86) && defined(TARGET_UNIX))
// A normal method entry point is always 8 byte aligned, but a funclet can start at an odd address.
// Since PtrHashMap can't handle odd pointers, check for this case and return NULL.
if ((entryPoint & 0x1) != 0)
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->GetMethodDescForEntryPointInNativeImage(entryPoint);
}
BOOL ReadyToRunInfo::HasHashtableOfTypes()
@ -313,7 +313,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 +332,52 @@ 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;
}
PTR_MethodDesc ReadyToRunInfo::GetMethodDescForEntryPointInNativeImage(PCODE entryPoint)
{
CONTRACTL
{
GC_NOTRIGGER;
NOTHROW;
SUPPORTS_DAC;
PRECONDITION(!m_isComponentAssembly);
}
CONTRACTL_END;
#if defined(TARGET_AMD64) || (defined(TARGET_X86) && defined(TARGET_UNIX))
// A normal method entry point is always 8 byte aligned, but a funclet can start at an odd address.
// Since PtrHashMap can't handle odd pointers, check for this case and return NULL.
if ((entryPoint & 0x1) != 0)
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);
}
#ifndef DACCESS_COMPILE
void ReadyToRunInfo::SetMethodDescForEntryPointInNativeImage(PCODE entryPoint, MethodDesc *methodDesc)
{
CONTRACTL
{
PRECONDITION(!m_isComponentAssembly);
}
CONTRACTL_END;
CrstHolder ch(&m_Crst);
if ((TADDR)m_entryPointToMethodDescMap.LookupValue(PCODEToPINSTR(entryPoint), (LPVOID)PCODEToPINSTR(entryPoint)) == (TADDR)INVALIDENTRY)
{
m_entryPointToMethodDescMap.InsertValue(PCODEToPINSTR(entryPoint), methodDesc);
}
}
BOOL ReadyToRunInfo::IsReadyToRunEnabled()
{
WRAPPER_NO_CONTRACT;
@ -408,7 +449,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 +485,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 +591,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 +615,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 +663,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 +674,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 +708,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 +720,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 +732,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 +884,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 +901,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->SetMethodDescForEntryPointInNativeImage(pEntryPoint, pMD);
#ifndef CROSSGEN_COMPILE
#ifdef PROFILING_SUPPORTED
@ -823,7 +932,6 @@ done:
return pEntryPoint;
}
void ReadyToRunInfo::MethodIterator::ParseGenericMethodSignatureAndRid(uint *pOffset, RID *pRid)
{
_ASSERTE(!m_genericParser.IsNull());
@ -987,7 +1095,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 +1133,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);
}

View file

@ -15,20 +15,50 @@
#include "nativeformatreader.h"
#include "inlinetracking.h"
#include "wellknownattributes.h"
#include "nativeimage.h"
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);
PTR_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;
typedef DPTR(class ReadyToRunCoreInfo) PTR_ReadyToRunCoreInfo;
typedef DPTR(class NativeImage) PTR_NativeImage;
class ReadyToRunInfo
{
friend class ReadyToRunJitManager;
PTR_Module m_pModule;
PTR_PEImageLayout m_pLayout;
PTR_READYTORUN_HEADER m_pHeader;
bool m_isComponentAssembly;
PTR_NativeImage m_pNativeImage;
PTR_ReadyToRunInfo m_pCompositeInfo;
ReadyToRunCoreInfo m_component;
PTR_ReadyToRunCoreInfo m_pComposite;
PTR_RUNTIME_FUNCTION m_pRuntimeFunctions;
DWORD m_nRuntimeFunctions;
@ -40,6 +70,7 @@ class ReadyToRunInfo
NativeFormat::NativeArray m_methodDefEntryPoints;
NativeFormat::NativeHashtable m_instMethodEntryPoints;
NativeFormat::NativeHashtable m_availableTypesHashtable;
NativeFormat::NativeHashtable m_pMetaDataHashtable;
NativeFormat::NativeCuckooFilter m_attributesPresence;
@ -48,16 +79,23 @@ 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; }
PTR_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);
PTR_MethodDesc GetMethodDescForEntryPoint(PCODE entryPoint);
BOOL HasHashtableOfTypes();
BOOL TryLookupTypeTokenFromName(const NameHandle *pName, mdToken * pFoundTypeToken);
@ -65,29 +103,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 +201,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);
PTR_MethodDesc GetMethodDescForEntryPointInNativeImage(PCODE entryPoint);
void SetMethodDescForEntryPointInNativeImage(PCODE entryPoint, PTR_MethodDesc methodDesc);
PTR_ReadyToRunCoreInfo GetComponentInfo() { return dac_cast<PTR_ReadyToRunCoreInfo>(&m_component); }
};
class DynamicHelpers

View 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;
// Find the encoded type name
LPCSTR pTypeName = NULL;
if (pAssemblyName != NULL)
pTypeName = strchr(pAssemblyName, '!');
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))
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)
// Replace . between namespace and name with null terminator.
// This breaks the string into a namespace and name pair.
*pszName = '\0';
pszName++;
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;
}
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);
}
}
}

View 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));