in src/Microsoft.Diagnostics.Runtime/ClrHeap.cs [964:1024]
internal IEnumerable<ClrReference> EnumerateReferencesWithFields(ulong obj, ClrType type, bool carefully, bool considerDependantHandles)
{
if (type is null)
throw new ArgumentNullException(nameof(type));
if (considerDependantHandles)
{
(ulong Source, ulong Target)[] dependent = GetDependentHandles();
if (dependent.Length > 0)
{
int index = dependent.Search(obj, (x, y) => x.Source.CompareTo(y));
if (index != -1)
{
while (index >= 1 && dependent[index - 1].Source == obj)
index--;
while (index < dependent.Length && dependent[index].Source == obj)
{
ulong dependantObj = dependent[index++].Target;
ClrObject target = new(dependantObj, GetObjectType(dependantObj) ?? ErrorType);
yield return ClrReference.CreateFromDependentHandle(target);
}
}
}
}
if (type.ContainsPointers)
{
GCDesc gcdesc = type.GCDesc;
if (!gcdesc.IsEmpty)
{
ulong size = GetObjectSize(obj, type);
if (carefully)
{
ClrSegment? seg = GetSegmentByAddress(obj);
if (seg is null)
yield break;
bool large = seg.Kind is GCSegmentKind.Large or GCSegmentKind.Pinned;
if (obj + size > seg.End || (!large && size > MaxGen2ObjectSize))
yield break;
}
int intSize = (int)size;
byte[] buffer = ArrayPool<byte>.Shared.Rent(intSize);
int read = _memoryReader.Read(obj, new Span<byte>(buffer, 0, intSize));
if (read > IntPtr.Size)
{
foreach ((ulong reference, int offset) in gcdesc.WalkObject(buffer, read))
{
ClrObject target = new(reference, GetObjectType(reference) ?? ErrorType);
DebugOnly.Assert(offset >= IntPtr.Size);
yield return ClrReference.CreateFromFieldOrArray(target, type, offset - IntPtr.Size);
}
}
ArrayPool<byte>.Shared.Return(buffer);
}
}
}