From 193cdcdc4a6ccda3e2a16bbad5b3fefc048b3ca1 Mon Sep 17 00:00:00 2001 From: Robert Xiao Date: Sat, 11 Apr 2020 17:00:33 -0700 Subject: [PATCH] Get rid of TypesByMethodSpecClassIndex. classIndexIndex only indexes the genericInstance, not the actual generic instance type. Therefore, for example, A and B have the same classIndexIndex because the generic parameters are the same, despite being otherwise unrelated. Instead of TypesByMethodSpecClassIndex, we simply call MakeGenericType each time, relying on genericTypeInstances to dedup the resulting instances. This patch thus also adds all of the types from genericTypeInstances to the Il2CppModel.Types listing. --- .../Reflection/Il2CppModel.cs | 28 ++++++++----------- Il2CppInspector.Common/Reflection/TypeInfo.cs | 7 +++++ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Il2CppInspector.Common/Reflection/Il2CppModel.cs b/Il2CppInspector.Common/Reflection/Il2CppModel.cs index 94a81e2..6ae57fd 100644 --- a/Il2CppInspector.Common/Reflection/Il2CppModel.cs +++ b/Il2CppInspector.Common/Reflection/Il2CppModel.cs @@ -22,9 +22,6 @@ namespace Il2CppInspector.Reflection // List of all types from TypeRefs ordered by instanceIndex public TypeInfo[] TypesByReferenceIndex { get; } - // List of all types from MethodSpecs (closed generic types that can be instantiated) - public Dictionary TypesByMethodSpecClassIndex { get; } = new Dictionary(); - // List of all methods from MethodSpecs (closed generic methods that can be called; does not need to be in a generic class) public Dictionary GenericMethods { get; } = new Dictionary(); @@ -32,8 +29,13 @@ namespace Il2CppInspector.Reflection public Dictionary TypesByFullName { get; } = new Dictionary(); // Every type - public IEnumerable Types => new IEnumerable[] {TypesByDefinitionIndex, TypesByReferenceIndex, TypesByMethodSpecClassIndex.Values} - .SelectMany(t => t).Distinct(); + public IEnumerable Types { + get { + var result = new IEnumerable[] { TypesByDefinitionIndex, TypesByReferenceIndex }.SelectMany(t => t); + result = result.Concat(result.SelectMany(t => t.CachedGeneratedTypes)); + return result.Distinct(); + } + } // List of all methods ordered by their MethodDefinitionIndex public MethodBase[] MethodsByDefinitionIndex { get; } @@ -91,14 +93,10 @@ namespace Il2CppInspector.Reflection // Concrete instance of a generic class // If the class index is not specified, we will later create a generic method in a non-generic class if (spec.classIndexIndex != -1) { - if (!TypesByMethodSpecClassIndex.ContainsKey(spec.classIndexIndex)) { - var genericTypeDefinition = MethodsByDefinitionIndex[spec.methodDefinitionIndex].DeclaringType; - var genericInstance = Package.GenericInstances[spec.classIndexIndex]; - var genericArguments = ResolveGenericArguments(genericInstance); - TypesByMethodSpecClassIndex.Add(spec.classIndexIndex, genericTypeDefinition.MakeGenericType(genericArguments)); - } - - declaringType = TypesByMethodSpecClassIndex[spec.classIndexIndex]; + var genericTypeDefinition = MethodsByDefinitionIndex[spec.methodDefinitionIndex].DeclaringType; + var genericInstance = Package.GenericInstances[spec.classIndexIndex]; + var genericArguments = ResolveGenericArguments(genericInstance); + declaringType = genericTypeDefinition.MakeGenericType(genericArguments); } else declaringType = MethodsByDefinitionIndex[spec.methodDefinitionIndex].DeclaringType; @@ -216,9 +214,7 @@ namespace Il2CppInspector.Reflection MetadataUsageType.TypeInfo => TypesByReferenceIndex[usage.SourceIndex], MetadataUsageType.MethodDef => GetMetadataUsageMethod(usage).DeclaringType, MetadataUsageType.FieldInfo => TypesByReferenceIndex[Package.FieldRefs[usage.SourceIndex].typeIndex], - MetadataUsageType.MethodRef => Package.MethodSpecs[usage.SourceIndex].classIndexIndex != -1? - TypesByMethodSpecClassIndex[Package.MethodSpecs[usage.SourceIndex].classIndexIndex] : - GetMetadataUsageMethod(usage).DeclaringType, + MetadataUsageType.MethodRef => GetMetadataUsageMethod(usage).DeclaringType, _ => throw new InvalidOperationException("Incorrect metadata usage type to retrieve referenced type") }; diff --git a/Il2CppInspector.Common/Reflection/TypeInfo.cs b/Il2CppInspector.Common/Reflection/TypeInfo.cs index 79c67e0..5d7d179 100644 --- a/Il2CppInspector.Common/Reflection/TypeInfo.cs +++ b/Il2CppInspector.Common/Reflection/TypeInfo.cs @@ -33,6 +33,13 @@ namespace Il2CppInspector.Reflection { } + // This property exposes all types which have been generated directly from this one. + public IEnumerable CachedGeneratedTypes { + get { + return genericTypeInstances?.Values ?? Enumerable.Empty(); + } + } + // Information/flags about the type // Undefined if the Type represents a generic type parameter public TypeAttributes Attributes { get; }