static bool CrawlPointer(IntermediateCrawlData dataStack) { UnityEngine.Debug.Assert(dataStack.CrawlDataStack.Count > 0); var snapshot = dataStack.CachedMemorySnapshot; var typeDescriptions = snapshot.typeDescriptions; var data = dataStack.CrawlDataStack.Pop(); var virtualMachineInformation = snapshot.virtualMachineInformation; var managedHeapSections = snapshot.managedHeapSections; var byteOffset = managedHeapSections.Find(data.ptr, virtualMachineInformation); if (!byteOffset.IsValid) { return(false); } ManagedObjectInfo obj; bool wasAlreadyCrawled; obj = ParseObjectHeader(snapshot, data.ptr, out wasAlreadyCrawled, false); ++obj.RefCount; snapshot.CrawledData.ManagedObjects[obj.ManagedObjectIndex] = obj; snapshot.CrawledData.ManagedObjectByAddress[obj.PtrObject] = obj; dataStack.ManagedConnections.Add(ManagedConnection.MakeConnection(snapshot, data.indexOfFrom, data.ptrFrom, obj.ManagedObjectIndex, data.ptr, data.typeFrom, data.fieldFrom, data.fromArrayIndex)); if (!obj.IsKnownType()) { return(false); } if (wasAlreadyCrawled) { return(true); } if (!typeDescriptions.HasFlag(obj.ITypeDescription, TypeFlags.kArray)) { CrawlRawObjectData(dataStack, byteOffset.Add(snapshot.virtualMachineInformation.objectHeaderSize), obj.ITypeDescription, false, data.ptr, obj.ManagedObjectIndex); return(true); } var arrayLength = ArrayTools.ReadArrayLength(snapshot, data.ptr, obj.ITypeDescription); int iElementTypeDescription = typeDescriptions.baseOrElementTypeIndex[obj.ITypeDescription]; if (iElementTypeDescription == -1) { return(false); //do not crawl uninitialized object types, as we currently don't have proper handling for these } var arrayData = byteOffset.Add(virtualMachineInformation.arrayHeaderSize); for (int i = 0; i != arrayLength; i++) { if (typeDescriptions.HasFlag(iElementTypeDescription, TypeFlags.kValueType)) { CrawlRawObjectData(dataStack, arrayData, iElementTypeDescription, false, data.ptr, obj.ManagedObjectIndex); arrayData = arrayData.Add(typeDescriptions.size[iElementTypeDescription]); } else { dataStack.CrawlDataStack.Push(new StackCrawlData() { ptr = arrayData.ReadPointer(), ptrFrom = data.ptr, typeFrom = obj.ITypeDescription, indexOfFrom = obj.ManagedObjectIndex, fieldFrom = -1, fromArrayIndex = i }); arrayData = arrayData.NextPointer(); } } return(true); }
public bool IsGroupExpandable(ObjectData od, bool forceExpandAllObject = false) { switch (od.dataType) { case ObjectDataType.Array: { var l = ArrayTools.ReadArrayLength(Snapshot, od.hostManagedObjectPtr, od.managedTypeIndex); return(l > 0 || forceExpandAllObject); } case ObjectDataType.ReferenceArray: { var ptr = od.GetReferencePointer(); if (ptr != 0) { var arr = ObjectData.FromManagedPointer(Snapshot, ptr); var l = ArrayTools.ReadArrayLength(Snapshot, arr.hostManagedObjectPtr, arr.managedTypeIndex); return(l > 0 || forceExpandAllObject); } return(false); } case ObjectDataType.ReferenceObject: { ulong ptr = od.GetReferencePointer(); if (ptr == 0) { return(false); } var obj = ObjectData.FromManagedPointer(Snapshot, ptr); if (!obj.IsValid) { return(false); } if (forceExpandAllObject) { return(true); } if (!Formatter.IsExpandable(obj.managedTypeIndex)) { return(false); } return(Snapshot.typeDescriptions.HasAnyField(obj.managedTypeIndex)); } case ObjectDataType.BoxedValue: case ObjectDataType.Object: case ObjectDataType.Value: if (forceExpandAllObject) { return(true); } if (!Formatter.IsExpandable(od.managedTypeIndex)) { return(false); } return(Snapshot.typeDescriptions.HasAnyField(od.managedTypeIndex)); case ObjectDataType.Type: if (!Formatter.IsExpandable(od.managedTypeIndex)) { return(false); } if (Formatter.flattenFields) { return(Snapshot.typeDescriptions.HasAnyStaticField(od.managedTypeIndex)); } else { return(Snapshot.typeDescriptions.HasStaticField(od.managedTypeIndex)); } default: return(false); } }