in src/Microsoft.Diagnostics.Runtime/src/DataTargets/DataTarget.cs [156:253]
private ImmutableArray<ClrInfo> GetOrCreateClrVersions()
{
if (_disposed)
throw new ObjectDisposedException(nameof(DataTarget));
if (!_clrs.IsDefault)
return _clrs;
IExportReader? exportReader = DataReader as IExportReader;
Architecture arch = DataReader.Architecture;
RuntimeInfo? singleFileRuntimeInfo = null;
ImmutableArray<ClrInfo>.Builder versions = ImmutableArray.CreateBuilder<ClrInfo>(2);
foreach (ModuleInfo module in EnumerateModules())
{
ImmutableArray<byte> runtimeBuildId = ImmutableArray<byte>.Empty;
int runtimeTimeStamp = 0;
int runtimeFileSize = 0;
if (ClrInfoProvider.IsSupportedRuntime(module, out ClrFlavor flavor, out OSPlatform platform))
{
runtimeTimeStamp = module.IndexTimeStamp;
runtimeFileSize = module.IndexFileSize;
runtimeBuildId = module.BuildId;
}
else
{
if (exportReader is null || !exportReader.TryGetSymbolAddress(module.ImageBase, RuntimeInfo.SymbolValue, out ulong runtimeInfoAddress))
continue;
if (!DataReader.Read(runtimeInfoAddress, out RuntimeInfo runtimeInfo))
continue;
unsafe
{
string signature = Encoding.ASCII.GetString(runtimeInfo.Signature, RuntimeInfo.SignatureValueLength);
if (signature != RuntimeInfo.SignatureValue || runtimeInfo.Version <= 0)
continue;
platform = DataReader.TargetPlatform;
flavor = ClrFlavor.Core;
singleFileRuntimeInfo = runtimeInfo;
if (platform == OSPlatform.Windows)
{
if (runtimeInfo.RuntimeModuleIndex[0] >= sizeof(int) + sizeof(int))
{
runtimeTimeStamp = BitConverter.ToInt32(new ReadOnlySpan<byte>(runtimeInfo.RuntimeModuleIndex + sizeof(byte), sizeof(int)).ToArray(), 0);
runtimeFileSize = BitConverter.ToInt32(new ReadOnlySpan<byte>(runtimeInfo.RuntimeModuleIndex + sizeof(byte) + sizeof(int), sizeof(int)).ToArray(), 0);
}
}
else
{
// The first byte of the module indexes is the length of the build id
runtimeBuildId = new ReadOnlySpan<byte>(runtimeInfo.RuntimeModuleIndex + sizeof(byte), runtimeInfo.RuntimeModuleIndex[0]).ToArray().ToImmutableArray();
}
}
}
string dacFileName = ClrInfoProvider.GetDacFileName(flavor, platform);
string? dacLocation = Path.Combine(Path.GetDirectoryName(module.FileName)!, dacFileName);
if (platform == OSPlatform.Linux)
{
if (File.Exists(dacLocation))
{
// Works around issue https://github.com/dotnet/coreclr/issues/20205
lock (_sync)
{
_symlink = Path.GetTempFileName();
if (LinuxFunctions.symlink(dacLocation, _symlink) == 0)
{
dacLocation = _symlink;
}
}
}
else
{
dacLocation = null;
}
}
else if (!File.Exists(dacLocation) || !PlatformFunctions.IsEqualFileVersion(dacLocation, module.Version))
{
dacLocation = null;
}
VersionInfo version = module.Version;
string dacAgnosticName = ClrInfoProvider.GetDacRequestFileName(flavor, arch, arch, version, platform);
string dacRegularName = ClrInfoProvider.GetDacRequestFileName(flavor, IntPtr.Size == 4 ? Architecture.X86 : Architecture.Amd64, arch, version, platform);
DacInfo dacInfo = new DacInfo(dacLocation, dacRegularName, dacAgnosticName, arch, runtimeFileSize, runtimeTimeStamp, version, runtimeBuildId);
versions.Add(new ClrInfo(this, flavor, module, dacInfo) {
SingleFileRuntimeInfo = singleFileRuntimeInfo
});
}
_clrs = versions.MoveOrCopyToImmutable();
return _clrs;
}