Пример #1
0
        public override IEnumerable <ClrObject> EnumerateObjects()
        {
            bool        large      = IsLargeObjectSegment;
            uint        minObjSize = (uint)IntPtr.Size * 3;
            ulong       obj        = FirstObjectAddress;
            IDataReader dataReader = _helpers.DataReader;

            // C# isn't smart enough to understand that !large means memoryReader is non-null.  We will just be
            // careful here.
            using MemoryReader memoryReader = (!large ? new MemoryReader(dataReader, 0x10000) : null) !;
            byte[] buffer = ArrayPool <byte> .Shared.Rent(IntPtr.Size * 2 + sizeof(uint));

            // The large object heap
            if (!large)
            {
                memoryReader.EnsureRangeInCache(obj);
            }

            while (ObjectRange.Contains(obj))
            {
                ulong mt;
                if (large)
                {
                    if (dataReader.Read(obj, buffer) != buffer.Length)
                    {
                        break;
                    }

                    mt = Unsafe.As <byte, nuint>(ref buffer[0]);
                }
                else
                {
                    if (!memoryReader.ReadPtr(obj, out mt))
                    {
                        break;
                    }
                }

                ClrType?type = _helpers.Factory.GetOrCreateType(_clrmdHeap, mt, obj);
                if (type is null)
                {
                    break;
                }

                int marker = GetMarkerIndex(obj);
                if (marker != -1 && _markers[marker] == 0)
                {
                    _markers[marker] = obj;
                }

                ClrObject result = new ClrObject(obj, type);
                yield return(result);

                ulong size;
                if (type.ComponentSize == 0)
                {
                    size = (uint)type.StaticSize;
                }
                else
                {
                    uint count;
                    if (large)
                    {
                        count = Unsafe.As <byte, uint>(ref buffer[IntPtr.Size]);
                    }
                    else
                    {
                        memoryReader.ReadDword(obj + (uint)IntPtr.Size, out count);
                    }

                    // Strings in v4+ contain a trailing null terminator not accounted for.
                    if (_clrmdHeap.StringType == type)
                    {
                        count++;
                    }

                    size = count * (ulong)type.ComponentSize + (ulong)type.StaticSize;
                }

                size = ClrmdHeap.Align(size, large);
                if (size < minObjSize)
                {
                    size = minObjSize;
                }

                obj += size;
                obj  = _clrmdHeap.SkipAllocationContext(this, obj);
            }

            ArrayPool <byte> .Shared.Return(buffer);
        }