Skip to content

Commit 1e05521

Browse files
committed
R2RDump support for MVIDs; R2R format update; various minor fixes
(*) Renamed 'ComponentAssemblyMvids' to 'ManifestAssemblyMvids' to better express the fact that the MVID table is parallel to the manifest metadata. (*) Added basic R2RDump support for dumping the manifest assembly MVID table. (*) Fixed R2R format version number in Crossgen2. Thanks Tomas
1 parent 0d634c2 commit 1e05521

File tree

10 files changed

+78
-27
lines changed

10 files changed

+78
-27
lines changed

docs/design/coreclr/botr/readytorun-format.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Revisions:
55
* 1.1 - [Jan Kotas](https://github.com/jkotas) - 2015
66
* 3.1 - [Tomas Rylek](https://github.com/trylek) - 2019
77
* 4.1 - [Tomas Rylek](https://github.com/trylek) - 2020
8+
* 5.3 - [Tomas Rylek](https://github.com/trylek) - 2021
89

910
# Introduction
1011

@@ -161,6 +162,8 @@ The following section types are defined and described later in this document:
161162
| InliningInfo2 | 114 | Image (added in V4.1)
162163
| ComponentAssemblies | 115 | Image (added in V4.1)
163164
| OwnerCompositeExecutable | 116 | Image (added in V4.1)
165+
| PgoInstrumentationData | 117 | Image (added in V5.2)
166+
| ManifestAssemblyMvids | 118 | Image (added in V5.3)
164167

165168
## ReadyToRunSectionType.CompilerIdentifier
166169

@@ -540,6 +543,17 @@ the `OwnerCompositeExecutable` section that contains a UTF-8 string encoding the
540543
composite R2R executable this MSIL belongs to with extension (without path). Runtime uses this
541544
information to locate the composite R2R executable with the compiled native code when loading the MSIL.
542545

546+
## ReadyToRunSectionType.PgoInstrumentationData (v5.2+)
547+
548+
**TODO**: document PGO instrumentation data
549+
550+
## ReadyToRunSectionType.ManifestAssemblyMvids (v5.3+)
551+
552+
This section is a binary array of 16-byte MVID records, one for each assembly in the manifest metadata.
553+
Number of assemblies stored in the manifest metadata is equal to the number of MVID records in the array.
554+
MVID records are used at runtime to verify that the assemblies loaded match those referenced by the
555+
manifest metadata representing the versioning bubble.
556+
543557
# Native Format
544558

545559
Native format is set of encoding patterns that allow persisting type system data in a binary format that is

src/coreclr/inc/readytorun.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ enum class ReadyToRunSectionType : uint32_t
8080
ComponentAssemblies = 115, // Added in V4.1
8181
OwnerCompositeExecutable = 116, // Added in V4.1
8282
PgoInstrumentationData = 117, // Added in 5.2
83-
ComponentAssemblyMvids = 118, // Added in V5.3
83+
ManifestAssemblyMvids = 118, // Added in V5.3
8484

8585
// If you add a new section consider whether it is a breaking or non-breaking change.
8686
// Usually it is non-breaking, but if it is preferable to have older runtimes fail

src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal struct ReadyToRunHeaderConstants
1515
public const uint Signature = 0x00525452; // 'RTR'
1616

1717
public const ushort CurrentMajorVersion = 5;
18-
public const ushort CurrentMinorVersion = 4;
18+
public const ushort CurrentMinorVersion = 3;
1919
}
2020

2121
#pragma warning disable 0169
@@ -66,6 +66,7 @@ public enum ReadyToRunSectionType
6666
ComponentAssemblies = 115, // Added in 4.1
6767
OwnerCompositeExecutable = 116, // Added in 4.1
6868
PgoInstrumentationData = 117, // Added in 5.2
69+
ManifestAssemblyMvids = 118, // Added in 5.3
6970

7071
//
7172
// CoreRT ReadyToRun sections
Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System;
45
using System.Reflection.Metadata;
56
using System.Reflection.PortableExecutable;
67

@@ -11,11 +12,11 @@
1112

1213
namespace ILCompiler.DependencyAnalysis.ReadyToRun
1314
{
14-
public class ComponentMetadataMvidHeaderNode : ObjectNode, ISymbolDefinitionNode
15+
public class ManifestAssemblyMvidHeaderNode : ObjectNode, ISymbolDefinitionNode
1516
{
1617
private ManifestMetadataTableNode _manifestNode;
1718

18-
public ComponentMetadataMvidHeaderNode(ManifestMetadataTableNode manifestNode)
19+
public ManifestAssemblyMvidHeaderNode(ManifestMetadataTableNode manifestNode)
1920
{
2021
_manifestNode = manifestNode;
2122
}
@@ -26,18 +27,18 @@ public ComponentMetadataMvidHeaderNode(ManifestMetadataTableNode manifestNode)
2627

2728
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
2829

29-
public override int ClassCode => (int)ObjectNodeOrder.CorHeaderNode;
30+
public override int ClassCode => 735231445;
3031

3132
public override bool StaticDependenciesAreComputed => true;
3233

3334
public int Offset => 0;
3435

35-
public int Size => _manifestNode.ComponentAssemblyMvidTableSize;
36+
public int Size => _manifestNode.ManifestAssemblyMvidTableSize;
3637

3738
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
3839
{
3940
sb.Append(nameMangler.CompilationUnitPrefix);
40-
sb.Append("__ComponentAssemblyMvids");
41+
sb.Append("__ManifestAssemblyMvids");
4142
}
4243

4344
protected override string GetName(NodeFactory nodeFactory)
@@ -47,6 +48,15 @@ protected override string GetName(NodeFactory nodeFactory)
4748
return sb.ToString();
4849
}
4950

50-
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) => _manifestNode.GetComponentAssemblyMvidTableData(factory, relocsOnly);
51+
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
52+
{
53+
if (relocsOnly)
54+
{
55+
return new ObjectData(Array.Empty<byte>(), null, 1, null);
56+
}
57+
58+
byte[] manifestAssemblyMvidTable = _manifestNode.GetManifestAssemblyMvidTableData();
59+
return new ObjectData(manifestAssemblyMvidTable, Array.Empty<Relocation>(), alignment: 0, new ISymbolDefinitionNode[] { this });
60+
}
5161
}
5262
}

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ public class ManifestMetadataTableNode : HeaderTableNode
4343

4444
/// <summary>
4545
/// MVID's of the assemblies included in manifest metadata to be emitted as the
46-
/// ComponentAssemblyMvid R2R header table used by the runtime to check loaded assemblies
46+
/// ManifestAssemblyMvid R2R header table used by the runtime to check loaded assemblies
4747
/// and fail fast in case of mismatch.
4848
/// </summary>
49-
private readonly List<Guid> _componentAssemblyMvids;
49+
private readonly List<Guid> _manifestAssemblyMvids;
5050

5151
/// <summary>
5252
/// Registered signature emitters.
@@ -78,7 +78,7 @@ public ManifestMetadataTableNode(NodeFactory nodeFactory)
7878
{
7979
_assemblyRefToModuleIdMap = new Dictionary<string, int>();
8080
_moduleIdToAssemblyNameMap = new Dictionary<int, AssemblyName>();
81-
_componentAssemblyMvids = new List<Guid>();
81+
_manifestAssemblyMvids = new List<Guid>();
8282
_signatureEmitters = new List<ISignatureEmitter>();
8383
_nodeFactory = nodeFactory;
8484
_nextModuleId = 1;
@@ -158,7 +158,7 @@ private int ModuleToIndexInternal(EcmaModule module)
158158
Debug.Assert(_nodeFactory.CompilationModuleGroup.VersionsWithModule(module));
159159

160160
_moduleIdToAssemblyNameMap.Add(assemblyRefIndex, assemblyName);
161-
_componentAssemblyMvids.Add(module.MetadataReader.GetGuid(module.MetadataReader.GetModuleDefinition().Mvid));
161+
_manifestAssemblyMvids.Add(module.MetadataReader.GetGuid(module.MetadataReader.GetModuleDefinition().Mvid));
162162
}
163163
return assemblyRefIndex;
164164
}
@@ -253,26 +253,21 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
253253

