Model: Eliminate stream reads and duplicate TypeInfos from GetTypeFromVirtualAddress
This commit is contained in:
@@ -49,9 +49,12 @@ namespace Il2CppInspector
|
|||||||
// List of constructed generic method function pointers corresponding to each possible method instantiation
|
// List of constructed generic method function pointers corresponding to each possible method instantiation
|
||||||
public Dictionary<Il2CppMethodSpec, ulong> GenericMethodPointers { get; } = new Dictionary<Il2CppMethodSpec, ulong>();
|
public Dictionary<Il2CppMethodSpec, ulong> GenericMethodPointers { get; } = new Dictionary<Il2CppMethodSpec, ulong>();
|
||||||
|
|
||||||
// Every defined type
|
// Every type reference (TypeRef) sorted by index
|
||||||
public List<Il2CppType> TypeReferences { get; private set; }
|
public List<Il2CppType> TypeReferences { get; private set; }
|
||||||
|
|
||||||
|
// Every type reference index sorted by virtual address
|
||||||
|
public Dictionary<ulong, int> TypeReferenceIndicesByAddress { get; private set; }
|
||||||
|
|
||||||
// From v24.2 onwards, this structure is stored for each module (image)
|
// From v24.2 onwards, this structure is stored for each module (image)
|
||||||
// One assembly may contain multiple modules
|
// One assembly may contain multiple modules
|
||||||
public Dictionary<string, Il2CppCodeGenModule> Modules { get; private set; }
|
public Dictionary<string, Il2CppCodeGenModule> Modules { get; private set; }
|
||||||
@@ -193,6 +196,8 @@ namespace Il2CppInspector
|
|||||||
FieldOffsetPointers = image.ReadMappedWordArray(MetadataRegistration.pfieldOffsets, (int)MetadataRegistration.fieldOffsetsCount);
|
FieldOffsetPointers = image.ReadMappedWordArray(MetadataRegistration.pfieldOffsets, (int)MetadataRegistration.fieldOffsetsCount);
|
||||||
|
|
||||||
// Type references (pointer array)
|
// Type references (pointer array)
|
||||||
|
var typeRefPointers = image.ReadMappedArray<ulong>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount);
|
||||||
|
TypeReferenceIndicesByAddress = typeRefPointers.Zip(Enumerable.Range(0, typeRefPointers.Length), (a, i) => new { a, i }).ToDictionary(x => x.a, x => x.i);
|
||||||
TypeReferences = image.ReadMappedObjectPointerArray<Il2CppType>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount);
|
TypeReferences = image.ReadMappedObjectPointerArray<Il2CppType>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount);
|
||||||
|
|
||||||
// Custom attribute constructors (function pointers)
|
// Custom attribute constructors (function pointers)
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ namespace Il2CppInspector
|
|||||||
public Dictionary<int, (ulong, object)> ParameterDefaultValue { get; } = new Dictionary<int, (ulong, object)>();
|
public Dictionary<int, (ulong, object)> ParameterDefaultValue { get; } = new Dictionary<int, (ulong, object)>();
|
||||||
public List<long> FieldOffsets { get; }
|
public List<long> FieldOffsets { get; }
|
||||||
public List<Il2CppType> TypeReferences => Binary.TypeReferences;
|
public List<Il2CppType> TypeReferences => Binary.TypeReferences;
|
||||||
|
public Dictionary<ulong, int> TypeReferenceIndicesByAddress => Binary.TypeReferenceIndicesByAddress;
|
||||||
public List<Il2CppGenericInst> GenericInstances => Binary.GenericInstances;
|
public List<Il2CppGenericInst> GenericInstances => Binary.GenericInstances;
|
||||||
public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules;
|
public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules;
|
||||||
public ulong[] CustomAttributeGenerators => Binary.CustomAttributeGenerators;
|
public ulong[] CustomAttributeGenerators => Binary.CustomAttributeGenerators;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Il2CppInspector.Reflection
|
namespace Il2CppInspector.Reflection
|
||||||
{
|
{
|
||||||
@@ -32,12 +31,8 @@ namespace Il2CppInspector.Reflection
|
|||||||
// List of all type definitions by fully qualified name (TypeDefs only)
|
// List of all type definitions by fully qualified name (TypeDefs only)
|
||||||
public Dictionary<string, TypeInfo> TypesByFullName { get; } = new Dictionary<string, TypeInfo>();
|
public Dictionary<string, TypeInfo> TypesByFullName { get; } = new Dictionary<string, TypeInfo>();
|
||||||
|
|
||||||
// List of type references that are initialized via pointers in the image
|
|
||||||
public ConcurrentDictionary<ulong, TypeInfo> TypesByVirtualAddress { get; } = new ConcurrentDictionary<ulong, TypeInfo>();
|
|
||||||
|
|
||||||
// Every type
|
// Every type
|
||||||
public IEnumerable<TypeInfo> Types => new IEnumerable<TypeInfo>[]
|
public IEnumerable<TypeInfo> Types => new IEnumerable<TypeInfo>[] {TypesByDefinitionIndex, TypesByReferenceIndex, TypesByMethodSpecClassIndex.Values}
|
||||||
{TypesByDefinitionIndex, TypesByReferenceIndex, TypesByMethodSpecClassIndex.Values, TypesByVirtualAddress.Values}
|
|
||||||
.SelectMany(t => t).Distinct();
|
.SelectMany(t => t).Distinct();
|
||||||
|
|
||||||
// List of all methods ordered by their MethodDefinitionIndex
|
// List of all methods ordered by their MethodDefinitionIndex
|
||||||
@@ -103,7 +98,7 @@ namespace Il2CppInspector.Reflection
|
|||||||
|
|
||||||
// Get list of pointers to type parameters (both unresolved and concrete)
|
// Get list of pointers to type parameters (both unresolved and concrete)
|
||||||
var genericTypeArguments = Package.BinaryImage.ReadMappedWordArray(inst.type_argv, (int)inst.type_argc);
|
var genericTypeArguments = Package.BinaryImage.ReadMappedWordArray(inst.type_argv, (int)inst.type_argc);
|
||||||
|
|
||||||
return genericTypeArguments.Select(a => GetTypeFromVirtualAddress((ulong) a)).ToList();
|
return genericTypeArguments.Select(a => GetTypeFromVirtualAddress((ulong) a)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,17 +144,18 @@ namespace Il2CppInspector.Reflection
|
|||||||
return TypesByFullName[fqn];
|
return TypesByFullName[fqn];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type from a virtual address pointer
|
// Get a TypeRef by its virtual address
|
||||||
// These are always nested types from references within another TypeRef
|
// These are always nested types from references within another TypeRef
|
||||||
// TODO: Eliminate GetTypeFromVirtualAddress() - use base and offset from MetadataRegistration.ptypes (Package.TypeReferences) instead
|
|
||||||
public TypeInfo GetTypeFromVirtualAddress(ulong ptr) {
|
public TypeInfo GetTypeFromVirtualAddress(ulong ptr) {
|
||||||
if (TypesByVirtualAddress.ContainsKey(ptr))
|
var typeRefIndex = Package.TypeReferenceIndicesByAddress[ptr];
|
||||||
return TypesByVirtualAddress[ptr];
|
|
||||||
|
|
||||||
var type = Package.BinaryImage.ReadMappedObject<Il2CppType>(ptr);
|
if (TypesByReferenceIndex[typeRefIndex] != null)
|
||||||
|
return TypesByReferenceIndex[typeRefIndex];
|
||||||
|
|
||||||
|
var type = Package.TypeReferences[typeRefIndex];
|
||||||
var referencedType = resolveTypeReference(type);
|
var referencedType = resolveTypeReference(type);
|
||||||
|
|
||||||
TypesByVirtualAddress.TryAdd(ptr, referencedType);
|
TypesByReferenceIndex[typeRefIndex] = referencedType;
|
||||||
return referencedType;
|
return referencedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,10 +103,8 @@ namespace Il2CppInspector.Reflection
|
|||||||
Position = generic.Position;
|
Position = generic.Position;
|
||||||
Attributes = generic.Attributes;
|
Attributes = generic.Attributes;
|
||||||
|
|
||||||
// TODO: Duplicate instances of 'concrete' may cause this search to fail. Replace with a straight lookup after eliminating GetTypeFromVirtualAddress
|
// Search for the concrete type's TypeRef index to store as the parameter type reference index
|
||||||
//paramTypeReference = Array.IndexOf(model.TypesByReferenceIndex, concrete);
|
paramTypeReference = Array.IndexOf(model.TypesByReferenceIndex, concrete);
|
||||||
// TODO: Get rid of this slow and filthy hack to force finding the correct type reference
|
|
||||||
paramTypeReference = model.TypesByReferenceIndex.Select((v, i) => new {i, v}).First(t => t.v.ToString() == concrete.ToString()).i;
|
|
||||||
|
|
||||||
DefaultValue = generic.DefaultValue;
|
DefaultValue = generic.DefaultValue;
|
||||||
DefaultValueMetadataAddress = generic.DefaultValueMetadataAddress;
|
DefaultValueMetadataAddress = generic.DefaultValueMetadataAddress;
|
||||||
|
|||||||
@@ -580,6 +580,8 @@ namespace Il2CppInspector.Reflection {
|
|||||||
|
|
||||||
// Open and closed generic types
|
// Open and closed generic types
|
||||||
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST) {
|
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST) {
|
||||||
|
|
||||||
|
// TODO: Replace with array load from Il2CppMetadataRegistration.genericClasses
|
||||||
var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.datapoint); // Il2CppGenericClass *
|
var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.datapoint); // Il2CppGenericClass *
|
||||||
|
|
||||||
// We have seen one test case where the TypeRef can point to no generic instance
|
// We have seen one test case where the TypeRef can point to no generic instance
|
||||||
@@ -608,6 +610,7 @@ namespace Il2CppInspector.Reflection {
|
|||||||
IsGenericParameter = false;
|
IsGenericParameter = false;
|
||||||
|
|
||||||
// Get the instantiation
|
// Get the instantiation
|
||||||
|
// TODO: Replace with array load from Il2CppMetadataRegistration.genericInsts
|
||||||
var genericInstance = image.ReadMappedObject<Il2CppGenericInst>(generic.context.class_inst);
|
var genericInstance = image.ReadMappedObject<Il2CppGenericInst>(generic.context.class_inst);
|
||||||
|
|
||||||
if (generic.context.method_inst != 0)
|
if (generic.context.method_inst != 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user