in src/Microsoft.Diagnostics.Runtime/Windows/Minidump.cs [62:136]
public Minidump(string displayName, Stream stream, CacheOptions cacheOptions, bool leaveOpen)
{
_displayName = displayName;
// Load header
MinidumpHeader header = Read<MinidumpHeader>(stream);
if (!header.IsValid)
throw new InvalidDataException($"File '{displayName}' is not a Minidump.");
IsMiniDump = (header.Flags & (MiniDumpWithFullMemory | MiniDumpWithPrivateReadWriteMemory | MiniDumpWithPrivateWriteCopyMemory)) == 0;
_directories = new MinidumpDirectory[header.NumberOfStreams];
stream.Position = header.StreamDirectoryRva;
if (!Read(stream, _directories))
throw new InvalidDataException($"Unable to read directories from minidump '{displayName} offset 0x{header.StreamDirectoryRva:x}");
(int systemInfoIndex, int moduleListIndex, int miscStream) = FindImportantStreams(displayName);
// Architecture is the first entry in MINIDUMP_SYSTEM_INFO. We need nothing else out of that struct,
// so we only read the first entry.
// https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_system_info
Architecture = Read<MinidumpProcessorArchitecture>(stream, _directories[systemInfoIndex].Rva);
// ProcessId is the 3rd DWORD in this stream.
if (miscStream != -1)
ProcessId = Read<int>(stream, _directories[miscStream].Rva + sizeof(uint) * 2);
// Initialize modules. DataTarget will need a module list immediately, so there's no reason to delay
// filling in the module list.
long rva = _directories[moduleListIndex].Rva;
uint count = Read<uint>(stream, rva);
rva += sizeof(uint);
MinidumpModule[] modules = new MinidumpModule[count];
if (Read(stream, rva, modules))
Modules = modules.AsImmutableArray();
else
Modules = ImmutableArray<MinidumpModule>.Empty;
// Read segments async.
ImmutableArray<MinidumpSegment> segments = GetSegments(stream);
MinidumpMemoryReader memoryReader;
if (stream is FileStream fs) // we can optimize for FileStreams
{
int cacheSize = cacheOptions.MaxDumpCacheSize > int.MaxValue ? int.MaxValue : (int)cacheOptions.MaxDumpCacheSize;
bool isTinyDump = stream.Length <= cacheSize;
if (isTinyDump)
{
_file = MemoryMappedFile.CreateFromFile(fs, null, 0, MemoryMappedFileAccess.Read, HandleInheritability.None, leaveOpen: false);
MemoryMappedViewStream mmStream = _file.CreateViewStream(0, 0, MemoryMappedFileAccess.Read);
memoryReader = new UncachedMemoryReader(segments, mmStream, PointerSize, leaveOpen);
}
else if (cacheSize < CachedMemoryReader.MinimumCacheSize)
{
// this will be very slow
memoryReader = new UncachedMemoryReader(segments, stream, PointerSize, leaveOpen);
}
else
{
CacheTechnology technology = cacheOptions.UseOSMemoryFeatures ? CacheTechnology.AWE : CacheTechnology.ArrayPool;
memoryReader = new CachedMemoryReader(segments, displayName, fs, cacheSize, technology, PointerSize, leaveOpen);
}
}
else
{
memoryReader = new UncachedMemoryReader(segments, stream, PointerSize, leaveOpen);
}
MemoryReader = memoryReader;
_threadTask = ReadThreadData(stream);
}