in ClrMemDiag/Desktop/heap.cs [231:403]
public override IEnumerable<ClrRoot> EnumerateRoots(bool enumerateStatics)
{
if (enumerateStatics)
{
// Statics
foreach (var type in EnumerateTypes())
{
// Statics
foreach (var staticField in type.StaticFields)
{
if (!ClrRuntime.IsPrimitive(staticField.ElementType))
{
foreach (var ad in DesktopRuntime.AppDomains)
{
ulong addr = 0;
ulong value = 0;
// We must manually get the value, as strings will not be returned as an object address.
try // If this fails for whatever reasion, don't fail completely.
{
addr = staticField.GetAddress(ad);
}
catch (Exception e)
{
Trace.WriteLine(string.Format("Error getting stack field {0}.{1}: {2}", type.Name, staticField.Name, e.Message));
goto NextStatic;
}
if (DesktopRuntime.ReadPointer(addr, out value) && value != 0)
{
ClrType objType = GetObjectType(value);
if (objType != null)
yield return new StaticVarRoot(addr, value, objType, type.Name, staticField.Name, ad);
}
}
}
NextStatic:;
}
// Thread statics
foreach (var tsf in type.ThreadStaticFields)
{
if (ClrRuntime.IsObjectReference(tsf.ElementType))
{
foreach (var ad in DesktopRuntime.AppDomains)
{
foreach (var thread in DesktopRuntime.Threads)
{
// We must manually get the value, as strings will not be returned as an object address.
ulong addr = tsf.GetAddress(ad, thread);
ulong value = 0;
if (DesktopRuntime.ReadPointer(addr, out value) && value != 0)
{
ClrType objType = GetObjectType(value);
if (objType != null)
yield return new ThreadStaticVarRoot(addr, value, objType, type.Name, tsf.Name, ad);
}
}
}
}
}
}
}
// Handles
var handles = DesktopRuntime.EnumerateHandles();
if (handles != null)
{
foreach (ClrHandle handle in handles)
{
Address objAddr = handle.Object;
GCRootKind kind = GCRootKind.Strong;
if (objAddr != 0)
{
ClrType type = GetObjectType(objAddr);
if (type != null)
{
switch (handle.HandleType)
{
case HandleType.WeakShort:
case HandleType.WeakLong:
break;
case HandleType.RefCount:
if (handle.RefCount <= 0)
break;
goto case HandleType.Strong;
case HandleType.Dependent:
if (objAddr == 0)
continue;
objAddr = handle.DependentTarget;
goto case HandleType.Strong;
case HandleType.Pinned:
kind = GCRootKind.Pinning;
goto case HandleType.Strong;
case HandleType.AsyncPinned:
kind = GCRootKind.AsyncPinning;
goto case HandleType.Strong;
case HandleType.Strong:
case HandleType.SizedRef:
yield return new HandleRoot(handle.Address, objAddr, type, handle.HandleType, kind, handle.AppDomain);
// Async pinned handles keep 1 or more "sub objects" alive. I will report them here as their own pinned handle.
if (handle.HandleType == HandleType.AsyncPinned)
{
ClrInstanceField userObjectField = type.GetFieldByName("m_userObject");
if (userObjectField != null)
{
ulong _userObjAddr = userObjectField.GetAddress(objAddr);
ulong _userObj = (ulong)userObjectField.GetValue(objAddr);
var _userObjType = GetObjectType(_userObj);
if (_userObjType != null)
{
if (_userObjType.IsArray)
{
if (_userObjType.ComponentType != null)
{
if (_userObjType.ComponentType.ElementType == ClrElementType.Object)
{
// report elements
int len = _userObjType.GetArrayLength(_userObj);
for (int i = 0; i < len; ++i)
{
ulong indexAddr = _userObjType.GetArrayElementAddress(_userObj, i);
ulong indexObj = (ulong)_userObjType.GetArrayElementValue(_userObj, i);
ClrType indexObjType = GetObjectType(indexObj);
if (indexObj != 0 && indexObjType != null)
yield return new HandleRoot(indexAddr, indexObj, indexObjType, HandleType.AsyncPinned, GCRootKind.AsyncPinning, handle.AppDomain);
}
}
else
{
yield return new HandleRoot(_userObjAddr, _userObj, _userObjType, HandleType.AsyncPinned, GCRootKind.AsyncPinning, handle.AppDomain);
}
}
}
else
{
yield return new HandleRoot(_userObjAddr, _userObj, _userObjType, HandleType.AsyncPinned, GCRootKind.AsyncPinning, handle.AppDomain);
}
}
}
}
break;
default:
Debug.WriteLine("Warning, unknown handle type {0} ignored", Enum.GetName(typeof(HandleType), handle.HandleType));
break;
}
}
}
}
}
else
{
Trace.WriteLine("Warning, GetHandles() return null!");
}
// Finalization Queue
foreach (Address objAddr in DesktopRuntime.EnumerateFinalizerQueueObjectAddresses())
if (objAddr != 0)
{
ClrType type = GetObjectType(objAddr);
if (type != null)
yield return new FinalizerRoot(objAddr, type);
}
// Threads
foreach (ClrThread thread in DesktopRuntime.Threads)
if (thread.IsAlive)
foreach (var root in thread.EnumerateStackObjects(false))
yield return root;
}