254254
private const int GuidByteSize = 16;
255255

256-
public int ComponentAssemblyMvidTableSize => GuidByteSize * _componentAssemblyMvids.Count;
256+
public int ManifestAssemblyMvidTableSize => GuidByteSize * _manifestAssemblyMvids.Count;
257257

258-
public ObjectData GetComponentAssemblyMvidTableData(NodeFactory factory, bool relocsOnly = false)
258+
internal byte[] GetManifestAssemblyMvidTableData()
259259
{
260-
if (relocsOnly)
261-
{
262-
return new ObjectData(Array.Empty<byte>(), null, 1, null);
263-
}
264-
265-
byte[] componentAssemblyMvidTable = new byte[ComponentAssemblyMvidTableSize];
266-
for (int i = 0; i < _componentAssemblyMvids.Count; i++)
260+
byte[] manifestAssemblyMvidTable = new byte[ManifestAssemblyMvidTableSize];
261+
for (int i = 0; i < _manifestAssemblyMvids.Count; i++)
267262
{
268263
Array.Copy(
269-
sourceArray: _componentAssemblyMvids[i].ToByteArray(),
264+
sourceArray: _manifestAssemblyMvids[i].ToByteArray(),
270265
sourceIndex: 0,
271-
destinationArray: componentAssemblyMvidTable,
266+
destinationArray: manifestAssemblyMvidTable,
272267
destinationIndex: GuidByteSize * i,
273268
length: GuidByteSize);
274269
}
275-
return new ObjectData(componentAssemblyMvidTable, Array.Empty<Relocation>(), alignment: 0, new ISymbolDefinitionNode[] { this });
270+
return manifestAssemblyMvidTable;
276271
}
277272
}
278273
}

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,9 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph)
570570
Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestMetadata, ManifestMetadataTable, ManifestMetadataTable);
571571
Resolver.SetModuleIndexLookup(ManifestMetadataTable.ModuleToIndex);
572572

