public PackedCrawlerData Crawl(PackedMemorySnapshot input) { _typeInfoToTypeDescription = input.typeDescriptions.ToDictionary(td => td.typeInfoAddress, td => td); _virtualMachineInformation = input.virtualMachineInformation; _typeDescriptions = input.typeDescriptions; _instanceFields = new FieldDescription[_typeDescriptions.Length][]; _staticFields = new FieldDescription[_typeDescriptions.Length][]; foreach (var type in _typeDescriptions) { _instanceFields[type.typeIndex] = TypeTools.AllFieldsOf(type, _typeDescriptions, TypeTools.FieldFindOptions.OnlyInstance).ToArray(); _staticFields[type.typeIndex] = TypeTools.AllFieldsOf(type, _typeDescriptions, TypeTools.FieldFindOptions.OnlyStatic).ToArray(); } var result = new PackedCrawlerData(input); var managedObjects = new List <PackedManagedObject>(result.startIndices.OfFirstManagedObject * 3); var connections = new List <Connection>(managedObjects.Capacity * 3); //we will be adding a lot of connections, but the input format also already had connections. (nativeobject->nativeobject and nativeobject->gchandle). we'll add ours to the ones already there. connections.AddRange(input.connections); Stack <ThingToProfile> thingsToProfile = new Stack <ThingToProfile>(); for (int i = 0; i < input.gcHandles.Length; ++i) { thingsToProfile.Push(new ThingToProfile(input.gcHandles[i].target, result.startIndices.OfFirstGCHandle + i)); } for (int i = 0; i < result.typesWithStaticFields.Length; i++) { var typeDescription = result.typesWithStaticFields[i]; thingsToProfile.Push(new ThingToProfile(typeDescription, new BytesAndOffset { bytes = typeDescription.staticFieldBytes, offset = 0, pointerSize = _virtualMachineInformation.pointerSize }, true, result.startIndices.OfFirstStaticFields + i)); } while (thingsToProfile.Count > 0) { var thingToProfile = thingsToProfile.Pop(); if (thingToProfile.type == PointerType.Reference) { CrawlPointerNonRecursive(input, result.startIndices, thingToProfile.object_offset, thingToProfile.indexOfFrom, connections, managedObjects, thingsToProfile); } else { CrawlRawObjectDataNonRecursive(input, result.startIndices, thingToProfile.bytesAndOffset, thingToProfile.typeDescription, thingToProfile.useStaticFields, thingToProfile.indexOfFrom, connections, managedObjects, thingsToProfile); } } result.managedObjects = managedObjects.ToArray(); connections.AddRange(AddManagedToNativeConnectionsAndRestoreObjectHeaders(input, result.startIndices, result)); result.connections = connections.ToArray(); return(result); }
private string DumpFields(TypeDescription typeDescription, BytesAndOffset bytesAndOffset, bool useStatics = false) { var str = new StringBuilder(); foreach (var field in TypeTools.AllFieldsOf(typeDescription, _unpackedCrawl.typeDescriptions, useStatics ? TypeTools.FieldFindOptions.OnlyStatic : TypeTools.FieldFindOptions.OnlyInstance)) { str.AppendFormat("\t\t\t{0}\n", field.name); // str.Append(DumpValueFor(field, bytesAndOffset.Add(field.offset))); } return(str.ToString()); }
private void CrawlRawObjectData(PackedMemorySnapshot packedMemorySnapshot, StartIndices startIndices, BytesAndOffset bytesAndOffset, TypeDescription typeDescription, bool useStaticFields, int indexOfFrom, List <Connection> out_connections, List <PackedManagedObject> out_managedObjects) { foreach (var field in TypeTools.AllFieldsOf(typeDescription, _typeDescriptions, useStaticFields ? TypeTools.FieldFindOptions.OnlyStatic : TypeTools.FieldFindOptions.OnlyInstance)) { if (field.typeIndex == typeDescription.typeIndex && typeDescription.isValueType) { //this happens in System.Single, which is a weird type that has a field of its own type. continue; } if (field.offset == -1) { //this is how we encode TLS fields. todo: actually treat TLS fields as roots continue; } var fieldType = packedMemorySnapshot.typeDescriptions[field.typeIndex]; var fieldLocation = bytesAndOffset.Add(field.offset - (useStaticFields ? 0 : _virtualMachineInformation.objectHeaderSize)); if (fieldType.isValueType) { CrawlRawObjectData(packedMemorySnapshot, startIndices, fieldLocation, fieldType, false, indexOfFrom, out_connections, out_managedObjects); continue; } //temporary workaround for a bug in 5.3b4 and earlier where we would get literals returned as fields with offset 0. soon we'll be able to remove this code. bool gotException = false; try { fieldLocation.ReadPointer(); } catch (ArgumentException) { UnityEngine.Debug.LogWarningFormat("Skipping field {0} on type {1}", field.name, typeDescription.name); UnityEngine.Debug.LogWarningFormat("FieldType.name: {0}", fieldType.name); gotException = true; } if (!gotException) { CrawlPointer(packedMemorySnapshot, startIndices, fieldLocation.ReadPointer(), indexOfFrom, out_connections, out_managedObjects); } } }
private void DrawFields(TypeDescription typeDescription, BytesAndOffset bytesAndOffset, bool useStatics = false) { int counter = 0; foreach (var field in TypeTools.AllFieldsOf(typeDescription, _unpackedCrawl.typeDescriptions, useStatics ? TypeTools.FieldFindOptions.OnlyStatic : TypeTools.FieldFindOptions.OnlyInstance)) { counter++; var gUIStyle = counter % 2 == 0 ? Styles.entryEven : Styles.entryOdd; gUIStyle.margin = new RectOffset(0, 0, 0, 0); gUIStyle.overflow = new RectOffset(0, 0, 0, 0); gUIStyle.padding = EditorStyles.label.padding; GUILayout.BeginHorizontal(gUIStyle); GUILayout.Label(field.name, labelWidth); GUILayout.BeginVertical(); DrawValueFor(field, bytesAndOffset.Add(field.offset)); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } }