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);
        }
Example #3
0
        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];
                }
            }
        }