in src/Microsoft.Diagnostics.Runtime/src/Implementation/ClrmdHeap.cs [313:379]
public override IEnumerable<ClrReference> EnumerateReferencesWithFields(ulong obj, ClrType type, bool carefully, bool considerDependantHandles)
{
if (type is null)
throw new ArgumentNullException(nameof(type));
if (considerDependantHandles)
{
ImmutableArray<(ulong Source, ulong Target)> dependent = GetHeapData().GetDependentHandles(_helpers);
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 ClrObject(dependantObj, GetObjectType(dependantObj));
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.IsLargeObjectSegment || seg.IsPinnedObjectSegment;
if (obj + size > seg.End || (!large && size > MaxGen2ObjectSize))
yield break;
}
int intSize = (int)size;
byte[] buffer = ArrayPool<byte>.Shared.Rent(intSize);
try
{
int read = _helpers.DataReader.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 ClrObject(reference, GetObjectType(reference));
DebugOnly.Assert(offset >= IntPtr.Size);
yield return ClrReference.CreateFromFieldOrArray(target, type, offset - IntPtr.Size);
}
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
}
}