public override Address NextObject(Address addr) { if (addr >= CommittedEnd) { return(0); } uint minObjSize = (uint)m_clr.PointerSize * 3; ClrType type = m_heap.GetObjectType(addr); if (type == null) { return(0); } ulong size = type.GetSize(addr); size = Align(size, m_large); if (size < minObjSize) { size = minObjSize; } // Move to the next object addr += size; // Check to make sure a GC didn't cause "count" to be invalid, leading to too large // of an object if (addr >= End) { return(0); } // Ensure we aren't at the start of an alloc context ulong tmp; while (!IsLarge && m_subHeap.AllocPointers.TryGetValue(addr, out tmp)) { tmp += Align(minObjSize, m_large); // Only if there's data corruption: if (addr >= tmp) { return(0); } // Otherwise: addr = tmp; if (addr >= End) { return(0); } } return(addr); }
public override ulong NextObject(ulong objRef) { if (objRef >= CommittedEnd) { return(0); } uint minObjSize = (uint)_clr.PointerSize * 3; ClrType currType = _heap.GetObjectType(objRef); if (currType == null) { return(0); } ulong size = currType.GetSize(objRef); size = Align(size, _large); if (size < minObjSize) { size = minObjSize; } // Move to the next object objRef += size; // Check to make sure a GC didn't cause "count" to be invalid, leading to too large // of an object if (objRef >= End) { return(0); } // Ensure we aren't at the start of an alloc context ulong tmp; while (!IsLarge && _subHeap.AllocPointers.TryGetValue(objRef, out tmp)) { tmp += Align(minObjSize, _large); // Only if there's data corruption: if (objRef >= tmp) { return(0); } // Otherwise: objRef = tmp; if (objRef >= End) { return(0); } } return(objRef); }
internal static bool IsTooLarge(ulong obj, ClrType type, ClrSegment seg) { ulong size = type.GetSize(obj); if (!seg.IsLarge && size >= 85000) { return(true); } return(obj + size > seg.End); }
protected internal override IEnumerable <ClrObjectReference> EnumerateObjectReferencesWithFields(ulong obj, ClrType type, bool carefully) { if (type == null) { type = GetObjectType(obj); } else { Debug.Assert(type == GetObjectType(obj)); } if (type == null || (!type.ContainsPointers && !type.IsCollectible)) { return(s_emptyObjectReferenceSet); } List <ClrObjectReference> result = null; if (type.ContainsPointers) { GCDesc gcdesc = type.GCDesc; if (gcdesc == null) { return(s_emptyObjectReferenceSet); } ulong size = type.GetSize(obj); if (carefully) { ClrSegment seg = GetSegmentByAddress(obj); if (seg == null || obj + size > seg.End || (!seg.IsLarge && size > 85000)) { return(s_emptyObjectReferenceSet); } } result = new List <ClrObjectReference>(); MemoryReader reader = GetMemoryReaderForAddress(obj); gcdesc.WalkObject(obj, size, ptr => ReadPointer(reader, ptr), (reference, offset) => result.Add(new ClrObjectReference(offset, reference, GetObjectType(reference)))); } if (type.IsCollectible) { result ??= new List <ClrObjectReference>(1); ulong loaderAllocatorObject = type.LoaderAllocatorObject; result.Add(new ClrObjectReference(-1, loaderAllocatorObject, GetObjectType(loaderAllocatorObject))); } return(result); }
protected internal override IEnumerable <ClrObject> EnumerateObjectReferences(ulong obj, ClrType type, bool carefully) { if (type == null) { type = GetObjectType(obj); } else { Debug.Assert(type == GetObjectType(obj)); } if (!type.ContainsPointers) { return(s_emptyObjectSet); } GCDesc gcdesc = type.GCDesc; if (gcdesc == null) { return(s_emptyObjectSet); } ulong size = type.GetSize(obj); if (carefully) { ClrSegment seg = GetSegmentByAddress(obj); if (seg == null || obj + size > seg.End || !seg.IsLarge && size > 85000) { return(s_emptyObjectSet); } } List <ClrObject> result = new List <ClrObject>(); MemoryReader reader = GetMemoryReaderForAddress(obj); gcdesc.WalkObject(obj, size, ptr => ReadPointer(reader, ptr), (reference, offset) => result.Add(new ClrObject(reference, GetObjectType(reference)))); return(result); }
protected internal override void EnumerateObjectReferences(ulong obj, ClrType type, bool carefully, Action <ulong, int> callback) { if (type == null) { type = GetObjectType(obj); } else { Debug.Assert(type == GetObjectType(obj)); } if (!type.ContainsPointers) { return; } GCDesc gcdesc = type.GCDesc; if (gcdesc == null) { return; } ulong size = type.GetSize(obj); if (carefully) { ClrSegment seg = GetSegmentByAddress(obj); if (seg == null || obj + size > seg.End || !seg.IsLarge && size > 85000) { return; } } MemoryReader reader = GetMemoryReaderForAddress(obj); gcdesc.WalkObject(obj, size, ptr => ReadPointer(reader, ptr), callback); }
private static void VerifyStringObjectSize(ClrRuntime runtime, ClrType type, ulong obj, string text) { var objSize = type.GetSize(obj); var objAsHex = obj.ToString("x"); var rawBytes = Encoding.Unicode.GetBytes(text); if (runtime.ClrInfo.Version.Major == 2) { // This only works in .NET 2.0, the "m_array_Length" field was removed in .NET 4.0 var arrayLength = (int)type.GetFieldByName("m_arrayLength").GetValue(obj); var stringLength = (int)type.GetFieldByName("m_stringLength").GetValue(obj); var calculatedSize = (((ulong)arrayLength - 1) * 2) + HeaderSize; if (objSize != calculatedSize) { Console.WriteLine("Object Size Mismatch: arrayLength: {0,4}, stringLength: {1,4}, Object Size: {2,4}, Object: {3} -> \n\"{4}\"", arrayLength, stringLength, objSize, objAsHex, text); } } else { // In .NET 4.0 we can do a more normal check, i.e. ("object size" - "raw byte array length") should equal the expected header size var theRest = objSize - (ulong)rawBytes.Length; if (theRest != HeaderSize) { Console.WriteLine("Object Size Mismatch: Raw Bytes Length: {0,4}, Object Size: {1,4}, Object: {2} -> \n\"{3}\"", rawBytes.Length, objSize, objAsHex, text); } } }