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); }
public IEnumerable <(ulong ReferencedObject, int Offset)> WalkObject(ulong addr, ulong size, IMemoryReader reader) { if (reader is null) { throw new ArgumentNullException(nameof(reader)); } DebugOnly.Assert(size >= (ulong)IntPtr.Size); int series = GetNumSeries(); int highest = GetHighestSeries(); int curr = highest; if (series > 0) { int lowest = GetLowestSeries(); do { ulong ptr = addr + GetSeriesOffset(curr); ulong stop = (ulong)((long)ptr + GetSeriesSize(curr) + (long)size); while (ptr < stop) { ulong ret = reader.ReadPointer(ptr); if (ret != 0) { yield return(ret, (int)(ptr - addr)); } ptr += (ulong)IntPtr.Size; } curr -= s_GCDescSize; } while (curr >= lowest); } else { ulong ptr = addr + GetSeriesOffset(curr); while (ptr < addr + size - (ulong)IntPtr.Size) { for (int i = 0; i > series; i--) { uint nptrs = GetPointers(curr, i); uint skip = GetSkip(curr, i); ulong stop = ptr + (ulong)(nptrs * IntPtr.Size); do { ulong ret = reader.ReadPointer(ptr); if (ret != 0) { yield return(ret, (int)(ptr - addr)); } ptr += (ulong)IntPtr.Size; } while (ptr < stop); ptr += skip; } } } }