Пример #1
0
        // address = object address (start of header)
        System.ArraySegment <byte> ReadObjectBytes(System.UInt64 address, PackedManagedType typeDescription)
        {
            var size = ReadObjectSize(address, typeDescription);

            if (size <= 0)
            {
                return(new System.ArraySegment <byte>());
            }

            var offset = TryBeginRead(address);

            if (offset < 0)
            {
                return(new System.ArraySegment <byte>());
            }

            // Unity bug? For a reason that I do not understand, sometimes a memory segment is smaller
            // than the actual size of an object. In order to workaround this issue, we make sure to never
            // try to read more data from the segment than is available.
            if ((m_Bytes.Length - offset) < size)
            {
                //var wantedLength = size;
                size = m_Bytes.Length - offset;
                //Debug.LogErrorFormat("Cannot read entire string 0x{0:X}. The requested length in bytes is {1}, but the memory segment holds {2} bytes only.\n{3}...", address, wantedLength, size, System.Text.Encoding.Unicode.GetString(m_bytes, offset, Mathf.Min(size, 32)));
                if (size <= 0)
                {
                    return(new System.ArraySegment <byte>());
                }
            }

            var segment = new System.ArraySegment <byte>(m_Bytes, offset, size);

            return(segment);
        }
        public static bool HasTypeOrBaseAnyStaticField(PackedMemorySnapshot snapshot, PackedManagedType type, out PackedManagedType fieldType)
        {
            fieldType = new PackedManagedType();
            fieldType.managedTypesArrayIndex = -1;
            fieldType.nativeTypeArrayIndex   = -1;
            fieldType.baseOrElementTypeIndex = -1;

            var loopguard = 0;

            do
            {
                if (++loopguard > 64)
                {
                    Debug.LogError("loopguard kicked in");
                    break;
                }

                if (type.staticFields.Length > 0)
                {
                    fieldType = snapshot.managedTypes[type.staticFields[0].managedTypesArrayIndex];
                    return(true);
                }

                if (type.baseOrElementTypeIndex != -1)
                {
                    type = snapshot.managedTypes[type.baseOrElementTypeIndex];
                }
            } while (type.baseOrElementTypeIndex != -1 && type.managedTypesArrayIndex != type.baseOrElementTypeIndex);

            return(false);
        }
Пример #3
0
        /// <summary>
        /// Computes a checksum of the managed object specified at 'address'.
        /// This is used to find object duplicates.
        /// </summary>
        public UnityEngine.Hash128 ComputeObjectHash(System.UInt64 address, PackedManagedType type)
        {
            if (m_Hasher == null)
            {
                m_Hasher = System.Security.Cryptography.MD5.Create();
            }

            var content = ReadObjectBytes(address, type);

            if (content.Count == 0)
            {
                return(new Hash128());
            }

            var bytes = m_Hasher.ComputeHash(content.Array, content.Offset, content.Count);

            if (bytes.Length != 16)
            {
                return(new Hash128());
            }

            var v0 = (uint)(bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24);
            var v1 = (uint)(bytes[4] << 32 | bytes[5] << 40 | bytes[6] << 48 | bytes[7] << 56);
            var v2 = (uint)(bytes[8] | bytes[9] << 8 | bytes[10] << 16 | bytes[11] << 24);
            var v3 = (uint)(bytes[12] << 32 | bytes[13] << 40 | bytes[14] << 48 | bytes[15] << 56);

            return(new Hash128(v0, v1, v2, v3));
        }
        /// <summary>
        /// Gets whether any type in its inheritance chain has an instance field.
        /// </summary>
        public static bool HasTypeOrBaseAnyField(PackedMemorySnapshot snapshot, PackedManagedType type, bool checkInstance, bool checkStatic)
        {
            var loopguard = 0;

            do
            {
                if (++loopguard > 64)
                {
                    Debug.LogError("loopguard kicked in");
                    break;
                }

                if (checkInstance && type.instanceFields.Length > 0)
                {
                    return(true);
                }

                if (checkStatic && type.staticFields.Length > 0)
                {
                    return(true);
                }

                if (type.baseOrElementTypeIndex != -1)
                {
                    type = snapshot.managedTypes[type.baseOrElementTypeIndex];
                }
            } while (type.baseOrElementTypeIndex != -1 && type.managedTypesArrayIndex != type.baseOrElementTypeIndex);

            return(false);
        }
        public static                            PackedManagedType[] FromMemoryProfiler(UnityEditor.MemoryProfiler.TypeDescription[] source)
        {
            var value = new PackedManagedType[source.Length];

            for (int n = 0, nend = source.Length; n < nend; ++n)
            {
                value[n] = new PackedManagedType
                {
                    isValueType            = source[n].isValueType,
                    isArray                = source[n].isArray,
                    arrayRank              = source[n].arrayRank,
                    name                   = source[n].name,
                    assembly               = source[n].assembly,
                    fields                 = PackedManagedField.FromMemoryProfiler(source[n].fields),
                    staticFieldBytes       = source[n].staticFieldBytes,
                    baseOrElementTypeIndex = source[n].baseOrElementTypeIndex,
                    size                   = source[n].size,
                    typeInfoAddress        = source[n].typeInfoAddress,
                    managedTypesArrayIndex = source[n].typeIndex,

                    nativeTypeArrayIndex = -1,
                };

                // namespace-less types have a preceding dot, which we remove here
                if (value[n].name != null && value[n].name.Length > 0 && value[n].name[0] == '.')
                {
                    value[n].name = value[n].name.Substring(1);
                }
            }
            return(value);
        }
        public bool IsSubclassOf(PackedManagedType type, int baseTypeIndex)
        {
            if (type.managedTypesArrayIndex == baseTypeIndex)
            {
                return(true);
            }

            if (type.managedTypesArrayIndex < 0 || baseTypeIndex < 0)
            {
                return(false);
            }

            var guard = 0;

            while (type.baseOrElementTypeIndex != -1)
            {
                // safety code in case of an infite loop
                if (++guard > 64)
                {
                    return(false);
                }

                if (type.managedTypesArrayIndex == baseTypeIndex)
                {
                    return(true);
                }

                // get type of the base class
                type = managedTypes[type.baseOrElementTypeIndex];
            }

            return(false);
        }
Пример #7
0
        /// <summary>
        /// Loads a memory snapshot from the specified 'filePath' and stores the result in 'snapshot'.
        /// </summary>
        /// <param name="filePath">Absolute file path</param>
        public bool LoadFromFile(string filePath)
        {
            busyString = "Loading";

            using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open))
            {
                using (var reader = new System.IO.BinaryReader(fileStream))
                {
                    try
                    {
                        PackedMemorySnapshotHeader.Read(reader, out header, out busyString);
                        if (!header.isValid)
                        {
                            throw new Exception("Invalid header.");
                        }

                        PackedNativeType.Read(reader, out nativeTypes, out busyString);
                        PackedNativeUnityEngineObject.Read(reader, out nativeObjects, out busyString);
                        PackedGCHandle.Read(reader, out gcHandles, out busyString);
                        PackedConnection.Read(reader, out connections, out busyString);
                        PackedMemorySection.Read(reader, out managedHeapSections, out busyString);
                        PackedManagedType.Read(reader, out managedTypes, out busyString);
                        PackedVirtualMachineInformation.Read(reader, out virtualMachineInformation, out busyString);
                    }
                    catch (System.Exception e)
                    {
                        Debug.LogException(e);
                        return(false);
                    }
                }
            }

            return(true);
        }
Пример #8
0
        /// <summary>
        /// Gets whether this native type is a subclass of the specified type 't'.
        /// </summary>
        public bool IsSubclassOf(PackedManagedType t)
        {
            if (!isValid || t.managedTypesArrayIndex == -1)
            {
                return(false);
            }

            var me = m_Snapshot.managedTypes[m_ManagedTypesArrayIndex];

            if (me.managedTypesArrayIndex == t.managedTypesArrayIndex)
            {
                return(true);
            }

            var guard = 0;

            while (me.baseOrElementTypeIndex != -1)
            {
                if (++guard > 64)
                {
                    break; // no inheritance should have more depths than this
                }
                if (me.baseOrElementTypeIndex == t.managedTypesArrayIndex)
                {
                    return(true);
                }

                me = m_Snapshot.managedTypes[me.baseOrElementTypeIndex];
            }

            return(false);
        }
 void SetObjectSize(ref PackedManagedObject managedObj, PackedManagedType type)
 {
     if (managedObj.size > 0)
     {
         return; // size is set already
     }
     managedObj.size = m_MemoryReader.ReadObjectSize(managedObj.address, type);
 }
Пример #10
0
        public static void ManagedTypeIcon(Rect position, PackedManagedType type)
        {
            var isValueType = type.isValueType;
            var icon        = isValueType ? HeEditorStyles.csValueTypeImage : HeEditorStyles.csReferenceTypeImage;
            var content     = new GUIContent(icon, isValueType ? "ValueType" : "ReferenceType");

            GUI.Box(HeEditorGUI.SpaceL(ref position, position.height), content, HeEditorStyles.iconStyle);
        }
Пример #11
0
        public void Initialize(PackedMemorySnapshot snapshot, AbstractMemoryReader memoryReader, System.UInt64 address, PackedManagedType type)
        {
            m_Snapshot     = snapshot;
            m_Address      = address;
            m_Type         = type;
            m_MemoryReader = memoryReader;
            m_Title        = string.Format("{0} Visualizer", type.name);

            OnInitialize();
        }
Пример #12
0
        /// <summary>
        /// Converts an Unity PackedMemorySnapshot to our own format.
        /// </summary>
        public static PackedMemorySnapshot FromMemoryProfiler(MemorySnapshotProcessingArgs args)
        {
            var source = args.source;

            var value = new PackedMemorySnapshot();

            try
            {
                VerifyMemoryProfilerSnapshot(source);

                value.busyString = "Loading Header";
                value.header     = PackedMemorySnapshotHeader.FromMemoryProfiler();

                value.busyString  = string.Format("Loading {0} Native Types", source.nativeTypes.Length);
                value.nativeTypes = PackedNativeType.FromMemoryProfiler(source.nativeTypes);

                value.busyString    = string.Format("Loading {0} Native Objects", source.nativeObjects.Length);
                value.nativeObjects = PackedNativeUnityEngineObject.FromMemoryProfiler(source.nativeObjects);

                value.busyString = string.Format("Loading {0} GC Handles", source.gcHandles.Length);
                value.gcHandles  = PackedGCHandle.FromMemoryProfiler(source.gcHandles);

                value.busyString = string.Format("Loading {0} Object Connections", source.connections.Length);
                if (args.excludeNativeFromConnections)
                {
                    value.connections = ConnectionsFromMemoryProfilerWithoutNativeHACK(value, source);
                }
                else
                {
                    value.connections = PackedConnection.FromMemoryProfiler(source.connections);
                }

                value.busyString          = string.Format("Loading {0} Managed Heap Sections", source.managedHeapSections.Length);
                value.managedHeapSections = PackedMemorySection.FromMemoryProfiler(source.managedHeapSections);

                value.busyString   = string.Format("Loading {0} Managed Types", source.typeDescriptions.Length);
                value.managedTypes = PackedManagedType.FromMemoryProfiler(source.typeDescriptions);

                value.busyString = "Loading VM Information";
                value.virtualMachineInformation = PackedVirtualMachineInformation.FromMemoryProfiler(source.virtualMachineInformation);
            }
            catch (System.Exception e)
            {
                Debug.LogException(e);
                value = null;
                throw;
            }
            return(value);
        }
        public void FindManagedStaticFieldsOfType(PackedManagedType type, List <int> target)
        {
            if (target == null)
            {
                return;
            }

            for (int n = 0, nend = managedStaticFields.Length; n < nend; ++n)
            {
                if (managedStaticFields[n].managedTypesArrayIndex == type.managedTypesArrayIndex)
                {
                    target.Add(managedStaticFields[n].staticFieldsArrayIndex);
                }
            }
        }
Пример #14
0
        void TryCreateDataVisualizer(AbstractMemoryReader reader, PackedManagedType type, ulong address, bool resolveAddress)
        {
            m_DataVisualizer          = null;
            m_DataVisualizerScrollPos = new Vector2();

            //if (AbstractDataVisualizer.HasVisualizer(type.name))
            {
                if (type.isPointer && resolveAddress)
                {
                    address = reader.ReadPointer(address);
                }

                m_DataVisualizer = AbstractDataVisualizer.CreateVisualizer(type.name);
                m_DataVisualizer.Initialize(m_Snapshot, reader, address, type);
            }
        }
Пример #15
0
        public static GUIContent GetTypeContent(PackedMemorySnapshot snapshot, PackedManagedType type)
        {
            const string valueTypeLabel     = "Value types are either stack-allocated or allocated inline in a structure.";
            const string referenceTypeLabel = "Reference types are heap-allocated.";

            if (type.isValueType)
            {
                if (snapshot.IsSubclassOf(type, snapshot.coreTypes.systemEnum))
                {
                    return(new GUIContent(csEnumTypeImage, valueTypeLabel));
                }

                return(new GUIContent(csValueTypeImage, valueTypeLabel));
            }

            return(new GUIContent(csReferenceTypeImage, referenceTypeLabel));
        }
Пример #16
0
 /// <summary>
 /// Saves the specfified memory snapshot as a file, using the specified 'filePath'.
 /// </summary>
 public void SaveToFile(string filePath)
 {
     using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.OpenOrCreate))
     {
         using (var writer = new System.IO.BinaryWriter(fileStream))
         {
             PackedMemorySnapshotHeader.Write(writer, header);
             PackedNativeType.Write(writer, nativeTypes);
             PackedNativeUnityEngineObject.Write(writer, nativeObjects);
             PackedGCHandle.Write(writer, gcHandles);
             PackedConnection.Write(writer, connections);
             PackedMemorySection.Write(writer, managedHeapSections);
             PackedManagedType.Write(writer, managedTypes);
             PackedVirtualMachineInformation.Write(writer, virtualMachineInformation);
         }
     }
 }
        public bool IsEnum(PackedManagedType type)
        {
            if (!type.isValueType)
            {
                return(false);
            }

            if (type.baseOrElementTypeIndex == -1)
            {
                return(false);
            }

            if (type.baseOrElementTypeIndex != coreTypes.systemEnum)
            {
                return(false);
            }

            return(true);
        }
Пример #18
0
        public int ReadArrayLength(System.UInt64 address, PackedManagedType arrayType)
        {
            var vm = m_Snapshot.virtualMachineInformation;

            var bounds = ReadPointer(address + (ulong)vm.arrayBoundsOffsetInHeader);

            if (bounds == 0)
            {
                return((int)ReadPointer(address + (ulong)vm.arraySizeOffsetInHeader));
            }

            int length = 1;

            for (int i = 0; i != arrayType.arrayRank; i++)
            {
                var ptr = bounds + (ulong)(i * vm.pointerSize);
                length *= (int)ReadPointer(ptr);
            }
            return(length);
        }
        public static void Read(System.IO.BinaryReader reader, out PackedManagedType[] value, out string stateString)
        {
            value       = new PackedManagedType[0];
            stateString = "";

            var version = reader.ReadInt32();

            if (version >= 1)
            {
                var length = reader.ReadInt32();
                stateString = string.Format("Loading {0} Managed Types", length);
                value       = new PackedManagedType[length];

                for (int n = 0, nend = value.Length; n < nend; ++n)
                {
                    value[n].isValueType = reader.ReadBoolean();
                    value[n].isArray     = reader.ReadBoolean();
                    value[n].arrayRank   = reader.ReadInt32();
                    value[n].name        = reader.ReadString();
                    value[n].assembly    = reader.ReadString();

                    var count = reader.ReadInt32();
                    value[n].staticFieldBytes       = reader.ReadBytes(count);
                    value[n].baseOrElementTypeIndex = reader.ReadInt32();
                    value[n].size                   = reader.ReadInt32();
                    value[n].typeInfoAddress        = reader.ReadUInt64();
                    value[n].managedTypesArrayIndex = reader.ReadInt32();

                    PackedManagedField.Read(reader, out value[n].fields);

                    // Types without namespace have a preceding period, which we remove here
                    // https://issuetracker.unity3d.com/issues/packedmemorysnapshot-leading-period-symbol-in-typename
                    if (value[n].name != null && value[n].name.Length > 0 && value[n].name[0] == '.')
                    {
                        value[n].name = value[n].name.Substring(1);
                    }

                    value[n].nativeTypeArrayIndex = -1;
                }
            }
        }
Пример #20
0
        public int ReadObjectSize(System.UInt64 address, PackedManagedType typeDescription)
        {
            // System.Array
            // Do not display its pointer-size, but the actual size of its content.
            if (typeDescription.isArray)
            {
                if (typeDescription.baseOrElementTypeIndex < 0 || typeDescription.baseOrElementTypeIndex >= m_Snapshot.managedTypes.Length)
                {
                    var details = "";
                    details = "arrayRank=" + typeDescription.arrayRank + ", " +
                              "isArray=" + typeDescription.isArray + ", " +
                              "typeInfoAddress=" + typeDescription.typeInfoAddress.ToString("X") + ", " +
                              "address=" + address.ToString("X") + ", " +
                              "memoryreader=" + GetType().Name + ", " +
                              "isValueType=" + typeDescription.isValueType;

                    Debug.LogErrorFormat("ERROR: '{0}.baseOrElementTypeIndex' = {1} is out of range, ignoring. Details in second line\n{2}", typeDescription.name, typeDescription.baseOrElementTypeIndex, details);
                    return(1);
                }

                var arrayLength = ReadArrayLength(address, typeDescription);
                var elementType = m_Snapshot.managedTypes[typeDescription.baseOrElementTypeIndex];
                var elementSize = elementType.isValueType ? elementType.size : m_Snapshot.virtualMachineInformation.pointerSize;

                var size = m_Snapshot.virtualMachineInformation.arrayHeaderSize;
                size += elementSize * arrayLength;
                return(size);
            }

            // System.String
            if (typeDescription.managedTypesArrayIndex == m_Snapshot.coreTypes.systemString)
            {
                var size = m_Snapshot.virtualMachineInformation.objectHeaderSize;
                size += sizeof(System.Int32); // string length
                size += ReadStringLength(address + (uint)m_Snapshot.virtualMachineInformation.objectHeaderSize) * sizeof(char);
                size += 2;                    // two null terminators aka \0\0
                return(size);
            }

            return(typeDescription.size);
        }
