in src/Microsoft.Diagnostics.Runtime/Implementation/DotNetClrInfoProvider.cs [135:339]
protected ClrInfo CreateClrInfo(DataTarget dataTarget, ModuleInfo module, ulong runtimeInfo, ClrFlavor flavor)
{
Version version;
int indexTimeStamp = 0;
int indexFileSize = 0;
ImmutableArray<byte> buildId = ImmutableArray<byte>.Empty;
List<DebugLibraryInfo> artifacts = new(8);
OSPlatform currentPlatform = GetCurrentPlatform();
OSPlatform targetPlatform = dataTarget.DataReader.TargetPlatform;
Architecture currentArch = RuntimeInformation.ProcessArchitecture;
Architecture targetArch = dataTarget.DataReader.Architecture;
string? dacCurrentPlatform = GetDacFileName(flavor, currentPlatform);
string? dacTargetPlatform = GetDacFileName(flavor, targetPlatform);
string? dbiCurrentPlatform = GetDbiFileName(flavor, currentPlatform);
string? dbiTargetPlatform = GetDbiFileName(flavor, targetPlatform);
if (runtimeInfo != 0)
{
if (ClrRuntimeInfo.TryReadClrRuntimeInfo(dataTarget.DataReader, runtimeInfo, out ClrRuntimeInfo info, out version))
{
if (dataTarget.DataReader.TargetPlatform == OSPlatform.Windows)
{
indexTimeStamp = info.RuntimePEProperties.TimeStamp;
indexFileSize = info.RuntimePEProperties.FileSize;
if (dacTargetPlatform is not null)
{
(int timeStamp, int fileSize) = info.DacPEProperties;
if (timeStamp != 0 && fileSize != 0)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dac, dacTargetPlatform, targetArch, SymbolProperties.Self, fileSize, timeStamp));
}
if (dbiTargetPlatform is not null)
{
(int timeStamp, int fileSize) = info.DbiPEProperties;
if (timeStamp != 0 && fileSize != 0)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dbi, dbiTargetPlatform, targetArch, SymbolProperties.Self, fileSize, timeStamp));
}
}
else
{
buildId = info.RuntimeBuildId;
if (dacTargetPlatform is not null)
{
ImmutableArray<byte> dacBuild = info.DacBuildId;
if (!dacBuild.IsDefaultOrEmpty)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dac, dacTargetPlatform, targetArch, targetPlatform, SymbolProperties.Self, dacBuild));
}
if (dbiTargetPlatform is not null)
{
ImmutableArray<byte> dbiBuild = info.DbiBuildId;
if (!dbiBuild.IsDefaultOrEmpty)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dbi, dbiTargetPlatform, targetArch, targetPlatform, SymbolProperties.Self, dbiBuild));
}
}
}
}
else
{
indexTimeStamp = module.IndexTimeStamp;
indexFileSize = module.IndexFileSize;
buildId = module.BuildId;
version = module.Version;
}
// Long-name dac
if (dataTarget.DataReader.TargetPlatform == OSPlatform.Windows && version.Major != 0)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dac, GetWindowsLongNameDac(flavor, currentArch, targetArch, version), currentArch, SymbolProperties.Coreclr, indexFileSize, indexTimeStamp));
// Short-name dac under CLR's properties
if (targetPlatform == currentPlatform)
{
// We are debugging the process on the same operating system.
if (dacCurrentPlatform is not null)
{
bool foundLocalDac = false;
// Check if the user has the same CLR installed locally, and if so
string? directory = Path.GetDirectoryName(module.FileName);
if (!string.IsNullOrWhiteSpace(directory))
{
string potentialClr = Path.Combine(directory, Path.GetFileName(module.FileName));
if (File.Exists(potentialClr))
{
try
{
using PEImage peimage = new(File.OpenRead(potentialClr));
if (peimage.IndexFileSize == indexFileSize && peimage.IndexTimeStamp == indexTimeStamp)
{
string dacFound = Path.Combine(directory, dacCurrentPlatform);
if (File.Exists(dacFound))
{
dacCurrentPlatform = dacFound;
foundLocalDac = true;
}
}
}
catch
{
}
}
}
if (indexFileSize != 0 && indexTimeStamp != 0)
{
DebugLibraryInfo dacLibraryInfo = new(DebugLibraryKind.Dac, dacCurrentPlatform, targetArch, SymbolProperties.Coreclr, indexFileSize, indexTimeStamp);
if (foundLocalDac)
artifacts.Insert(0, dacLibraryInfo);
else
artifacts.Add(dacLibraryInfo);
}
if (!buildId.IsDefaultOrEmpty)
{
DebugLibraryInfo dacLibraryInfo = new(DebugLibraryKind.Dac, dacCurrentPlatform, targetArch, targetPlatform, SymbolProperties.Coreclr, buildId);
if (foundLocalDac)
artifacts.Insert(0, dacLibraryInfo);
else
artifacts.Add(dacLibraryInfo);
}
}
if (dbiCurrentPlatform is not null)
{
if (indexFileSize != 0 && indexTimeStamp != 0)
{
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dbi, dbiCurrentPlatform, targetArch, SymbolProperties.Coreclr, indexFileSize, indexTimeStamp));
}
if (!buildId.IsDefaultOrEmpty)
{
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dbi, dbiCurrentPlatform, targetArch, targetPlatform, SymbolProperties.Coreclr, buildId));
}
}
}
else
{
// We are debugging the process on a different operating system.
if (indexFileSize != 0 && indexTimeStamp != 0)
{
// We currently only support cross-os debugging on windows targeting linux or os x runtimes. So if we have windows properties,
// then we only generate one artifact (the target one).
if (dacTargetPlatform is not null)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dac, dacTargetPlatform, targetArch, SymbolProperties.Coreclr, indexFileSize, indexTimeStamp));
if (dbiTargetPlatform is not null)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dbi, dbiTargetPlatform, targetArch, SymbolProperties.Coreclr, indexFileSize, indexTimeStamp));
}
if (!buildId.IsDefaultOrEmpty)
{
if (dacTargetPlatform is not null)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dac, dacTargetPlatform, targetArch, targetPlatform, SymbolProperties.Coreclr, buildId));
if (dbiTargetPlatform is not null)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dbi, dbiTargetPlatform, targetArch, targetPlatform, SymbolProperties.Coreclr, buildId));
if (currentPlatform == OSPlatform.Windows)
{
// If we are running from Windows, we can target Linux and OS X dumps. We do build cross-os, cross-architecture debug libraries to run on Windows x64 or x86
if (dacCurrentPlatform is not null)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dac, dacCurrentPlatform, currentArch, currentPlatform, SymbolProperties.Coreclr, buildId));
if (dbiCurrentPlatform is not null)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dbi, dbiCurrentPlatform, currentArch, currentPlatform, SymbolProperties.Coreclr, buildId));
}
}
}
// Windows CLRDEBUGINFO resource
IResourceNode? resourceNode = module.ResourceRoot?.GetChild("RCData")?.GetChild("CLRDEBUGINFO")?.Children.FirstOrDefault();
if (resourceNode is not null)
{
CLR_DEBUG_RESOURCE resource = resourceNode.Read<CLR_DEBUG_RESOURCE>(0);
if (resource.dwVersion == 0)
{
if (dacTargetPlatform is not null && resource.dwDacTimeStamp != 0 && resource.dwDacSizeOfImage != 0)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dac, dacTargetPlatform, targetArch, SymbolProperties.Self, resource.dwDacSizeOfImage, resource.dwDacTimeStamp));
if (dbiTargetPlatform is not null && resource.dwDbiTimeStamp != 0 && resource.dwDbiSizeOfImage != 0)
artifacts.Add(new DebugLibraryInfo(DebugLibraryKind.Dbi, dbiTargetPlatform, targetArch, SymbolProperties.Self, resource.dwDbiSizeOfImage, resource.dwDbiTimeStamp));
}
}
// Do NOT take a dependency on the order of enumerated libraries. I reserve the right to change this at any time.
IOrderedEnumerable<DebugLibraryInfo> orderedDebugLibraries = from artifact in EnumerateUnique(artifacts)
orderby artifact.Kind,
Path.GetFileName(artifact.FileName) == artifact.FileName, // if we have a full local path, put it first
artifact.ArchivedUnder
select artifact;
ClrInfo result = new(dataTarget, module, version, this)
{
Flavor = flavor,
DebuggingLibraries = orderedDebugLibraries.ToImmutableArray(),
IndexFileSize = indexFileSize,
IndexTimeStamp = indexTimeStamp,
BuildId = buildId,
};
return result;
}