public static int ReadStringObjectSizeInBytes(BytesAndOffset bo, VirtualMachineInformation virtualMachineInformation)
        {
            var lengthPointer = bo.Add(virtualMachineInformation.objectHeaderSize);
            var length        = lengthPointer.ReadInt32();

            return(virtualMachineInformation.objectHeaderSize + /*lengthfield*/ 1 + (length * /*utf16=2bytes per char*/ 2) + /*2 zero terminators*/ 2);
        }
            public BytesAndOffset Find(ulong address, VirtualMachineInformation virtualMachineInformation)
            {
                using (cacheFind.Auto())
                {
                    var bytesAndOffset = new BytesAndOffset();

                    if (address != 0 && address >= minAddress && address < maxAddress)
                    {
                        int idx = Array.BinarySearch(startAddress, address);
                        if (idx < 0)
                        {
                            idx = ~idx - 1;
                        }

                        if (address >= startAddress[idx] && address < (startAddress[idx] + (ulong)bytes[idx].Length))
                        {
                            bytesAndOffset.bytes       = bytes[idx];
                            bytesAndOffset.offset      = (int)(address - startAddress[idx]);
                            bytesAndOffset.pointerSize = virtualMachineInformation.pointerSize;
                        }
                    }

                    return(bytesAndOffset);
                }
            }
        public static int ReadArrayLength(CachedSnapshot data, BytesAndOffset arrayData, int iTypeDescriptionArrayType)
        {
            if (iTypeDescriptionArrayType < 0)
            {
                return(0);
            }

            var virtualMachineInformation = data.virtualMachineInformation;
            var heap   = data.managedHeapSections;
            var bo     = arrayData;
            var bounds = bo.Add(virtualMachineInformation.arrayBoundsOffsetInHeader).ReadPointer();

            if (bounds == 0)
            {
                return(bo.Add(virtualMachineInformation.arraySizeOffsetInHeader).ReadInt32());
            }

            var cursor = heap.Find(bounds, virtualMachineInformation);
            int length = 1;
            int rank   = data.typeDescriptions.GetRank(iTypeDescriptionArrayType);

            for (int i = 0; i != rank; i++)
            {
                length *= cursor.ReadInt32();
                cursor  = cursor.Add(8);
            }
            return(length);
        }
Exemple #4
0
        static void CrawlRawObjectData(IntermediateCrawlData crawlData, BytesAndOffset bytesAndOffset, int iTypeDescription, bool useStaticFields, ulong ptrFrom, int indexOfFrom)
        {
            var snapshot = crawlData.CachedMemorySnapshot;

            var fields = useStaticFields ? snapshot.typeDescriptions.fieldIndicesOwned_static[iTypeDescription] : snapshot.typeDescriptions.fieldIndices_instance[iTypeDescription];

            foreach (var iField in fields)
            {
                int iField_TypeDescription_TypeIndex  = snapshot.fieldDescriptions.typeIndex[iField];
                int iField_TypeDescription_ArrayIndex = snapshot.typeDescriptions.TypeIndex2ArrayIndex(iField_TypeDescription_TypeIndex);

                var fieldLocation = bytesAndOffset.Add(snapshot.fieldDescriptions.offset[iField] - (useStaticFields ? 0 : snapshot.virtualMachineInformation.objectHeaderSize));

                if (snapshot.typeDescriptions.HasFlag(iField_TypeDescription_ArrayIndex, TypeFlags.kValueType))
                {
                    CrawlRawObjectData(crawlData, fieldLocation, iField_TypeDescription_ArrayIndex, useStaticFields, ptrFrom, indexOfFrom);
                    continue;
                }


                ulong fieldAddr;
                if (fieldLocation.TryReadPointer(out fieldAddr) == BytesAndOffset.PtrReadError.Success)
                {
                    crawlData.CrawlDataStack.Push(new StackCrawlData()
                    {
                        ptr = fieldAddr, ptrFrom = ptrFrom, typeFrom = iTypeDescription, indexOfFrom = indexOfFrom, fieldFrom = iField, fromArrayIndex = -1
                    });
                }
            }
        }
        public static string ReadString(BytesAndOffset bo, VirtualMachineInformation virtualMachineInformation)
        {
            var lengthPointer = bo.Add(virtualMachineInformation.objectHeaderSize);
            var length        = lengthPointer.ReadInt32();
            var firstChar     = lengthPointer.Add(4);

            return(System.Text.Encoding.Unicode.GetString(firstChar.bytes, firstChar.offset, length * 2));
        }
Exemple #6
0
 private ObjectData(ObjectDataType t)
 {
     m_dataType = t;
     m_data     = new Data();
     m_data.managed.objectPtr = 0;
     managedObjectData        = new BytesAndOffset();
     m_data.managed.iType     = -1;
     m_Parent = null;
 }
