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
|
||||
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; }
|
||||
|
||||
// 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)
|
||||
// One assembly may contain multiple modules
|
||||
public Dictionary<string, Il2CppCodeGenModule> Modules { get; private set; }
|
||||
@@ -193,6 +196,8 @@ namespace Il2CppInspector
|
||||
FieldOffsetPointers = image.ReadMappedWordArray(MetadataRegistration.pfieldOffsets, (int)MetadataRegistration.fieldOffsetsCount);
|
||||
|
||||
// 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);
|
||||
|
||||
// Custom attribute constructors (function pointers)
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Il2CppInspector
|
||||
public Dictionary<int, (ulong, object)> ParameterDefaultValue { get; } = new Dictionary<int, (ulong, object)>();
|
||||
public List<long> FieldOffsets { get; }
|
||||
public List<Il2CppType> TypeReferences => Binary.TypeReferences;
|
||||
public Dictionary<ulong, int> TypeReferenceIndicesByAddress => Binary.TypeReferenceIndicesByAddress;
|
||||
public List<Il2CppGenericInst> GenericInstances => Binary.GenericInstances;
|
||||
public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules;
|
||||
public ulong[] CustomAttributeGenerators => Binary.CustomAttributeGenerators;
|
||||
|
||||
@@ -8,7 +8,6 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Il2CppInspector.Reflection
|
||||
{
|
||||
@@ -32,12 +31,8 @@ namespace Il2CppInspector.Reflection
|
||||
// List of all type definitions by fully qualified name (TypeDefs only)
|
||||
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
|
||||
public IEnumerable<TypeInfo> Types => new IEnumerable<TypeInfo>[]
|
||||
{TypesByDefinitionIndex, TypesByReferenceIndex, TypesByMethodSpecClassIndex.Values, TypesByVirtualAddress.Values}
|
||||
public IEnumerable<TypeInfo> Types => new IEnumerable<TypeInfo>[] {TypesByDefinitionIndex, TypesByReferenceIndex, TypesByMethodSpecClassIndex.Values}
|
||||
.SelectMany(t => t).Distinct();
|
||||
|
||||
// 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)
|
||||
var genericTypeArguments = Package.BinaryImage.ReadMappedWordArray(inst.type_argv, (int)inst.type_argc);
|
||||
|
||||
|
||||
return genericTypeArguments.Select(a => GetTypeFromVirtualAddress((ulong) a)).ToList();
|
||||
}
|
||||
|
||||
@@ -149,17 +144,18 @@ namespace Il2CppInspector.Reflection
|
||||
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
|
||||
// TODO: Eliminate GetTypeFromVirtualAddress() - use base and offset from MetadataRegistration.ptypes (Package.TypeReferences) instead
|
||||
public TypeInfo GetTypeFromVirtualAddress(ulong ptr) {
|
||||
if (TypesByVirtualAddress.ContainsKey(ptr))
|
||||
return TypesByVirtualAddress[ptr];
|
||||
var typeRefIndex = Package.TypeReferenceIndicesByAddress[ptr];
|
||||
|
||||
var type = Package.BinaryImage.ReadMappedObject<Il2CppType>(ptr);
|
||||
if (TypesByReferenceIndex[typeRefIndex] != null)
|
||||
return TypesByReferenceIndex[typeRefIndex];
|
||||
|
||||
var type = Package.TypeReferences[typeRefIndex];
|
||||
var referencedType = resolveTypeReference(type);
|
||||
|
||||
TypesByVirtualAddress.TryAdd(ptr, referencedType);
|
||||
TypesByReferenceIndex[typeRefIndex] = referencedType;
|
||||
return referencedType;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,10 +103,8 @@ namespace Il2CppInspector.Reflection
|
||||
Position = generic.Position;
|
||||
Attributes = generic.Attributes;
|
||||
|
||||
// TODO: Duplicate instances of 'concrete' may cause this search to fail. Replace with a straight lookup after eliminating GetTypeFromVirtualAddress
|
||||
//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;
|
||||
// Search for the concrete type's TypeRef index to store as the parameter type reference index
|
||||
paramTypeReference = Array.IndexOf(model.TypesByReferenceIndex, concrete);
|
||||
|
||||
DefaultValue = generic.DefaultValue;
|
||||
DefaultValueMetadataAddress = generic.DefaultValueMetadataAddress;
|
||||
|
||||
@@ -580,6 +580,8 @@ namespace Il2CppInspector.Reflection {
|
||||
|
||||
// Open and closed generic types
|
||||
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST) {
|
||||
|
||||
// TODO: Replace with array load from Il2CppMetadataRegistration.genericClasses
|
||||
var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.datapoint); // Il2CppGenericClass *
|
||||
|
||||
// We have seen one test case where the TypeRef can point to no generic instance
|
||||
@@ -608,6 +610,7 @@ namespace Il2CppInspector.Reflection {
|
||||
IsGenericParameter = false;
|
||||
|
||||
// Get the instantiation
|
||||
// TODO: Replace with array load from Il2CppMetadataRegistration.genericInsts
|
||||
var genericInstance = image.ReadMappedObject<Il2CppGenericInst>(generic.context.class_inst);
|
||||
|
||||
if (generic.context.method_inst != 0)
|
||||
|
||||
Reference in New Issue
Block a user