Beispiel #1
0
 public static ObjectRange GetObjectRangeEnum(string value, ObjectRange defaultValue)
 {
     foreach (ObjectRange item in Enum.GetValues(typeof(ObjectRange)))
     {
         if (item.ToString() == value)
         {
             return(item);
         }
     }
     return(defaultValue);
 }
Beispiel #2
0
        public override ulong GetPreviousObjectAddress(ulong addr)
        {
            if (!ObjectRange.Contains(addr))
            {
                throw new InvalidOperationException($"Segment [{FirstObjectAddress:x},{CommittedMemory:x}] does not contain address {addr:x}");
            }

            if (addr == FirstObjectAddress)
            {
                return(0);
            }

            // Default to the start of the segment
            ulong prevAddr = FirstObjectAddress;

            // Look for markers that are closer to the address.  We keep the size of _markers small so a linear walk
            // should be roughly as fast as a binary search.
            foreach (ulong marker in _markers)
            {
                // Markers can be 0 even when _markers was fully initialized by a full heap walk.  This is because parts of
                // the ephemeral GC heap may be not in use (allocation contexts) or when objects on the large object heap
                // are so big that there's simply not a valid object starting point in that range.
                if (marker != 0)
                {
                    if (marker >= addr)
                    {
                        break;
                    }

                    prevAddr = marker;
                }
            }

            // Linear walk from the last known good previous address to the one we are looking for.
            // This could take a while if we don't know a close enough address.
            ulong curr = prevAddr;

            while (curr != 0 && curr <= addr)
            {
                ulong next = GetNextObjectAddress(curr);

                if (next >= addr)
                {
                    return(curr);
                }

                curr = next;
            }

            return(0);
        }
Beispiel #3
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);
        }
Beispiel #4
0
        public override ulong GetNextObjectAddress(ulong addr)
        {
            if (addr == 0)
            {
                return(0);
            }

            if (!ObjectRange.Contains(addr))
            {
                throw new InvalidOperationException($"Segment [{FirstObjectAddress:x},{CommittedMemory:x}] does not contain object {addr:x}");
            }

            bool          large        = IsLargeObjectSegment;
            uint          minObjSize   = (uint)IntPtr.Size * 3;
            IMemoryReader memoryReader = _helpers.DataReader;
            ulong         mt           = memoryReader.ReadPointer(addr);

            ClrType?type = _helpers.Factory.GetOrCreateType(Heap, mt, addr);

            if (type is null)
            {
                return(0);
            }

            ulong size;

            if (type.ComponentSize == 0)
            {
                size = (uint)type.StaticSize;
            }
            else
            {
                uint count = memoryReader.Read <uint>(addr + (uint)IntPtr.Size);

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

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

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

            ulong obj = addr + size;

            if (!large)
            {
                obj = _clrmdHeap.SkipAllocationContext(this, obj); // ignore mt here because it won't be used
            }
            if (obj >= End)
            {
                return(0);
            }

            int marker = GetMarkerIndex(obj);

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

            return(obj);
        }