public ClrmdSegment(ClrmdHeap heap, IHeapHelpers helpers, ISegmentData data) { if (helpers is null) { throw new ArgumentNullException(nameof(helpers)); } if (data is null) { throw new ArgumentNullException(nameof(data)); } _helpers = helpers; _clrmdHeap = heap; LogicalHeap = data.LogicalHeap; IsLargeObjectSegment = data.IsLargeObjectSegment; IsPinnedObjectSegment = data.IsPinnedObjectSegment; IsEphemeralSegment = data.IsEphemeralSegment; ObjectRange = new MemoryRange(data.Start, data.End); ReservedMemory = new MemoryRange(data.CommittedEnd, data.ReservedEnd); CommittedMemory = new MemoryRange(data.BaseAddress, data.CommittedEnd); Generation0 = MemoryRange.CreateFromLength(data.Gen0Start, data.Gen0Length); Generation1 = MemoryRange.CreateFromLength(data.Gen1Start, data.Gen1Length); Generation2 = MemoryRange.CreateFromLength(data.Gen2Start, data.Gen2Length); _markers = new ulong[MarkerCount]; }
public ClrmdSegment(ClrmdHeap heap, IHeapHelpers helpers, ISegmentData data) { if (helpers is null) { throw new ArgumentNullException(nameof(helpers)); } if (data is null) { throw new ArgumentNullException(nameof(data)); } _helpers = helpers; _clrmdHeap = heap; LogicalHeap = data.LogicalHeap; Start = data.Start; End = data.End; IsLargeObjectSegment = data.IsLargeObjectSegment; IsEphemeralSegment = data.IsEphemeralSegment; ReservedEnd = data.ReservedEnd; CommittedEnd = data.CommittedEnd; Gen0Start = data.Gen0Start; Gen0Length = data.Gen0Length; Gen1Start = data.Gen1Start; Gen1Length = data.Gen1Length; Gen2Start = data.Gen2Start; Gen2Length = data.Gen2Length; _markers = new ulong[MarkerCount]; }
public override IEnumerable <ClrObject> EnumerateObjects() { bool large = IsLargeObjectSegment; uint minObjSize = (uint)IntPtr.Size * 3; ulong obj = FirstObjectAddress; IDataReader dataReader = _helpers.DataReader; // C# isn't smart enough to understand that !large means memoryReader is non-null. We will just be // careful here. using MemoryReader memoryReader = (!large ? new MemoryReader(dataReader, 0x10000) : null) !; byte[] buffer = ArrayPool <byte> .Shared.Rent(IntPtr.Size * 2 + sizeof(uint)); // The large object heap if (!large) { memoryReader.EnsureRangeInCache(obj); } while (ObjectRange.Contains(obj)) { ulong mt; if (large) { if (dataReader.Read(obj, buffer) != buffer.Length) { break; } mt = Unsafe.As <byte, nuint>(ref buffer[0]); } else { if (!memoryReader.ReadPtr(obj, out mt)) { break; } } ClrType?type = _helpers.Factory.GetOrCreateType(_clrmdHeap, mt, obj); if (type is null) { break; } int marker = GetMarkerIndex(obj); if (marker != -1 && _markers[marker] == 0) { _markers[marker] = obj; } ClrObject result = new ClrObject(obj, type); yield return(result); ulong size; if (type.ComponentSize == 0) { size = (uint)type.StaticSize; } else { uint count; if (large) { count = Unsafe.As <byte, uint>(ref buffer[IntPtr.Size]); } else { memoryReader.ReadDword(obj + (uint)IntPtr.Size, out count); } // Strings in v4+ contain a trailing null terminator not accounted for. if (_clrmdHeap.StringType == type) { count++; } size = count * (ulong)type.ComponentSize + (ulong)type.StaticSize; } size = ClrmdHeap.Align(size, large); if (size < minObjSize) { size = minObjSize; } obj += size; obj = _clrmdHeap.SkipAllocationContext(this, obj); } ArrayPool <byte> .Shared.Return(buffer); }
public override ulong GetNextObjectAddress(ulong addr) { if (addr == 0) { return(0); } if (!ObjectRange.Contains(addr)) { throw new InvalidOperationException($"Segment [{FirstObjectAddress:x},{CommittedMemory:x}] does not contain object {addr:x}"); } bool large = IsLargeObjectSegment; uint minObjSize = (uint)IntPtr.Size * 3; IMemoryReader memoryReader = _helpers.DataReader; ulong mt = memoryReader.ReadPointer(addr); ClrType?type = _helpers.Factory.GetOrCreateType(Heap, mt, addr); if (type is null) { return(0); } ulong size; if (type.ComponentSize == 0) { size = (uint)type.StaticSize; } else { uint count = memoryReader.Read <uint>(addr + (uint)IntPtr.Size); // Strings in v4+ contain a trailing null terminator not accounted for. if (Heap.StringType == type) { count++; } size = count * (ulong)type.ComponentSize + (ulong)type.StaticSize; } size = ClrmdHeap.Align(size, large); if (size < minObjSize) { size = minObjSize; } ulong obj = addr + size; if (!large) { obj = _clrmdHeap.SkipAllocationContext(this, obj); // ignore mt here because it won't be used } if (obj >= End) { return(0); } int marker = GetMarkerIndex(obj); if (marker != -1 && _markers[marker] == 0) { _markers[marker] = obj; } return(obj); }