コード例 #1
0
        void CrawlManagedObjects()
        {
            var virtualMachineInformation = m_Snapshot.virtualMachineInformation;
            var nestedStructsIgnored      = 0;

            //var guard = 0;
            while (m_Crawl.Count > 0)
            {
                //if (++guard > 10000000)
                //{
                //    Debug.LogWarning("Loop guard kicked in");
                //    break;
                //}
                if ((m_TotalCrawled % 1000) == 0)
                {
                    UpdateProgress();
                    if (m_Snapshot.abortActiveStepRequested)
                    {
                        break;
                    }
                }

                var mo = m_Crawl[m_Crawl.Count - 1];
                m_Crawl.RemoveAt(m_Crawl.Count - 1);

#if DEBUG_BREAK_ON_ADDRESS
                if (mo.address == DebugBreakOnAddress)
                {
                    int a = 0;
                }
#endif

                var loopGuard = 0;
                var typeIndex = mo.managedTypesArrayIndex;

                while (typeIndex != -1)
                {
                    if (++loopGuard > 264)
                    {
                        break;
                    }

                    AbstractMemoryReader memoryReader = m_MemoryReader;
                    if (mo.staticBytes != null)
                    {
                        memoryReader = new StaticMemoryReader(m_Snapshot, mo.staticBytes);
                    }

                    var baseType = m_Snapshot.managedTypes[typeIndex];

                    if (baseType.isArray)
                    {
                        if (baseType.baseOrElementTypeIndex < 0 || baseType.baseOrElementTypeIndex >= m_Snapshot.managedTypes.Length)
                        {
                            m_Snapshot.Error("'{0}.baseOrElementTypeIndex' = {1} at address '{2:X}', ignoring managed object.", baseType.name, baseType.baseOrElementTypeIndex, mo.address);
                            break;
                        }

                        var elementType = m_Snapshot.managedTypes[baseType.baseOrElementTypeIndex];
                        if (elementType.isValueType && elementType.isPrimitive)
                        {
                            break; // don't crawl int[], byte[], etc
                        }
                        if (elementType.isValueType && !ContainsReferenceType(elementType.managedTypesArrayIndex))
                        {
                            break;
                        }

                        var dim0Length = mo.address > 0 ? memoryReader.ReadArrayLength(mo.address, baseType) : 0;
                        //if (dim0Length > 1024 * 1024)
                        if (dim0Length > (32 * 1024) * (32 * 1024))
                        {
                            m_Snapshot.Error("Array (rank={2}) found at address '{0:X} with '{1}' elements, that doesn't seem right.", mo.address, dim0Length, baseType.arrayRank);
                            break;
                        }

                        for (var k = 0; k < dim0Length; ++k)
                        {
                            if ((m_TotalCrawled % 1000) == 0)
                            {
                                UpdateProgress();
                            }

                            ulong elementAddr = 0;

                            if (elementType.isArray)
                            {
                                elementAddr = memoryReader.ReadPointer(mo.address + (ulong)(k * virtualMachineInformation.pointerSize) + (ulong)virtualMachineInformation.arrayHeaderSize);
                            }
                            else if (elementType.isValueType)
                            {
                                elementAddr = mo.address + (ulong)(k * elementType.size) + (ulong)virtualMachineInformation.arrayHeaderSize - (ulong)virtualMachineInformation.objectHeaderSize;
                            }
                            else
                            {
                                elementAddr = memoryReader.ReadPointer(mo.address + (ulong)(k * virtualMachineInformation.pointerSize) + (ulong)virtualMachineInformation.arrayHeaderSize);
                            }

#if DEBUG_BREAK_ON_ADDRESS
                            if (elementAddr == DebugBreakOnAddress)
                            {
                                int a = 0;
                            }
#endif

                            if (elementAddr != 0)
                            {
                                int newObjectIndex;
                                if (!m_Seen.TryGetValue(elementAddr, out newObjectIndex))
                                {
                                    var newObj = PackedManagedObject.New();
                                    newObj.address = elementAddr;
                                    newObj.managedTypesArrayIndex   = elementType.managedTypesArrayIndex;
                                    newObj.managedObjectsArrayIndex = m_ManagedObjects.Count;

                                    if (elementType.isValueType)
                                    {
                                        newObj.managedObjectsArrayIndex = mo.managedObjectsArrayIndex;
                                        newObj.staticBytes = mo.staticBytes;
                                    }
                                    else
                                    {
                                        newObj.managedTypesArrayIndex = m_Snapshot.FindManagedObjectTypeOfAddress(elementAddr);
                                        if (newObj.managedTypesArrayIndex == -1)
                                        {
                                            newObj.managedTypesArrayIndex = elementType.managedTypesArrayIndex;
                                        }

                                        TryConnectNativeObject(ref newObj);
                                    }
                                    SetObjectSize(ref newObj, m_Snapshot.managedTypes[newObj.managedTypesArrayIndex]);

                                    if (!elementType.isValueType)
                                    {
                                        m_ManagedObjects.Add(newObj);
                                    }

                                    m_Seen[newObj.address] = newObj.managedObjectsArrayIndex;
                                    m_Crawl.Add(newObj);
                                    m_TotalCrawled++;
                                    newObjectIndex = newObj.managedObjectsArrayIndex;
                                }

                                // If we do not connect the Slot elements at Slot[] 0x1DB2A512EE0
                                if (!elementType.isValueType)
                                {
                                    if (mo.managedObjectsArrayIndex >= 0)
                                    {
                                        m_Snapshot.AddConnection(PackedConnection.Kind.Managed, mo.managedObjectsArrayIndex, PackedConnection.Kind.Managed, newObjectIndex);
                                    }
                                    else
                                    {
                                        m_Snapshot.AddConnection(PackedConnection.Kind.StaticField, -mo.managedObjectsArrayIndex, PackedConnection.Kind.Managed, newObjectIndex);
                                    }
                                }
                            }
                        }

                        break;
                    }

                    for (var n = 0; n < baseType.fields.Length; ++n)
                    {
                        var field = baseType.fields[n];
                        if (field.isStatic)
                        {
                            continue;
                        }

                        var fieldType = m_Snapshot.managedTypes[field.managedTypesArrayIndex];

                        if (fieldType.isValueType)
                        {
                            if (fieldType.isPrimitive)
                            {
                                continue;
                            }

                            if (s_IgnoreNestedStructs && mo.managedTypesArrayIndex == fieldType.managedTypesArrayIndex)
                            {
                                nestedStructsIgnored++;
                                continue;
                            }

                            var newObj = PackedManagedObject.New();

                            if (mo.staticBytes == null)
                            {
                                newObj.address = mo.address + (uint)field.offset - (uint)virtualMachineInformation.objectHeaderSize;
                            }
                            else
                            {
                                newObj.address = mo.address + (uint)field.offset - (uint)virtualMachineInformation.objectHeaderSize;
                            }

                            newObj.managedObjectsArrayIndex = mo.managedObjectsArrayIndex;
                            newObj.managedTypesArrayIndex   = fieldType.managedTypesArrayIndex;
                            newObj.staticBytes = mo.staticBytes;
                            SetObjectSize(ref newObj, fieldType);

                            m_Crawl.Add(newObj); // Crawl, but do not add value types to the managedlist
                            m_TotalCrawled++;
                            continue;
                        }

                        if (!fieldType.isValueType)
                        {
                            ulong addr = 0;
                            if (mo.staticBytes == null)
                            {
                                addr = memoryReader.ReadPointer(mo.address + (uint)field.offset);
                            }
                            else
                            {
                                addr = memoryReader.ReadPointer(mo.address + (uint)field.offset - (uint)virtualMachineInformation.objectHeaderSize);
                            }

                            if (addr == 0)
                            {
                                continue;
                            }

#if DEBUG_BREAK_ON_ADDRESS
                            if (addr == DebugBreakOnAddress)
                            {
                                int a = 0;
                            }
#endif

                            int newObjIndex;
                            if (!m_Seen.TryGetValue(addr, out newObjIndex))
                            {
                                var newObj = PackedManagedObject.New();
                                newObj.address = addr;
                                newObj.managedObjectsArrayIndex = m_ManagedObjects.Count;
                                newObj.managedTypesArrayIndex   = m_Snapshot.FindManagedObjectTypeOfAddress(addr);
                                if (newObj.managedTypesArrayIndex == -1)
                                {
                                    newObj.managedTypesArrayIndex = fieldType.managedTypesArrayIndex;
                                }

                                SetObjectSize(ref newObj, m_Snapshot.managedTypes[newObj.managedTypesArrayIndex]);
                                TryConnectNativeObject(ref newObj);

                                m_Seen[newObj.address] = newObj.managedObjectsArrayIndex;
                                m_ManagedObjects.Add(newObj);
                                m_Crawl.Add(newObj);
                                m_TotalCrawled++;
                                newObjIndex = newObj.managedObjectsArrayIndex;
                            }

                            if (mo.managedObjectsArrayIndex >= 0)
                            {
                                m_Snapshot.AddConnection(PackedConnection.Kind.Managed, mo.managedObjectsArrayIndex, PackedConnection.Kind.Managed, newObjIndex);
                            }
                            else
                            {
                                m_Snapshot.AddConnection(PackedConnection.Kind.StaticField, -mo.managedObjectsArrayIndex, PackedConnection.Kind.Managed, newObjIndex);
                            }

                            continue;
                        }
                    }

                    if (typeIndex == baseType.baseOrElementTypeIndex || baseType.isArray)
                    {
                        break;
                    }

                    typeIndex = baseType.baseOrElementTypeIndex;
                }
            }

            if (nestedStructsIgnored > 0)
            {
                m_Snapshot.Warning("HeapExplorer: {0} nested structs ignored (Workaround for Unity bug Case 1104590).", nestedStructsIgnored);
            }
        }