Пример #21
0
        public int ReadArrayLength(System.UInt64 address, PackedManagedType arrayType, int dimension)
        {
            if (dimension >= arrayType.arrayRank)
            {
                return(0);
            }

            var vm = m_Snapshot.virtualMachineInformation;

            var bounds = ReadPointer(address + (ulong)vm.arrayBoundsOffsetInHeader);

            if (bounds == 0)
            {
                return((int)ReadPointer(address + (ulong)vm.arraySizeOffsetInHeader));
            }

            var pointer = bounds + (ulong)(dimension * vm.pointerSize);
            var length  = (int)ReadPointer(pointer);

            return(length);
        }
        bool ContainsFieldOfReferenceType(PackedManagedType type)
        {
            var managedTypesLength = managedTypes.Length;
            var instanceFields     = type.instanceFields;

            for (int n = 0, nend = instanceFields.Length; n < nend; ++n)
            {
                var fieldTypeIndex = instanceFields[n].managedTypesArrayIndex;
                if (fieldTypeIndex < 0 || fieldTypeIndex >= managedTypesLength)
                {
                    Error("'{0}' field '{1}' is out of bounds '{2}', ignoring.", type.name, n, fieldTypeIndex);
                    continue;
                }

                var fieldType = managedTypes[instanceFields[n].managedTypesArrayIndex];
                if (!fieldType.isValueType)
                {
                    return(true);
                }
            }

            return(false);
        }
        bool ContainsFieldOfReferenceTypeInInheritenceChain(PackedManagedType type)
        {
            var loopGuard = 0;
            var typeIndex = type.managedTypesArrayIndex;

            while (typeIndex >= 0 && typeIndex < managedTypes.Length)
            {
                if (++loopGuard > 64)
                {
                    break;
                }

                type = managedTypes[typeIndex];
                if (ContainsFieldOfReferenceType(type))
                {
                    return(true);
                }

                typeIndex = type.baseOrElementTypeIndex;
            }

            return(false);
        }
Пример #24
0
        public void InspectStaticType(PackedMemorySnapshot snapshot, PackedManagedType managedType)
        {
            m_Snapshot = snapshot;
            var m_type    = managedType;
            var m_address = 0ul;

            var root = new TreeViewItem {
                id = 0, depth = -1, displayName = "Root"
            };

            if (m_Snapshot == null)
            {
                root.AddChild(new TreeViewItem {
                    id = 1, depth = -1, displayName = ""
                });
                return;
            }

            var args = new PropertyGridItem.BuildChildrenArgs();

            args.parent       = root;
            args.type         = m_type;
            args.address      = m_address;
            args.memoryReader = new StaticMemoryReader(snapshot, managedType.staticFieldBytes);

            AddType(args);

            // add at least one item to the tree, otherwise it outputs an error
            if (!root.hasChildren)
            {
                root.AddChild(new TreeViewItem(1, 0, ""));
            }

            SetTree(root);
            TryCreateDataVisualizer(args.memoryReader, args.type, args.address, false);
        }
Пример #25
0
        public static Texture2D GetTypeImage(PackedMemorySnapshot snapshot, PackedManagedType type)
        {
            if (type.isArray)
            {
                return(csReferenceTypeImage);
            }

            if (type.isValueType)
            {
                if (snapshot.IsSubclassOf(type, snapshot.coreTypes.systemEnum))
                {
                    return(csEnumTypeImage);
                }

                return(csValueTypeImage);
            }

            if (snapshot.IsSubclassOf(type, snapshot.coreTypes.systemDelegate))
            {
                return(csDelegateTypeImage);
            }

            return(csReferenceTypeImage);
        }
 public void Initialize(StaticFieldsControl owner, PackedMemorySnapshot snapshot, PackedManagedType typeDescription)
 {
     m_Owner           = owner;
     m_TypeDescription = typeDescription;
 }
 public void Initialize(PackedMemorySnapshot snapshot, PackedManagedType type)
 {
     m_Type = new RichManagedType(snapshot, type.managedTypesArrayIndex);
 }
Пример #28
0
        public static EditorWindow CreateWindow(PackedMemorySnapshot snapshot, AbstractMemoryReader memoryReader, System.UInt64 address, PackedManagedType type)
        {
            var visualizer = AbstractDataVisualizer.CreateVisualizer(type.name);

            if (visualizer == null)
            {
                Debug.LogWarningFormat("Could not create DataVisualizer for type '{0}'", type.name);
                return(null);
            }
            visualizer.Initialize(snapshot, memoryReader, address, type);

            var window = DataVisualizerWindow.CreateInstance <DataVisualizerWindow>();

            window.SetVisualizer(visualizer);
            window.ShowUtility();
            return(window);
        }
