Model: Handle generic type parameter usages correctly

This commit is contained in:
Katy Coe
2019-11-01 17:41:26 +01:00
parent 364daf9dd8
commit a1046d6322

View File

@@ -187,9 +187,9 @@ namespace Il2CppInspector.Reflection {
ContainsGenericParameters = true; ContainsGenericParameters = true;
// Store the generic type parameters for later instantiation // Store the generic type parameters for later instantiation
var gc = pkg.GenericContainers[Definition.genericContainerIndex]; var container = pkg.GenericContainers[Definition.genericContainerIndex];
GenericTypeParameters = pkg.GenericParameters.Skip((int) gc.genericParameterStart).Take(gc.type_argc).Select(p => new TypeInfo(this, p)).ToList(); GenericTypeParameters = pkg.GenericParameters.Skip((int) container.genericParameterStart).Take(container.type_argc).Select(p => new TypeInfo(this, p)).ToList();
// TODO: Constraints // TODO: Constraints
// TODO: Attributes // TODO: Attributes
@@ -268,11 +268,10 @@ namespace Il2CppInspector.Reflection {
} }
// Initialize type from binary usage // Initialize type from binary usage
// Much of the following is adapted from il2cpp::vm::Class::FromIl2CppType
public TypeInfo(Il2CppModel model, Il2CppType pType, MemberTypes memberType) { public TypeInfo(Il2CppModel model, Il2CppType pType, MemberTypes memberType) {
var image = model.Package.BinaryImage; var image = model.Package.BinaryImage;
// Finding TypeDefinitions adapted from il2cpp::vm::Class::FromIl2CppType
// Generic type unresolved and concrete instance types // Generic type unresolved and concrete instance types
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST) { if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST) {
var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.datapoint); // Il2CppGenericClass * var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.datapoint); // Il2CppGenericClass *
@@ -287,6 +286,7 @@ namespace Il2CppInspector.Reflection {
if (genericTypeDef.Definition.parentIndex >= 0) if (genericTypeDef.Definition.parentIndex >= 0)
baseTypeUsage = genericTypeDef.Definition.parentIndex; baseTypeUsage = genericTypeDef.Definition.parentIndex;
// Nested type?
if (genericTypeDef.Definition.declaringTypeIndex >= 0) { if (genericTypeDef.Definition.declaringTypeIndex >= 0) {
declaringTypeDefinitionIndex = (int)model.Package.TypeUsages[genericTypeDef.Definition.declaringTypeIndex].datapoint; declaringTypeDefinitionIndex = (int)model.Package.TypeUsages[genericTypeDef.Definition.declaringTypeIndex].datapoint;
MemberType = memberType | MemberTypes.NestedType; MemberType = memberType | MemberTypes.NestedType;
@@ -311,12 +311,13 @@ namespace Il2CppInspector.Reflection {
} }
} }
// TODO: Set Assembly, BaseType and DeclaringType for all of the below // TODO: Set Assembly, BaseType and DeclaringType for the two below
// Array with known dimensions and bounds // Array with known dimensions and bounds
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_ARRAY) { if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_ARRAY) {
var descriptor = image.ReadMappedObject<Il2CppArrayType>(pType.datapoint); var descriptor = image.ReadMappedObject<Il2CppArrayType>(pType.datapoint);
elementType = model.GetTypeFromVirtualAddress(descriptor.etype); elementType = model.GetTypeFromVirtualAddress(descriptor.etype);
Namespace = ElementType.Namespace; Namespace = ElementType.Namespace;
Name = ElementType.Name; Name = ElementType.Name;
@@ -327,18 +328,40 @@ namespace Il2CppInspector.Reflection {
// Dynamically allocated array // Dynamically allocated array
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY) { if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY) {
elementType = model.GetTypeFromVirtualAddress(pType.datapoint); elementType = model.GetTypeFromVirtualAddress(pType.datapoint);
Namespace = ElementType.Namespace; Namespace = ElementType.Namespace;
Name = ElementType.Name; Name = ElementType.Name;
IsArray = true; IsArray = true;
} }
// Unresolved generic type variable // Generic type parameter
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_VAR || pType.type == Il2CppTypeEnum.IL2CPP_TYPE_MVAR) { if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_VAR || pType.type == Il2CppTypeEnum.IL2CPP_TYPE_MVAR) {
var paramType = model.Package.GenericParameters[pType.datapoint]; // genericParameterIndex
var container = model.Package.GenericContainers[paramType.ownerIndex];
var ownerType = model.TypesByDefinitionIndex[
container.is_method == 1
? model.Package.Methods[container.ownerIndex].declaringType
: container.ownerIndex];
Assembly = ownerType.Assembly;
Namespace = "";
Name = model.Package.Strings[paramType.nameIndex];
Attributes |= TypeAttributes.Class; Attributes |= TypeAttributes.Class;
// Derived type?
if (ownerType.Definition.parentIndex >= 0)
baseTypeUsage = ownerType.Definition.parentIndex;
// Nested type always - sets DeclaringType used below
declaringTypeDefinitionIndex = ownerType.Index;
MemberType = memberType | MemberTypes.NestedType;
IsGenericParameter = true; IsGenericParameter = true;
Name = "T"; // TODO: Don't hardcode parameter name ContainsGenericParameters = true;
// TODO: Add to GenericTypeParameters? ContainsGenericParameters? IsGenericType = false;
IsGenericTypeDefinition = false;
} }
// Pointer type // Pointer type