/// <summary> /// Initializes a new instance of the <see cref="MemoryRegionFinder"/> class. /// </summary> /// <param name="regions">The memory regions.</param> public MemoryRegionFinder(IReadOnlyList <MemoryRegion> regions) { if (regions.Count > 0) { ulong minValue = regions[0].MemoryStart; ulong maxValue = regions[regions.Count - 1].MemoryEnd; triesStartBits = 64 - BucketSizeBits; triesStartMask = ((1UL << BucketSizeBits) - 1) << triesStartBits; while ((triesStartMask & (maxValue - 1)) == 0) { triesStartMask >>= BucketSizeBits; triesStartBits -= BucketSizeBits; } Tuple <int, MemoryRegion>[] regionsTuple = new Tuple <int, MemoryRegion> [regions.Count]; for (int i = 0; i < regionsTuple.Length; i++) { regionsTuple[i] = Tuple.Create(i, regions[i]); } TriesElement element = new TriesElement(regionsTuple, triesStartMask, triesStartBits); buckets = element.buckets; if (buckets == null) { buckets = new TriesElement[] { element }; } } else { buckets = new TriesElement[0]; } }
/// <summary> /// Finds the index of memory region where the specified address is located or -1 if not found. /// </summary> /// <param name="address">The address.</param> /// <returns>The index of memory region where the specified address is located or -1 if not found.</returns> public int Find(ulong address) { ulong mask = triesStartMask; int offset = triesStartBits; ulong bucketIndex = (address & mask) >> offset; if (bucketIndex < (ulong)buckets.LongLength) { TriesElement bucket = buckets[bucketIndex]; while (bucket != null && bucket.buckets != null) { mask >>= BucketSizeBits; offset -= BucketSizeBits; bucketIndex = (address & mask) >> offset; bucket = bucket.buckets[bucketIndex]; } if (bucket != null) { return(bucket.location); } } return(-1); }
public TriesElement(IReadOnlyList <Tuple <int, MemoryRegion> > regions, ulong triesStartMask, int triesStartBits, ulong minValue = 0, ulong maxValue = ulong.MaxValue) { if (regions.Count > 1) { var division = new List <Tuple <int, MemoryRegion> > [1 << BucketSizeBits]; foreach (var region in regions) { ulong bucketStart = (Math.Max(minValue, region.Item2.MemoryStart) & triesStartMask) >> triesStartBits; ulong bucketEnd = (Math.Min(maxValue, region.Item2.MemoryEnd - 1) & triesStartMask) >> triesStartBits; for (ulong j = bucketStart; j <= bucketEnd; j++) { if (division[j] == null) { division[j] = new List <Tuple <int, MemoryRegion> >(); } division[j].Add(region); } } buckets = new TriesElement[1 << BucketSizeBits]; for (int i = 0; i < 1 << BucketSizeBits; i++) { if (division[i] != null) { buckets[i] = new TriesElement(division[i], triesStartMask >> BucketSizeBits, triesStartBits - BucketSizeBits, minValue | ((ulong)i << triesStartBits), minValue | (((ulong)i + 1) << triesStartBits) - 1); } } } else { location = regions[0].Item1; } }
public TriesElement(IEnumerable <Tuple <int, MemoryLocation> > ranges, ulong triesStartMask, int triesStartBits, ulong minValue = 0, ulong maxValue = ulong.MaxValue) { if (ranges.Count() > 1) { var division = new List <Tuple <int, MemoryLocation> > [1 << BucketSizeBits]; foreach (var range in ranges) { var bucketStart = (Math.Max(minValue, range.Item2.MemoryStart) & triesStartMask) >> triesStartBits; var bucketEnd = (Math.Min(maxValue, range.Item2.MemoryEnd - 1) & triesStartMask) >> triesStartBits; for (var j = bucketStart; j <= bucketEnd; j++) { if (division[j] == null) { division[j] = new List <Tuple <int, MemoryLocation> >(); } division[j].Add(range); } } buckets = new TriesElement[1 << BucketSizeBits]; for (int i = 0; i < 1 << BucketSizeBits; i++) { if (division[i] != null) { buckets[i] = new TriesElement(division[i], triesStartMask >> BucketSizeBits, triesStartBits - BucketSizeBits, minValue | ((ulong)i << triesStartBits), minValue | (((ulong)i + 1) << triesStartBits) - 1); } } } else { location = ranges.First().Item1; } }
/// <summary> /// Initializes a new instance of the <see cref="MemoryRegionFinder"/> class. /// </summary> /// <param name="regions">The memory regions.</param> public MemoryRegionFinder(MemoryRegion[] regions) { ulong minValue = regions[0].MemoryStart; ulong maxValue = regions[regions.Length - 1].MemoryEnd; triesStartBits = 64 - BucketSizeBits; triesStartMask = ((1UL << BucketSizeBits) - 1) << triesStartBits; while ((triesStartMask & (maxValue - 1)) == 0) { triesStartMask >>= BucketSizeBits; triesStartBits -= BucketSizeBits; } Tuple <int, MemoryRegion>[] regionsTuple = new Tuple <int, MemoryRegion> [regions.Length]; for (int i = 0; i < regionsTuple.Length; i++) { regionsTuple[i] = Tuple.Create(i, regions[i]); } TriesElement element = new TriesElement(regionsTuple, triesStartMask, triesStartBits); buckets = element.buckets; }
/// <summary> /// Initializes a new instance of the <see cref="MemoryRegionFinder"/> class. /// </summary> /// <param name="regions">The memory regions.</param> public MemoryRegionFinder(MemoryRegion[] regions) { ulong minValue = regions[0].MemoryStart; ulong maxValue = regions[regions.Length - 1].MemoryEnd; triesStartBits = 64 - BucketSizeBits; triesStartMask = ((1UL << BucketSizeBits) - 1) << triesStartBits; while ((triesStartMask & (maxValue - 1)) == 0) { triesStartMask >>= BucketSizeBits; triesStartBits -= BucketSizeBits; } Tuple<int, MemoryRegion>[]regionsTuple = new Tuple<int, MemoryRegion>[regions.Length]; for (int i = 0; i < regionsTuple.Length; i++) regionsTuple[i] = Tuple.Create(i, regions[i]); TriesElement element = new TriesElement(regionsTuple, triesStartMask, triesStartBits); buckets = element.buckets; }
public TriesElement(IReadOnlyList<Tuple<int, MemoryRegion>> regions, ulong triesStartMask, int triesStartBits, ulong minValue = 0, ulong maxValue = ulong.MaxValue) { if (regions.Count > 1) { var division = new List<Tuple<int, MemoryRegion>>[1 << BucketSizeBits]; foreach (var region in regions) { ulong bucketStart = (Math.Max(minValue, region.Item2.MemoryStart) & triesStartMask) >> triesStartBits; ulong bucketEnd = (Math.Min(maxValue, region.Item2.MemoryEnd - 1) & triesStartMask) >> triesStartBits; for (ulong j = bucketStart; j <= bucketEnd; j++) { if (division[j] == null) division[j] = new List<Tuple<int, MemoryRegion>>(); division[j].Add(region); } } buckets = new TriesElement[1 << BucketSizeBits]; for (int i = 0; i < 1 << BucketSizeBits; i++) if (division[i] != null) buckets[i] = new TriesElement(division[i], triesStartMask >> BucketSizeBits, triesStartBits - BucketSizeBits, minValue | ((ulong)i << triesStartBits), minValue | (((ulong)i + 1) << triesStartBits) - 1); } else { location = regions[0].Item1; } }
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); var minValue = ranges[0].MemoryStart; var maxValue = ranges[ranges.Length - 1].MemoryEnd; triesStartBits = 64 - BucketSizeBits; triesStartMask = ((1UL << BucketSizeBits) - 1) << triesStartBits; while ((triesStartMask & (maxValue - 1)) == 0) { triesStartMask >>= BucketSizeBits; triesStartBits -= BucketSizeBits; } var rangesTuple = new Tuple <int, MemoryLocation> [ranges.Length]; for (int i = 0; i < rangesTuple.Length; i++) { rangesTuple[i] = Tuple.Create(i, ranges[i]); } var element = new TriesElement(rangesTuple, triesStartMask, triesStartBits); buckets = element.buckets; dispose = false; } catch (Exception ex) { Console.Error.WriteLine(ex); throw; } 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; } } }