Exemple #7
0
        public static ManagedObjectInfo ParseObjectHeader(CachedSnapshot snapshot, BytesAndOffset byteOffset, bool ignoreBadHeaderError)
        {
            var heap = snapshot.managedHeapSections;
            ManagedObjectInfo objectInfo;

            objectInfo                    = new ManagedObjectInfo();
            objectInfo.PtrObject          = 0;
            objectInfo.ManagedObjectIndex = -1;

            var   boHeader = byteOffset;
            ulong ptrIdentity;

            boHeader.TryReadPointer(out ptrIdentity);
            objectInfo.PtrTypeInfo      = ptrIdentity;
            objectInfo.ITypeDescription = snapshot.typeDescriptions.TypeInfo2ArrayIndex(objectInfo.PtrTypeInfo);
            bool error = false;

            if (objectInfo.ITypeDescription < 0)
            {
                var boIdentity = heap.Find(ptrIdentity, snapshot.virtualMachineInformation);
                if (boIdentity.IsValid)
                {
                    ulong ptrTypeInfo;
                    boIdentity.TryReadPointer(out ptrTypeInfo);
                    objectInfo.PtrTypeInfo      = ptrTypeInfo;
                    objectInfo.ITypeDescription = snapshot.typeDescriptions.TypeInfo2ArrayIndex(objectInfo.PtrTypeInfo);
                    error = objectInfo.ITypeDescription < 0;
                }
                else
                {
                    error = true;
                }
            }
            if (!error)
            {
                objectInfo.Size = SizeOfObjectInBytes(snapshot, objectInfo.ITypeDescription, boHeader, heap);
                objectInfo.data = boHeader;
            }
            else
            {
                if (!ignoreBadHeaderError)
                {
#if DEBUG_VALIDATION
                    UnityEngine.Debug.LogError("Bad object header at address: " + ptrIdentity);
#endif
                }

                objectInfo.PtrTypeInfo      = 0;
                objectInfo.ITypeDescription = -1;
                objectInfo.Size             = 0;
            }
            return(objectInfo);
        }
