Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/coreclr/src/inc/CrstTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -705,3 +705,6 @@ Crst MethodDescBackpatchInfoTracker
AcquiredBefore FuncPtrStubs ThreadStore SystemDomain
AcquiredAfter ReJITGlobalRequest
End

Crst NativeImageDependencies
End
129 changes: 66 additions & 63 deletions src/coreclr/src/inc/crsttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,69 +106,70 @@ enum CrstType
CrstMUThunkHash = 87,
CrstNativeBinderInit = 88,
CrstNativeImageCache = 89,
CrstNls = 90,
CrstNotifyGdb = 91,
CrstObjectList = 92,
CrstOnEventManager = 93,
CrstPatchEntryPoint = 94,
CrstPEImage = 95,
CrstPEImagePDBStream = 96,
CrstPendingTypeLoadEntry = 97,
CrstPinHandle = 98,
CrstPinnedByrefValidation = 99,
CrstProfilerGCRefDataFreeList = 100,
CrstProfilingAPIStatus = 101,
CrstPublisherCertificate = 102,
CrstRCWCache = 103,
CrstRCWCleanupList = 104,
CrstRCWRefCache = 105,
CrstReadyToRunEntryPointToMethodDescMap = 106,
CrstReDacl = 107,
CrstReflection = 108,
CrstReJITDomainTable = 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
CrstNativeImageDependencies = 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,
CrstReJITDomainTable = 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
Expand Down Expand Up @@ -269,6 +270,7 @@ int g_rgCrstLevelMap[] =
0, // CrstMUThunkHash
-1, // CrstNativeBinderInit
-1, // CrstNativeImageCache
0, // CrstNativeImageDependencies
0, // CrstNls
0, // CrstNotifyGdb
2, // CrstObjectList
Expand Down Expand Up @@ -426,6 +428,7 @@ LPCSTR g_rgCrstNameMap[] =
"CrstMUThunkHash",
"CrstNativeBinderInit",
"CrstNativeImageCache",
"CrstNativeImageDependencies",
"CrstNls",
"CrstNotifyGdb",
"CrstObjectList",
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/src/inc/pedecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ class PEDecoder
// Debug directory access, returns NULL if no such entry
PTR_IMAGE_DEBUG_DIRECTORY GetDebugDirectoryEntry(UINT index) const;

PTR_IMAGE_DATA_DIRECTORY GetReadyToRunSection(ReadyToRunSectionType section) const;

PTR_CVOID GetNativeManifestMetadata(COUNT_T* pSize = NULL) const;

#ifdef FEATURE_PREJIT
Expand All @@ -328,7 +330,7 @@ class PEDecoder
BOOL IsNativeILILOnly() const;
BOOL IsNativeILDll() const;
void GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) const;
CORCOMPILE_DEPENDENCY * GetNativeDependencies(COUNT_T *pCount = NULL) const;
CORCOMPILE_DEPENDENCY* GetNativeDependencies(COUNT_T* pCount = NULL) const;

PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSections(COUNT_T *pCount = NULL) const;
PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSectionFromIndex(COUNT_T index) const;
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/src/inc/readytorun.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ enum class ReadyToRunSectionType : uint32_t
ManifestMetadata = 112, // Added in V2.3
AttributePresence = 113, // Added in V3.1
InliningInfo2 = 114, // Added in V4.1
NativeDependencies = 117, // 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
Expand Down Expand Up @@ -370,4 +371,10 @@ enum ReadyToRunRuntimeConstants : DWORD
READYTORUN_PInvokeTransitionFrameSizeInPointerUnits = 11
};

struct READYTORUN_DEPENDENCY
{
DWORD ModuleId;
GUID Mvid;
};

#endif // __READYTORUN_H__
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ protected enum ObjectNodeOrder
//
CorHeaderNode,
ReadyToRunHeaderNode,
InliningInfoNode,
ReadyToRunAssemblyHeaderNode,
ImportSectionsTableNode,
ImportSectionNode,
MethodEntrypointTableNode,
NativeDependenciesNode,


//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public enum ReadyToRunSectionType
InliningInfo2 = 114, // Added in 4.1
ComponentAssemblies = 115, // Added in 4.1
OwnerCompositeExecutable = 116, // Added in 4.1
NativeDependencies = 117, // Added in V4.1

//
// CoreRT ReadyToRun sections
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/src/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public AssemblyName GetName()
AssemblyName an = new AssemblyName();
an.Name = metadataReader.GetString(_assemblyDefinition.Name);
an.Version = _assemblyDefinition.Version;
an.SetPublicKey(metadataReader.GetBlobBytes(_assemblyDefinition.PublicKey));
if ((_assemblyDefinition.Flags & AssemblyFlags.PublicKey) != 0)
an.SetPublicKey(metadataReader.GetBlobBytes(_assemblyDefinition.PublicKey));

