public DumpFileMemoryReader(string dumpFilePath) { bool dispose = true; FileStream fileStream = null; MemoryMappedFile memoryMappedFile = null; MemoryMappedViewStream stream = null; try { fileStream = new FileStream(dumpFilePath, FileMode.Open, FileAccess.Read); memoryMappedFile = MemoryMappedFile.CreateFromFile(fileStream, Guid.NewGuid().ToString(), fileStream.Length, MemoryMappedFileAccess.Read, new MemoryMappedFileSecurity(), HandleInheritability.Inheritable, false); stream = memoryMappedFile.CreateViewStream(0, fileStream.Length, MemoryMappedFileAccess.Read); stream.SafeMemoryMappedViewHandle.AcquirePointer(ref basePointer); IntPtr streamPointer = IntPtr.Zero; uint streamSize = 0; MINIDUMP_DIRECTORY directory = new MINIDUMP_DIRECTORY(); if (!MiniDumpReadDumpStream((IntPtr)basePointer, MINIDUMP_STREAM_TYPE.Memory64ListStream, ref directory, ref streamPointer, ref streamSize)) throw new Exception("Unable to read mini dump stream"); var data = (MINIDUMP_MEMORY64_LIST)Marshal.PtrToStructure(streamPointer, typeof(MINIDUMP_MEMORY64_LIST)); ulong lastEnd = data.BaseRva; ranges = new MemoryLocation[data.NumberOfMemoryRanges]; for (int i = 0; i < ranges.Length; i++) { var descriptor = (MINIDUMP_MEMORY_DESCRIPTOR64)Marshal.PtrToStructure(streamPointer + sizeof(MINIDUMP_MEMORY64_LIST) + i * sizeof(MINIDUMP_MEMORY_DESCRIPTOR64), typeof(MINIDUMP_MEMORY_DESCRIPTOR64)); ranges[i] = new MemoryLocation() { MemoryStart = descriptor.StartOfMemoryRange, MemoryEnd = descriptor.StartOfMemoryRange + descriptor.DataSize, FilePosition = lastEnd, }; lastEnd += descriptor.DataSize; } int newEnd = 0; for (int i = 1; i < ranges.Length; i++) if (ranges[i].MemoryStart == ranges[newEnd].MemoryEnd) ranges[newEnd].MemoryEnd = ranges[i].MemoryEnd; else ranges[++newEnd] = ranges[i]; newEnd++; Array.Resize(ref ranges, newEnd); finder = new MemoryRegionFinder(ranges.Select(r => new MemoryRegion { BaseAddress = r.MemoryStart, MemoryEnd = r.MemoryEnd }).ToArray()); dispose = false; } finally { if (dispose) { stream.SafeMemoryMappedViewHandle.ReleasePointer(); if (stream != null) { stream.Dispose(); } if (memoryMappedFile != null) { memoryMappedFile.Dispose(); } if (fileStream != null) { fileStream.Dispose(); } } else { this.fileStream = fileStream; this.stream = stream; this.memoryMappedFile = memoryMappedFile; } } }
/// <summary> /// Load new stream from file starting at the given offset /// </summary> /// <param name="startOfStream"></param> /// <param name="accessor"></param> /// <param name="length"></param> /// <param name="mmf"></param> /// <param name="sizeOfFile"></param> /// <param name="offsetInFile"></param> private void LoadNewStream(ref long startOfStream, ref MemoryMappedViewStream accessor, int length, MemoryMappedFile mmf, long sizeOfFile, long offsetInFile) { long newStartOfStream = offsetInFile; long endPoint = newStartOfStream + length + chunckSize; long newLength = (endPoint > sizeOfFile) ? length : length + chunckSize; newLength = (newLength > chunckSize) ? chunckSize : newLength; //Do not load streams more than chunck accessor.Dispose(); accessor = mmf.CreateViewStream(newStartOfStream, newLength); startOfStream = newStartOfStream; }