public override IEnumerable EnumerateRoots()

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;
        }