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 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]; } } }