Пример #29
0
        void AddArrayElement(PackedManagedType elementType, int elementIndex, System.Action <BuildChildrenArgs> add)
        {
            if (elementType.isArray)
            {
                var pointer = m_MemoryReader.ReadPointer(address + (ulong)(elementIndex * m_Snapshot.virtualMachineInformation.pointerSize) + (ulong)m_Snapshot.virtualMachineInformation.arrayHeaderSize);
                var item    = new ArrayPropertyGridItem(m_Owner, m_Snapshot, pointer, m_MemoryReader)
                {
                    depth = this.depth + 1,
                    type  = elementType
                };
                item.OnInitialize();
                this.AddChild(item);
            }
            else if (elementType.isValueType)
            {
                if (elementType.isPrimitive)
                {
                    var args = new BuildChildrenArgs();
                    args.parent       = this;
                    args.type         = elementType;
                    args.address      = address + (ulong)(elementIndex * elementType.size) + (ulong)m_Snapshot.virtualMachineInformation.arrayHeaderSize - (ulong)m_Snapshot.virtualMachineInformation.objectHeaderSize;
                    args.memoryReader = new MemoryReader(m_Snapshot);
                    add(args);
                }
                else
                {
                    // this is the container node for the array elements.
                    // if we don't add the container, all fields are simply added to the array node itself.
                    // however, we want each array element being groupped
                    var pointer = address + (ulong)(elementIndex * elementType.size) + (ulong)m_Snapshot.virtualMachineInformation.arrayHeaderSize;

                    var item = new ArrayElementPropertyGridItem(m_Owner, m_Snapshot, pointer, new MemoryReader(m_Snapshot))
                    {
                        depth = this.depth + 1,
                        type  = elementType
                    };
                    item.Initialize();
                    this.AddChild(item);

                    pointer = address + (ulong)(elementIndex * elementType.size) + (ulong)m_Snapshot.virtualMachineInformation.arrayHeaderSize - (ulong)m_Snapshot.virtualMachineInformation.objectHeaderSize;

                    var args = new BuildChildrenArgs();
                    args.parent       = item;
                    args.type         = elementType;
                    args.address      = pointer;
                    args.memoryReader = new MemoryReader(m_Snapshot);
                    add(args);
                }
            }
            else
            {
                // address of element
                var addressOfElement = address + (ulong)(elementIndex * m_Snapshot.virtualMachineInformation.pointerSize) + (ulong)m_Snapshot.virtualMachineInformation.arrayHeaderSize;
                var pointer          = m_MemoryReader.ReadPointer(addressOfElement);
                if (pointer != 0)
                {
                    var i = m_Snapshot.FindManagedObjectTypeOfAddress(pointer);
                    if (i != -1)
                    {
                        elementType = m_Snapshot.managedTypes[i];
                    }
                }

                // this is the container node for the reference type.
                // if we don't add the container, all fields are simply added to the array node itself.
                // however, we want each array element being groupped
                var item = new ArrayElementPropertyGridItem(m_Owner, m_Snapshot, addressOfElement, m_MemoryReader)
                {
                    depth = this.depth + 1,
                    type  = elementType
                };
                item.Initialize();
                this.AddChild(item);

                // Only add the actual element fields if the pointer is valid
                if (pointer != 0)
                {
                    var args = new BuildChildrenArgs();
                    args.parent       = item;
                    args.type         = elementType;
                    args.address      = pointer;
                    args.memoryReader = new MemoryReader(m_Snapshot);
                    add(args);
                }
            }
        }
        public void Select(PackedManagedType managedType)
        {
            var item = FindItemByType(rootItem, managedType.managedTypesArrayIndex);

            SelectItem(item);
        }