Exemple #8
0
        public static ArrayInfo GetArrayInfo(CachedSnapshot data, BytesAndOffset arrayData, int iTypeDescriptionArrayType)
        {
            var virtualMachineInformation = data.virtualMachineInformation;
            var arrayInfo = new ArrayInfo();

            arrayInfo.baseAddress          = 0;
            arrayInfo.arrayTypeDescription = iTypeDescriptionArrayType;


            arrayInfo.header = arrayData;
            arrayInfo.data   = arrayInfo.header.Add(virtualMachineInformation.arrayHeaderSize);
            ulong bounds;

            arrayInfo.header.Add(virtualMachineInformation.arrayBoundsOffsetInHeader).TryReadPointer(out bounds);

            if (bounds == 0)
            {
                arrayInfo.length = arrayInfo.header.Add(virtualMachineInformation.arraySizeOffsetInHeader).ReadInt32();
                arrayInfo.rank   = new int[1] {
                    arrayInfo.length
                };
            }
            else
            {
                var cursor = data.managedHeapSections.Find(bounds, virtualMachineInformation);
                int rank   = data.typeDescriptions.GetRank(iTypeDescriptionArrayType);
                arrayInfo.rank   = new int[rank];
                arrayInfo.length = 1;
                for (int i = 0; i != rank; i++)
                {
                    var l = cursor.ReadInt32();
                    arrayInfo.length *= l;
                    arrayInfo.rank[i] = l;
                    cursor            = cursor.Add(8);
                }
            }

            arrayInfo.elementTypeDescription = data.typeDescriptions.baseOrElementTypeIndex[iTypeDescriptionArrayType];
            if (arrayInfo.elementTypeDescription == -1) //We currently do not handle uninitialized types as such override the type, making it return pointer size
            {
                arrayInfo.elementTypeDescription = iTypeDescriptionArrayType;
            }
            if (data.typeDescriptions.HasFlag(arrayInfo.elementTypeDescription, TypeFlags.kValueType))
            {
                arrayInfo.elementSize = data.typeDescriptions.size[arrayInfo.elementTypeDescription];
            }
            else
            {
                arrayInfo.elementSize = virtualMachineInformation.pointerSize;
            }
            return(arrayInfo);
        }
        public static int ReadArrayObjectSizeInBytes(CachedSnapshot data, BytesAndOffset arrayData, int iTypeDescriptionArrayType)
        {
            var arrayLength = ReadArrayLength(data, arrayData, iTypeDescriptionArrayType);
            var virtualMachineInformation = data.virtualMachineInformation;

            var ti = data.typeDescriptions.baseOrElementTypeIndex[iTypeDescriptionArrayType];

            if (ti == -1) // check added as element type index can be -1 if we are dealing with a class member (eg: Dictionary.Entry) whose type is uninitialized due to their generic data not getting inflated a.k.a unused types
            {
                ti = iTypeDescriptionArrayType;
            }

            var ai          = data.typeDescriptions.TypeIndex2ArrayIndex(ti);
            var isValueType = data.typeDescriptions.HasFlag(ai, TypeFlags.kValueType);
            var elementSize = isValueType ? data.typeDescriptions.size[ai] : virtualMachineInformation.pointerSize;

            return(virtualMachineInformation.arrayHeaderSize + elementSize * arrayLength);
        }
        static void CrawlRawObjectData(IntermediateCrawlData crawlData, BytesAndOffset bytesAndOffset, int iTypeDescription, bool useStaticFields, ulong ptrFrom, int indexOfFrom)
        {
            var snapshot = crawlData.CachedMemorySnapshot;

            var fields = useStaticFields ? snapshot.typeDescriptions.fieldIndicesOwned_static[iTypeDescription] : snapshot.typeDescriptions.fieldIndices_instance[iTypeDescription];

            foreach (var iField in fields)
            {
                int iField_TypeDescription_TypeIndex  = snapshot.fieldDescriptions.typeIndex[iField];
                int iField_TypeDescription_ArrayIndex = snapshot.typeDescriptions.TypeIndex2ArrayIndex(iField_TypeDescription_TypeIndex);

                var fieldLocation = bytesAndOffset.Add(snapshot.fieldDescriptions.offset[iField] - (useStaticFields ? 0 : snapshot.virtualMachineInformation.objectHeaderSize));

                if (snapshot.typeDescriptions.HasFlag(iField_TypeDescription_ArrayIndex, TypeFlags.kValueType))
                {
                    CrawlRawObjectData(crawlData, fieldLocation, iField_TypeDescription_ArrayIndex, useStaticFields, ptrFrom, indexOfFrom);
                    continue;
                }

                //Workaround that was done to not error out when trying to read an array where the remaining length is less than that pointer size.
                bool gotException = false;
                try
                {
                    ulong ptr = fieldLocation.ReadPointer();
                    if (ptr == 0)
                    {
                        gotException = true;
                    }
                }
                catch (ArgumentException)
                {
                    gotException = true;
                }

                if (!gotException)
                {
                    crawlData.CrawlDataStack.Push(new StackCrawlData()
                    {
                        ptr = fieldLocation.ReadPointer(), ptrFrom = ptrFrom, typeFrom = iTypeDescription, indexOfFrom = indexOfFrom, fieldFrom = iField, fromArrayIndex = -1
                    });
                }
            }
        }
        static int SizeOfObjectInBytes(CachedSnapshot snapshot, int iTypeDescription, BytesAndOffset byteOffset, CachedSnapshot.ManagedMemorySectionEntriesCache heap)
        {
            if (iTypeDescription < 0)
            {
                return(0);
            }

            if (snapshot.typeDescriptions.HasFlag(iTypeDescription, TypeFlags.kArray))
            {
                return(ArrayTools.ReadArrayObjectSizeInBytes(snapshot, byteOffset, iTypeDescription));
            }

            if (snapshot.typeDescriptions.typeDescriptionName[iTypeDescription] == "System.String")
            {
                return(StringTools.ReadStringObjectSizeInBytes(byteOffset, snapshot.virtualMachineInformation));
            }

            //array and string are the only types that are special, all other types just have one size, which is stored in the type description
            return(snapshot.typeDescriptions.size[iTypeDescription]);
        }
        public static IEnumerator Crawl(CachedSnapshot snapshot)
        {
            const int stepCount = 5;
            var       status    = new EnumerationUtilities.EnumerationStatus(stepCount);

            IntermediateCrawlData crawlData = new IntermediateCrawlData(snapshot);

            crawlData.ManagedObjectInfos.Capacity = (int)snapshot.gcHandles.Count * 3;
            crawlData.ManagedConnections.Capacity = (int)snapshot.gcHandles.Count * 6;

            //Gather handles and duplicates
            status.StepStatus = "Gathering snapshot managed data.";
            yield return(status);

            GatherIntermediateCrawlData(snapshot, crawlData);

            //crawl handle data
            status.IncrementStep();
            status.StepStatus = "Crawling GC handles.";
            yield return(status);

            while (crawlData.CrawlDataStack.Count > 0)
            {
                CrawlPointer(crawlData);
            }

            //crawl data pertaining to types with static fields and enqueue any heap objects
            status.IncrementStep();
            status.StepStatus = "Crawling data types with static fields";
            yield return(status);

            for (int i = 0; i < crawlData.TypesWithStaticFields.Count; i++)
            {
                var iTypeDescription = crawlData.TypesWithStaticFields[i];
                var bytesOffset      = new BytesAndOffset {
                    bytes = snapshot.typeDescriptions.staticFieldBytes[iTypeDescription], offset = 0, pointerSize = snapshot.virtualMachineInformation.pointerSize
                };
                CrawlRawObjectData(crawlData, bytesOffset, iTypeDescription, true, 0, -1);
            }

            //crawl handles belonging to static instances
            status.IncrementStep();
            status.StepStatus = "Crawling static instances heap data.";
            yield return(status);

            while (crawlData.CrawlDataStack.Count > 0)
            {
                CrawlPointer(crawlData);
            }

            //copy crawled object source data for duplicate objects
            foreach (var i in crawlData.DuplicatedGCHandlesStack)
            {
                var ptr = snapshot.CrawledData.ManagedObjects[i].PtrObject;
                snapshot.CrawledData.ManagedObjects[i] = snapshot.CrawledData.ManagedObjectByAddress[ptr];
            }

            //crawl connection data
            status.IncrementStep();
            status.StepStatus = "Crawling connection data";
            yield return(status);

            ConnectNativeToManageObject(crawlData);
            AddupRawRefCount(crawlData.CachedMemorySnapshot);
        }