573+
ManifestAssemblyMvidHeaderNode mvidTableNode = new ManifestAssemblyMvidHeaderNode(ManifestMetadataTable);
574+
Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestAssemblyMvids, mvidTableNode, mvidTableNode);
575+
573576
AssemblyTableNode assemblyTable = null;
574577

575578
if (CompilationModuleGroup.IsCompositeBuildMode)

src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
<Compile Include="..\..\Common\TypeSystem\Interop\InteropTypes.cs" Link="Interop\InteropTypes.cs" />
104104
<Compile Include="Compiler\AssemblyExtensions.cs" />
105105
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\DeferredTillPhaseNode.cs" />
106-
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\ComponentAssemblyMvidHeaderNode.cs" />
106+
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\ManifestAssemblyMvidHeaderNode.cs" />
107107
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\DelayLoadMethodCallThunkNodeRange.cs" />
108108
<Compile Include="Compiler\CallChainProfile.cs" />
109109
<Compile Include="ObjectWriter\MapFileBuilder.cs" />

src/coreclr/tools/r2rdump/TextDumper.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ namespace R2RDump
1818
{
1919
class TextDumper : Dumper
2020
{
21+
private const int GuidByteSize = 16;
22+
2123
public TextDumper(ReadyToRunReader r2r, TextWriter writer, Disassembler disassembler, DumpOptions options)
2224
: base(r2r, writer, disassembler, options)
2325
{
@@ -88,7 +90,14 @@ internal override void DumpHeader(bool dumpSections)
8890
int assemblyIndex = 0;
8991
foreach (string assemblyName in _r2r.ManifestReferenceAssemblies.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key))
9092
{
91-
WriteDivider($@"Component Assembly [{assemblyIndex}]: {assemblyName}");
93+
string dividerName = $@"Component Assembly [{assemblyIndex}]: {assemblyName}";
94+
if (_r2r.ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.ManifestAssemblyMvids, out ReadyToRunSection mvidSection))
95+
{
96+
int mvidOffset = _r2r.GetOffset(mvidSection.RelativeVirtualAddress) + GuidByteSize * assemblyIndex;
97+
Guid mvid = new Guid(new ReadOnlySpan<byte>(_r2r.Image, mvidOffset, GuidByteSize));
98+
dividerName += $@" - MVID {mvid}";
99+
}
100+
WriteDivider(dividerName);
92101
ReadyToRunCoreHeader assemblyHeader = _r2r.ReadyToRunAssemblyHeaders[assemblyIndex];
93102
foreach (ReadyToRunSection section in NormalizedSections(assemblyHeader))
94103
{
@@ -500,6 +509,18 @@ internal override void DumpSectionContents(ReadyToRunSection section)
500509
string ownerCompositeExecutable = Encoding.UTF8.GetString(_r2r.Image, oceOffset, section.Size - 1); // exclude the zero terminator
501510
_writer.WriteLine("Composite executable: {0}", ownerCompositeExecutable.ToEscapedString());
502511
break;
512+
case ReadyToRunSectionType.ManifestAssemblyMvids:
513+
int mvidOffset = _r2r.GetOffset(section.RelativeVirtualAddress);
514+
int mvidCount = section.Size / GuidByteSize;
515+
for (int mvidIndex = 0; mvidIndex < mvidCount; mvidIndex++)
516+
{
517+
Guid mvid = new Guid(new Span<byte>(_r2r.Image, mvidOffset + GuidByteSize * mvidIndex, GuidByteSize));
518+
_writer.WriteLine("MVID[{0}] = {1}", mvidIndex, mvid);
519+
}
520+
break;
521+
default:
522+
_writer.WriteLine("Unsupported section type {0}", section.Type);
523+
break;
503524
}
504525
}
505526

src/coreclr/vm/appdomain.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3043,13 +3043,15 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity,
30433043

30443044
// Find the list lock entry
30453045
FileLoadLock * fileLock = (FileLoadLock *)lock->FindFileLock(pFile);
3046+
bool registerNewAssembly = false;
30463047
if (fileLock == NULL)
30473048
{
30483049
// Check again in case we were racing
30493050
result = FindAssembly(pFile, FindAssemblyOptions_IncludeFailedToLoad);
30503051
if (result == NULL)
30513052
{
30523053
// We are the first one in - create the DomainAssembly
3054+
registerNewAssembly = true;
30533055
fileLock = FileLoadLock::Create(lock, pFile, pDomainAssembly);
30543056
pDomainAssembly.SuppressRelease();
30553057
#ifndef CROSSGEN_COMPILE
@@ -3082,6 +3084,11 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity,
30823084
{
30833085
result->EnsureLoadLevel(targetLevel);
30843086
}
3087+
3088+
if (registerNewAssembly)
3089+
{
3090+
pFile->GetAssemblyLoadContext()->AddLoadedAssembly(pDomainAssembly->GetLoadedAssembly());
3091+
}
30853092
}
30863093
else
30873094
result->EnsureLoadLevel(targetLevel);

src/coreclr/vm/nativeimage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void NativeImage::Initialize(READYTORUN_HEADER *pHeader, LoaderAllocator *pLoade
6767

6868
m_pReadyToRunInfo = new ReadyToRunInfo(/*pModule*/ NULL, pLoaderAllocator, m_pImageLayout, pHeader, /*compositeImage*/ NULL, pamTracker);
6969
m_pComponentAssemblies = m_pReadyToRunInfo->FindSection(ReadyToRunSectionType::ComponentAssemblies);
70-
m_pComponentAssemblyMvids = m_pReadyToRunInfo->FindSection(ReadyToRunSectionType::ComponentAssemblyMvids);
70+
m_pComponentAssemblyMvids = m_pReadyToRunInfo->FindSection(ReadyToRunSectionType::ManifestAssemblyMvids);
7171
m_componentAssemblyCount = m_pComponentAssemblies->Size / sizeof(READYTORUN_COMPONENT_ASSEMBLIES_ENTRY);
7272

7373
// Check if the current module's image has native manifest metadata, otherwise the current->GetNativeAssemblyImport() asserts.

0 commit comments

Comments
 (0)