From f395ed3ff5254ba83f529108cbf7609ced110e32 Mon Sep 17 00:00:00 2001 From: Robert Xiao Date: Sat, 11 Apr 2020 22:32:43 -0700 Subject: [PATCH] Send FromTypeReference back to Il2CppModel Now that FromTypeReference uses public Make* methods instead of private TypeInfo constructors, it doesn't need to be in TypeInfo anymore. Move it back to Il2CppModel, where it was before. --- .../Reflection/Il2CppModel.cs | 75 ++++++++++++++++++- Il2CppInspector.Common/Reflection/TypeInfo.cs | 71 ------------------ 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/Il2CppInspector.Common/Reflection/Il2CppModel.cs b/Il2CppInspector.Common/Reflection/Il2CppModel.cs index 0227558..2266935 100644 --- a/Il2CppInspector.Common/Reflection/Il2CppModel.cs +++ b/Il2CppInspector.Common/Reflection/Il2CppModel.cs @@ -85,7 +85,7 @@ namespace Il2CppInspector.Reflection } var typeRef = Package.TypeReferences[typeRefIndex]; - var referencedType = TypeInfo.FromTypeReference(this, typeRef); + var referencedType = resolveTypeReference(typeRef); TypesByReferenceIndex[typeRefIndex] = referencedType; } @@ -151,6 +151,77 @@ namespace Il2CppInspector.Reflection return genericTypeArguments.Select(a => GetTypeFromVirtualAddress((ulong) a)).ToArray(); } + // Initialize type from type reference (TypeRef) + // Much of the following is adapted from il2cpp::vm::Class::FromIl2CppType + private TypeInfo resolveTypeReference(Il2CppType typeRef) { + var image = Package.BinaryImage; + TypeInfo underlyingType; + + switch (typeRef.type) { + // Classes defined in the metadata (reference to a TypeDef) + case Il2CppTypeEnum.IL2CPP_TYPE_CLASS: + case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE: + underlyingType = TypesByDefinitionIndex[typeRef.datapoint]; // klassIndex + break; + + // Constructed types + case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST: + // TODO: Replace with array load from Il2CppMetadataRegistration.genericClasses + var generic = image.ReadMappedObject(typeRef.datapoint); // Il2CppGenericClass * + + // We have seen one test case where the TypeRef can point to no generic instance + // This is going to leave the TypeInfo in an undefined state + if (generic.typeDefinitionIndex == 0x0000_0000_ffff_ffff) + return null; + + var genericTypeDef = TypesByDefinitionIndex[generic.typeDefinitionIndex]; + + // Get the instantiation + // TODO: Replace with array load from Il2CppMetadataRegistration.genericInsts + var genericInstance = image.ReadMappedObject(generic.context.class_inst); + var genericArguments = ResolveGenericArguments(genericInstance); + + underlyingType = genericTypeDef.MakeGenericType(genericArguments); + break; + case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: + var descriptor = image.ReadMappedObject(typeRef.datapoint); + var elementType = GetTypeFromVirtualAddress(descriptor.etype); + underlyingType = elementType.MakeArrayType(descriptor.rank); + break; + case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: + elementType = GetTypeFromVirtualAddress(typeRef.datapoint); + underlyingType = elementType.MakeArrayType(1); + break; + case Il2CppTypeEnum.IL2CPP_TYPE_PTR: + elementType = GetTypeFromVirtualAddress(typeRef.datapoint); + underlyingType = elementType.MakePointerType(); + break; + + // Generic type and generic method parameters + case Il2CppTypeEnum.IL2CPP_TYPE_VAR: + case Il2CppTypeEnum.IL2CPP_TYPE_MVAR: + underlyingType = GetGenericParameterType((int)typeRef.datapoint); + break; + + // Primitive types + default: + underlyingType = getTypeDefinitionFromTypeEnum(typeRef.type); + break; + } + + // Create a reference type if necessary + return typeRef.byref ? underlyingType.MakeByRefType() : underlyingType; + } + + // Basic primitive types are specified via a flag value + private TypeInfo getTypeDefinitionFromTypeEnum(Il2CppTypeEnum t) { + if ((int)t >= Il2CppConstants.FullNameTypeString.Count) + return null; + + var fqn = Il2CppConstants.FullNameTypeString[(int)t]; + return TypesByFullName[fqn]; + } + // Get a TypeRef by its virtual address // These are always nested types from references within another TypeRef public TypeInfo GetTypeFromVirtualAddress(ulong ptr) { @@ -160,7 +231,7 @@ namespace Il2CppInspector.Reflection return TypesByReferenceIndex[typeRefIndex]; var type = Package.TypeReferences[typeRefIndex]; - var referencedType = TypeInfo.FromTypeReference(this, type); + var referencedType = resolveTypeReference(type); TypesByReferenceIndex[typeRefIndex] = referencedType; return referencedType; diff --git a/Il2CppInspector.Common/Reflection/TypeInfo.cs b/Il2CppInspector.Common/Reflection/TypeInfo.cs index 175dbff..5c512b6 100644 --- a/Il2CppInspector.Common/Reflection/TypeInfo.cs +++ b/Il2CppInspector.Common/Reflection/TypeInfo.cs @@ -729,77 +729,6 @@ namespace Il2CppInspector.Reflection { DeclaredEvents.Add(new EventInfo(pkg, e, this)); } - // Initialize type from type reference (TypeRef) - // Much of the following is adapted from il2cpp::vm::Class::FromIl2CppType - internal static TypeInfo FromTypeReference(Il2CppModel model, Il2CppType typeRef) { - var image = model.Package.BinaryImage; - TypeInfo underlyingType; - - switch (typeRef.type) { - // Classes defined in the metadata (reference to a TypeDef) - case Il2CppTypeEnum.IL2CPP_TYPE_CLASS: - case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE: - underlyingType = model.TypesByDefinitionIndex[typeRef.datapoint]; // klassIndex - break; - - // Constructed types - case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST: - // TODO: Replace with array load from Il2CppMetadataRegistration.genericClasses - var generic = image.ReadMappedObject(typeRef.datapoint); // Il2CppGenericClass * - - // We have seen one test case where the TypeRef can point to no generic instance - // This is going to leave the TypeInfo in an undefined state - if (generic.typeDefinitionIndex == 0x0000_0000_ffff_ffff) - return null; - - var genericTypeDef = model.TypesByDefinitionIndex[generic.typeDefinitionIndex]; - - // Get the instantiation - // TODO: Replace with array load from Il2CppMetadataRegistration.genericInsts - var genericInstance = image.ReadMappedObject(generic.context.class_inst); - var genericArguments = model.ResolveGenericArguments(genericInstance); - - underlyingType = genericTypeDef.MakeGenericType(genericArguments); - break; - case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: - var descriptor = image.ReadMappedObject(typeRef.datapoint); - var elementType = model.GetTypeFromVirtualAddress(descriptor.etype); - underlyingType = elementType.MakeArrayType(descriptor.rank); - break; - case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: - elementType = model.GetTypeFromVirtualAddress(typeRef.datapoint); - underlyingType = elementType.MakeArrayType(1); - break; - case Il2CppTypeEnum.IL2CPP_TYPE_PTR: - elementType = model.GetTypeFromVirtualAddress(typeRef.datapoint); - underlyingType = elementType.MakePointerType(); - break; - - // Generic type and generic method parameters - case Il2CppTypeEnum.IL2CPP_TYPE_VAR: - case Il2CppTypeEnum.IL2CPP_TYPE_MVAR: - underlyingType = model.GetGenericParameterType((int)typeRef.datapoint); - break; - - // Primitive types - default: - underlyingType = FromTypeEnum(model, typeRef.type); - break; - } - - // Create a reference type if necessary - return typeRef.byref ? underlyingType.MakeByRefType() : underlyingType; - } - - // Basic primitive types are specified via a flag value - internal static TypeInfo FromTypeEnum(Il2CppModel model, Il2CppTypeEnum t) { - if ((int)t >= Il2CppConstants.FullNameTypeString.Count) - return null; - - var fqn = Il2CppConstants.FullNameTypeString[(int)t]; - return model.TypesByFullName[fqn]; - } - // Initialize a type from a concrete generic instance private TypeInfo(TypeInfo genericTypeDef, TypeInfo[] genericArgs) : base(genericTypeDef.Assembly) { if (!genericTypeDef.IsGenericTypeDefinition)