static void ConnectNativeToManageObject(IntermediateCrawlData crawlData) { var snapshot = crawlData.CachedMemorySnapshot; var objectInfos = crawlData.ManagedObjectInfos; if (snapshot.typeDescriptions.Count == 0) { return; } // Get UnityEngine.Object int iTypeDescription_UnityEngineObject = snapshot.typeDescriptions.typeDescriptionName.FindIndex(x => x == "UnityEngine.Object"); if (iTypeDescription_UnityEngineObject < 0) { //No Unity Object ? return; } //Get UnityEngine.Object.m_InstanceID field int iField_UnityEngineObject_m_InstanceID = Array.FindIndex( snapshot.typeDescriptions.fieldIndices[iTypeDescription_UnityEngineObject] , iField => snapshot.fieldDescriptions.fieldDescriptionName[iField] == "m_InstanceID"); int instanceIDOffset = -1; int cachedPtrOffset = -1; if (iField_UnityEngineObject_m_InstanceID >= 0) { var fieldIndex = snapshot.typeDescriptions.fieldIndices[iTypeDescription_UnityEngineObject][iField_UnityEngineObject_m_InstanceID]; instanceIDOffset = snapshot.fieldDescriptions.offset[fieldIndex]; } if (instanceIDOffset < 0) { // on UNITY_5_4_OR_NEWER, there is the member m_CachedPtr we can use to identify the connection //Since Unity 5.4, UnityEngine.Object no longer stores instance id inside when running in the player. Use cached ptr instead to find the instanceID of native object int iField_UnityEngineObject_m_CachedPtr = Array.FindIndex( snapshot.typeDescriptions.fieldIndices[iTypeDescription_UnityEngineObject] , iField => snapshot.fieldDescriptions.fieldDescriptionName[iField] == "m_CachedPtr"); if (iField_UnityEngineObject_m_CachedPtr >= 0) { cachedPtrOffset = snapshot.fieldDescriptions.offset[iField_UnityEngineObject_m_CachedPtr]; } } if (instanceIDOffset < 0 && cachedPtrOffset < 0) { Debug.LogWarning("Could not find unity object instance id field or m_CachedPtr"); return; } for (int i = 0; i != objectInfos.Count; i++) { //Must derive of unity Object var objectInfo = objectInfos[i]; objectInfo.NativeObjectIndex = -1; int instanceID = CachedSnapshot.NativeObjectEntriesCache.InstanceID_None; if (DerivesFrom(snapshot.typeDescriptions, objectInfo.ITypeDescription, iTypeDescription_UnityEngineObject)) { //Find object instance id if (iField_UnityEngineObject_m_InstanceID >= 0) { var h = snapshot.managedHeapSections.Find(objectInfo.PtrObject + (UInt64)instanceIDOffset, snapshot.virtualMachineInformation); if (h.IsValid) { instanceID = h.ReadInt32(); } else { Debug.LogWarning("Managed object missing head (addr:" + objectInfo.PtrObject + ", index:" + objectInfo.ManagedObjectIndex + ")"); } } else if (cachedPtrOffset >= 0) { // If you get a compilation error on the following 2 lines, update to Unity 5.4b14. var heapSection = snapshot.managedHeapSections.Find(objectInfo.PtrObject + (UInt64)cachedPtrOffset, snapshot.virtualMachineInformation); if (!heapSection.IsValid) { Debug.LogWarning("Managed object (addr:" + objectInfo.PtrObject + ", index:" + objectInfo.ManagedObjectIndex + ") does not have data at cachedPtr offset(" + cachedPtrOffset + ")"); } else { var cachedPtr = heapSection.ReadPointer(); var indexOfNativeObject = snapshot.nativeObjects.nativeObjectAddress.FindIndex(no => no == cachedPtr); if (indexOfNativeObject >= 0) { instanceID = snapshot.nativeObjects.instanceId[indexOfNativeObject]; } } } if (instanceID != CachedSnapshot.NativeObjectEntriesCache.InstanceID_None && snapshot.nativeObjects.instanceId2Index.TryGetValue(instanceID, out objectInfo.NativeObjectIndex)) { snapshot.nativeObjects.managedObjectIndex[objectInfo.NativeObjectIndex] = i; } } objectInfos[i] = objectInfo; if (snapshot.HasConnectionOverhaul && instanceID != CachedSnapshot.NativeObjectEntriesCache.InstanceID_None) { snapshot.CrawledData.Connections.Add(ManagedConnection.MakeUnityEngineObjectConnection(objectInfo.NativeObjectIndex, objectInfo.ManagedObjectIndex)); ++snapshot.nativeObjects.refcount[objectInfo.NativeObjectIndex]; } snapshot.CrawledData.ManagedObjectByAddress[objectInfo.PtrObject] = objectInfo; } }
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); }
static void ConnectNativeToManageObject(IntermediateCrawlData crawlData) { var snapshot = crawlData.CachedMemorySnapshot; var objectInfos = crawlData.ManagedObjectInfos; if (snapshot.typeDescriptions.Count == 0) { return; } // Get UnityEngine.Object int iTypeDescription_UnityEngineObject = snapshot.typeDescriptions.typeDescriptionName.FindIndex(x => x == "UnityEngine.Object"); #if DEBUG_VALIDATION //This shouldn't really happen if (iTypeDescription_UnityEngineObject < 0) { throw new Exception("Unable to find UnityEngine.Object"); } #endif int cachedPtrOffset = -1; int iField_UnityEngineObject_m_CachedPtr = Array.FindIndex( snapshot.typeDescriptions.fieldIndices[iTypeDescription_UnityEngineObject] , iField => snapshot.fieldDescriptions.fieldDescriptionName[iField] == "m_CachedPtr"); if (iField_UnityEngineObject_m_CachedPtr >= 0) { cachedPtrOffset = snapshot.fieldDescriptions.offset[iField_UnityEngineObject_m_CachedPtr]; } #if DEBUG_VALIDATION if (cachedPtrOffset < 0) { Debug.LogWarning("Could not find unity object instance id field or m_CachedPtr"); return; } #endif for (int i = 0; i != objectInfos.Count; i++) { //Must derive of unity Object var objectInfo = objectInfos[i]; objectInfo.NativeObjectIndex = -1; int instanceID = CachedSnapshot.NativeObjectEntriesCache.k_InstanceIDNone; if (DerivesFrom(snapshot.typeDescriptions, objectInfo.ITypeDescription, iTypeDescription_UnityEngineObject)) { var heapSection = snapshot.managedHeapSections.Find(objectInfo.PtrObject + (ulong)cachedPtrOffset, snapshot.virtualMachineInformation); if (!heapSection.IsValid) { Debug.LogWarning("Managed object (addr:" + objectInfo.PtrObject + ", index:" + objectInfo.ManagedObjectIndex + ") does not have data at cachedPtr offset(" + cachedPtrOffset + ")"); } else { ulong cachedPtr; heapSection.TryReadPointer(out cachedPtr); if (!snapshot.nativeObjects.nativeObjectAddressToInstanceId.TryGetValue(cachedPtr, out instanceID)) { instanceID = CachedSnapshot.NativeObjectEntriesCache.k_InstanceIDNone; } } if (instanceID != CachedSnapshot.NativeObjectEntriesCache.k_InstanceIDNone && snapshot.nativeObjects.instanceId2Index.TryGetValue(instanceID, out objectInfo.NativeObjectIndex)) { snapshot.nativeObjects.managedObjectIndex[objectInfo.NativeObjectIndex] = i; } } objectInfos[i] = objectInfo; if (snapshot.HasConnectionOverhaul && instanceID != CachedSnapshot.NativeObjectEntriesCache.k_InstanceIDNone) { snapshot.CrawledData.Connections.Add(ManagedConnection.MakeUnityEngineObjectConnection(objectInfo.NativeObjectIndex, objectInfo.ManagedObjectIndex)); ++snapshot.nativeObjects.refcount[objectInfo.NativeObjectIndex]; } } }