private void ParseObjectHeader(StartIndices startIndices, MemorySection[] heap, ulong originalHeapAddress, out ulong typeInfoAddress, out int indexOfObject, out bool wasAlreadyCrawled, List <PackedManagedObject> outManagedObjects) { BytesAndOffset bo = heap.Find(originalHeapAddress, _virtualMachineInformation); UInt64 pointer1 = bo.ReadPointer(); BytesAndOffset pointer2 = bo.NextPointer(); if (HasMarkBit(pointer1) == 0) { TypeDescription typeDescription = GetTypeDescription(heap, pointer1); wasAlreadyCrawled = false; indexOfObject = outManagedObjects.Count + startIndices.OfFirstManagedObject; typeInfoAddress = typeDescription.typeInfoAddress; int size = SizeOfObjectInBytes(typeDescription, bo, heap, originalHeapAddress); outManagedObjects.Add(new PackedManagedObject() { address = originalHeapAddress, size = size, typeIndex = typeDescription.typeIndex }); //okay, we gathered all information, now lets set the mark bit, and store the index for this object in the 2nd pointer of the header, which is rarely used. bo.WritePointer(pointer1 | 1); pointer2.WritePointer((ulong)indexOfObject); return; } //give typeinfo address back without the markbit typeInfoAddress = ClearMarkBit(pointer1); wasAlreadyCrawled = true; //read the index for this object that we stored in the 2ndpointer field of the header indexOfObject = (int)pointer2.ReadPointer(); }
private void CrawlPointerNonRecursive(PackedMemorySnapshot packedMemorySnapshot, StartIndices startIndices, ulong pointer, int indexOfFrom, List <Connection> out_connections, List <PackedManagedObject> out_managedObjects, Stack <ThingToProfile> out_thingsToProfile) { BytesAndOffset bo = packedMemorySnapshot.managedHeapSections.Find(pointer, _virtualMachineInformation); if (!bo.IsValid) { return; } UInt64 typeInfoAddress; int indexOfObject; bool wasAlreadyCrawled; try { ParseObjectHeader(startIndices, packedMemorySnapshot.managedHeapSections, pointer, out typeInfoAddress, out indexOfObject, out wasAlreadyCrawled, out_managedObjects); } catch (Exception e) { UnityEngine.Debug.LogWarningFormat("Exception parsing object header. Skipping. {0}", e); return; } out_connections.Add(new Connection() { from = indexOfFrom, to = indexOfObject }); if (wasAlreadyCrawled) { return; } TypeDescription typeDescription = _typeInfoToTypeDescription[typeInfoAddress]; if (!typeDescription.isArray) { out_thingsToProfile.Push(new ThingToProfile(typeDescription, bo.Add(_virtualMachineInformation.objectHeaderSize), false, indexOfObject)); return; } int arrayLength = ArrayTools.ReadArrayLength(packedMemorySnapshot.managedHeapSections, pointer, typeDescription, _virtualMachineInformation); TypeDescription elementType = packedMemorySnapshot.typeDescriptions[typeDescription.baseOrElementTypeIndex]; BytesAndOffset cursor = bo.Add(_virtualMachineInformation.arrayHeaderSize); for (int i = 0; i != arrayLength; i++) { if (elementType.isValueType) { out_thingsToProfile.Push(new ThingToProfile(elementType, cursor, false, indexOfObject)); cursor = cursor.Add(elementType.size); } else { out_thingsToProfile.Push(new ThingToProfile(cursor.ReadPointer(), indexOfObject)); cursor = cursor.NextPointer(); } } }
private TypeDescription RestoreObjectHeader(MemorySection[] heaps, ulong address, int managedObjectIndex) { BytesAndOffset bo = heaps.Find(address, _virtualMachineInformation); UInt64 mask = this._virtualMachineInformation.pointerSize == 8 ? System.UInt64.MaxValue - 1 : System.UInt32.MaxValue - 1; UInt64 pointer = bo.ReadPointer(); UInt64 typeInfoAddress = pointer & mask; bo.WritePointer(typeInfoAddress); UInt64 restoreValue = 0; _pointer2Backups.TryGetValue(managedObjectIndex, out restoreValue); bo.NextPointer().WritePointer(restoreValue); return(GetTypeDescription(heaps, typeInfoAddress)); }