Exemple #13
0
        // Returns a new ObjectData pointing to the object's (that this ObjectData is currently pointing at) field
        // using a field index from snapshot.fieldDescriptions
        public ObjectData GetInstanceFieldBySnapshotFieldIndex(CachedSnapshot snapshot, int iField, bool expandToTarget)
        {
            ObjectData obj;
            ulong      objectPtr;

            switch (m_dataType)
            {
            case ObjectDataType.ReferenceObject:
                objectPtr = GetReferencePointer();
                obj       = FromManagedPointer(snapshot, objectPtr);
                break;

            case ObjectDataType.BoxedValue:
            case ObjectDataType.Object:
            case ObjectDataType.Value:
            case ObjectDataType.Type:
                objectPtr = m_data.managed.objectPtr;
                obj       = this;
                break;

            //case ObjectDataType.ReferenceArray:
            default:
                //TODO: add proper handling for missing types
                //DebugUtility.LogError("Requesting a field on an invalid data type");
                return(new ObjectData());
            }
            var  fieldOffset = snapshot.fieldDescriptions.offset[iField];
            var  fieldType   = snapshot.fieldDescriptions.typeIndex[iField];
            bool isStatic    = snapshot.fieldDescriptions.isStatic[iField];

            switch (m_dataType)
            {
            case ObjectDataType.Value:
                if (!isStatic)
                {
                    fieldOffset -= snapshot.virtualMachineInformation.objectHeaderSize;
                }
                break;

            case ObjectDataType.Object:
            case ObjectDataType.BoxedValue:
                break;

            case ObjectDataType.Type:
                if (!isStatic)
                {
                    Debug.LogError("Requesting a non-static field on a type");
                    return(invalid);
                }
                break;

            default:
                break;
            }

            ObjectData o = new ObjectData();

            o.m_Parent = new ObjectDataParent(obj, iField, -1, expandToTarget);
            o.SetManagedType(snapshot, fieldType);
            o.m_dataType = TypeToSubDataType(snapshot, fieldType);

            if (isStatic)
            {
                //the field requested might come from a base class. make sure we are using the right staticFieldBytes.
                var iOwningType = obj.m_data.managed.iType;
                while (iOwningType >= 0)
                {
                    var fieldIndex = System.Array.FindIndex(snapshot.typeDescriptions.fieldIndicesOwned_static[iOwningType], x => x == iField);
                    if (fieldIndex >= 0)
                    {
                        //field iField is owned by type iCurrentBase
                        break;
                    }
                    iOwningType = snapshot.typeDescriptions.baseOrElementTypeIndex[iOwningType];
                }
                if (iOwningType < 0)
                {
                    Debug.LogError("Field requested is not owned by the type not any of its bases");
                    return(invalid);
                }

                o.m_data.managed.objectPtr = 0;
                var typeStaticData = new BytesAndOffset(snapshot.typeDescriptions.staticFieldBytes[iOwningType], snapshot.virtualMachineInformation.pointerSize);
                o.managedObjectData = typeStaticData.Add(fieldOffset);
            }
            else
            {
                o.m_data.managed.objectPtr = objectPtr;// m_data.managed.objectPtr;
                o.managedObjectData        = obj.managedObjectData.Add(fieldOffset);
            }
            return(o);
        }