an.CultureName = metadataReader.GetString(_assemblyDefinition.Culture);
an.ContentType = GetContentTypeFromAssemblyFlags(_assemblyDefinition.Flags);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ public class InliningInfoNode : HeaderTableNode
{
private readonly EcmaModule _module;

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

public override int ClassCode => (int)ObjectNodeOrder.InliningInfoNode;

public InliningInfoNode(TargetDetails target, EcmaModule module)
: base(target)
{
Expand Down Expand Up @@ -155,7 +159,5 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
InliningInfoNode otherInliningInfo = (InliningInfoNode)other;
return _module.Assembly.GetName().Name.CompareTo(otherInliningInfo._module.Assembly.GetName().Name);
}

public override int ClassCode => -87382891;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,24 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde
sb.Append("ManifestMetadataTableNode");
}

public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
internal IEnumerable<(int Index, Guid Mvid)> GetFragileDependencies(CompilerTypeSystemContext context)
{
if (relocsOnly)
// Freeze the moduleId to assembly name map to catch possible ordering bugs.
CompleteEmission();

foreach (var assemblyNameAndIndex in _assemblyRefToModuleIdMap.OrderBy(x => x.Value))
{
return new ObjectData(Array.Empty<byte>(), null, 1, null);
var module = (EcmaModule)context.GetModuleForSimpleName(assemblyNameAndIndex.Key, throwIfNotFound: false);
if (module == null)
continue;

Guid mvid = module.MetadataReader.GetGuid(module.MetadataReader.GetModuleDefinition().Mvid);
yield return (assemblyNameAndIndex.Value, mvid);
}
}

private void CompleteEmission()
{
if (!_emissionCompleted)
{
foreach (ISignatureEmitter emitter in _signatureEmitters)
Expand All @@ -173,6 +184,16 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)

_emissionCompleted = true;
}
}

public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
if (relocsOnly)
{
return new ObjectData(Array.Empty<byte>(), null, 1, null);
}

CompleteEmission();

MetadataBuilder metadataBuilder = new MetadataBuilder();

Expand Down Expand Up @@ -222,7 +243,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
name: metadataBuilder.GetOrAddString(assemblyName.Name),
version: assemblyName.Version,
culture: metadataBuilder.GetOrAddString(assemblyName.CultureName),
publicKeyOrToken: metadataBuilder.GetOrAddBlob(publicKeyOrToken),
publicKeyOrToken: publicKeyOrToken == null ? default : metadataBuilder.GetOrAddBlob(publicKeyOrToken),
flags: assemblyFlags,
hashValue: default(BlobHandle) /* TODO */);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we just use the hashValue here to store the MVID instead of a new node type?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless of course we have plans to use hashValue for something else, but the list of assemblies written in this MD blob seem to only be used for the version bubble stuff.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This table only has references to assemblies that don't exist in the original AssemblyRef table. There's a complex scheme of how to make sense of it.

We can't modify the original AssemblyRef table because it's visible to user code. We would need an alternative storage mechanism for those entries anyway - people do weird stuff with user visible parts of these things - e.g. I've seen an app that used the assembly's public key to encrypt network traffic 😱).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok Thanks Michal for the clarification

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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.

using System;

using Internal.Text;
using Internal.TypeSystem;

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
/// <summary>
/// Stores information about assemblies that this module has fragile dependencies on.
/// </summary>
public class NativeDependencieNode : HeaderTableNode
{
protected internal override int Phase => (int)ObjectNodePhase.Ordered;

public override int ClassCode => (int)ObjectNodeOrder.NativeDependenciesNode;

public NativeDependencieNode(TargetDetails target)
: base(target)
{
}

public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
sb.Append("__ReadyToRunNativeDependenciesNode");
}

public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
// This node does not trigger generation of other nodes.
if (relocsOnly)
return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });

ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
builder.RequireInitialPointerAlignment();
builder.AddSymbol(this);

foreach (var nativeDependency in factory.ManifestMetadataTable.GetFragileDependencies(factory.TypeSystemContext))
{
builder.EmitInt(nativeDependency.Index);
builder.EmitBytes(nativeDependency.Mvid.ToByteArray());
}

return builder.ToObjectData();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder
private int _parallelism;

private string _jitPath;
private bool _generateNativeDependencies;

// These need to provide reasonable defaults so that the user can optionally skip
// calling the Use/Configure methods and still get something reasonable back.
Expand Down Expand Up @@ -108,6 +109,12 @@ public ReadyToRunCodegenCompilationBuilder UseParallelism(int parallelism)
return this;
}

public ReadyToRunCodegenCompilationBuilder WithNativeDependenciesTable(bool enable)
{
_generateNativeDependencies = enable;
return this;
}

public override ICompilation ToCompilation()
{
// TODO: only copy COR headers for single-assembly build and for composite build with embedded MSIL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\InliningInfoNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\InstanceEntryPointTableNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\IReadyToRunMethodCodeNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\NativeDependenciesNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\OwnerCompositeExecutableNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\PrecodeMethodImport.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\LocalMethodImport.cs" />
Expand Down
Loading