Model: Re-implement the handling of Il2CppType
This commit is contained in:
@@ -16,25 +16,32 @@ namespace Il2CppInspector.Reflection
|
|||||||
public List<Assembly> Assemblies { get; } = new List<Assembly>();
|
public List<Assembly> Assemblies { get; } = new List<Assembly>();
|
||||||
|
|
||||||
// List of all types ordered by their TypeDefinitionIndex
|
// List of all types ordered by their TypeDefinitionIndex
|
||||||
public TypeInfo[] TypesByIndex { get; }
|
public TypeInfo[] TypesByDefinitionIndex { get; }
|
||||||
|
|
||||||
|
// List of all type usages ordered by their type usage index
|
||||||
|
public TypeInfo[] TypesByUsageIndex { get; }
|
||||||
|
|
||||||
|
// List of type usages that are initialized via pointers in the image
|
||||||
|
public Dictionary<ulong, TypeInfo> TypesByVirtualAddress { get; } = new Dictionary<ulong, TypeInfo>();
|
||||||
|
|
||||||
|
// List of all types
|
||||||
|
|
||||||
public Il2CppModel(Il2CppInspector package) {
|
public Il2CppModel(Il2CppInspector package) {
|
||||||
Package = package;
|
Package = package;
|
||||||
TypesByIndex = new TypeInfo[package.TypeDefinitions.Length];
|
TypesByDefinitionIndex = new TypeInfo[package.TypeDefinitions.Length];
|
||||||
|
TypesByUsageIndex = new TypeInfo[package.TypeUsages.Count];
|
||||||
|
|
||||||
// Create Assembly objects from Il2Cpp package
|
// Create Assembly objects from Il2Cpp package
|
||||||
for (var image = 0; image < package.Images.Length; image++)
|
for (var image = 0; image < package.Images.Length; image++)
|
||||||
Assemblies.Add(new Assembly(this, image));
|
Assemblies.Add(new Assembly(this, image));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get or generate a type from its IL2CPP binary type usage reference
|
private TypeInfo getNewTypeUsage(Il2CppType usage, MemberTypes memberType) {
|
||||||
// (field, return type, generic type parameter etc.)
|
switch (usage.type) {
|
||||||
public TypeInfo GetType(Il2CppType pType, MemberTypes memberType = MemberTypes.All) {
|
|
||||||
switch (pType.type) {
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
|
case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
|
case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
|
||||||
// Classes defined in the metadata
|
// Classes defined in the metadata
|
||||||
return TypesByIndex[(int) pType.datapoint];
|
return TypesByDefinitionIndex[usage.datapoint];
|
||||||
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
|
case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY:
|
case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY:
|
||||||
@@ -43,20 +50,49 @@ namespace Il2CppInspector.Reflection
|
|||||||
case Il2CppTypeEnum.IL2CPP_TYPE_VAR:
|
case Il2CppTypeEnum.IL2CPP_TYPE_VAR:
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_MVAR:
|
case Il2CppTypeEnum.IL2CPP_TYPE_MVAR:
|
||||||
// Everything that requires special handling
|
// Everything that requires special handling
|
||||||
return new TypeInfo(this, pType, memberType);
|
return new TypeInfo(this, usage, memberType);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return GetTypeFromEnum(pType.type);
|
// Primitive types
|
||||||
|
return GetTypeFromTypeEnum(usage.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get or generate a type from its IL2CPP binary type usage reference
|
||||||
|
// (field, return type, generic type parameter etc.)
|
||||||
|
public TypeInfo GetTypeFromUsage(int typeUsageIndex, MemberTypes memberType = MemberTypes.All) {
|
||||||
|
|
||||||
|
// Already generated type previously?
|
||||||
|
if (TypesByUsageIndex[typeUsageIndex] != null)
|
||||||
|
return TypesByUsageIndex[typeUsageIndex];
|
||||||
|
|
||||||
|
var usage = Package.TypeUsages[typeUsageIndex];
|
||||||
|
var newUsage = getNewTypeUsage(usage, memberType);
|
||||||
|
|
||||||
|
TypesByUsageIndex[typeUsageIndex] = newUsage;
|
||||||
|
return newUsage;
|
||||||
|
}
|
||||||
|
|
||||||
// Basic primitive types
|
// Basic primitive types
|
||||||
public TypeInfo GetTypeFromEnum(Il2CppTypeEnum t) {
|
public TypeInfo GetTypeFromTypeEnum(Il2CppTypeEnum t) {
|
||||||
if ((int)t >= Il2CppConstants.FullNameTypeString.Count)
|
if ((int)t >= Il2CppConstants.FullNameTypeString.Count)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var fqn = Il2CppConstants.FullNameTypeString[(int) t];
|
var fqn = Il2CppConstants.FullNameTypeString[(int) t];
|
||||||
return TypesByIndex.First(x => x.FullName == fqn);
|
return TypesByDefinitionIndex.First(x => x.FullName == fqn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type from a virtual address pointer
|
||||||
|
// These are always nested types frorm usages within another type
|
||||||
|
public TypeInfo GetTypeFromVirtualAddress(ulong ptr) {
|
||||||
|
if (TypesByVirtualAddress.ContainsKey(ptr))
|
||||||
|
return TypesByVirtualAddress[ptr];
|
||||||
|
|
||||||
|
var type = Package.BinaryImage.ReadMappedObject<Il2CppType>(ptr);
|
||||||
|
var newUsage = getNewTypeUsage(type, MemberTypes.NestedType);
|
||||||
|
|
||||||
|
TypesByVirtualAddress.Add(ptr, newUsage);
|
||||||
|
return newUsage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,6 @@ namespace Il2CppInspector.Reflection
|
|||||||
|
|
||||||
public static readonly string TypeConstructorName = ".cctor";
|
public static readonly string TypeConstructorName = ".cctor";
|
||||||
|
|
||||||
// TODO
|
|
||||||
public override MemberTypes MemberType => MemberTypes.Constructor;
|
public override MemberTypes MemberType => MemberTypes.Constructor;
|
||||||
|
|
||||||
public ConstructorInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType) { }
|
public ConstructorInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType) { }
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ namespace Il2CppInspector.Reflection
|
|||||||
public MethodInfo RaiseMethod { get; }
|
public MethodInfo RaiseMethod { get; }
|
||||||
|
|
||||||
// Event handler delegate type
|
// Event handler delegate type
|
||||||
private Il2CppType eventType;
|
private int eventTypeUsage;
|
||||||
public TypeInfo EventHandlerType => Assembly.Model.GetType(eventType, MemberTypes.TypeInfo);
|
public TypeInfo EventHandlerType => Assembly.Model.GetTypeFromUsage(eventTypeUsage, MemberTypes.TypeInfo);
|
||||||
|
|
||||||
// True if the event has a special name
|
// True if the event has a special name
|
||||||
public bool IsSpecialName => (Attributes & EventAttributes.SpecialName) == EventAttributes.SpecialName;
|
public bool IsSpecialName => (Attributes & EventAttributes.SpecialName) == EventAttributes.SpecialName;
|
||||||
@@ -38,7 +38,9 @@ namespace Il2CppInspector.Reflection
|
|||||||
Index = eventIndex;
|
Index = eventIndex;
|
||||||
Name = pkg.Strings[Definition.nameIndex];
|
Name = pkg.Strings[Definition.nameIndex];
|
||||||
|
|
||||||
eventType = pkg.TypeUsages[Definition.typeIndex];
|
eventTypeUsage = Definition.typeIndex;
|
||||||
|
var eventType = pkg.TypeUsages[eventTypeUsage];
|
||||||
|
|
||||||
if ((eventType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME) == Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME)
|
if ((eventType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME) == Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME)
|
||||||
Attributes |= EventAttributes.SpecialName;
|
Attributes |= EventAttributes.SpecialName;
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ namespace Il2CppInspector.Reflection {
|
|||||||
public FieldAttributes Attributes { get; }
|
public FieldAttributes Attributes { get; }
|
||||||
|
|
||||||
// Type of field
|
// Type of field
|
||||||
private readonly Il2CppType fieldType;
|
private readonly int fieldTypeUsage;
|
||||||
public TypeInfo FieldType => Assembly.Model.GetType(fieldType, MemberTypes.Field);
|
public TypeInfo FieldType => Assembly.Model.GetTypeFromUsage(fieldTypeUsage, MemberTypes.Field);
|
||||||
|
|
||||||
// For the Is* definitions below, see:
|
// For the Is* definitions below, see:
|
||||||
// https://docs.microsoft.com/en-us/dotnet/api/system.reflection.fieldinfo.isfamilyandassembly?view=netframework-4.7.1#System_Reflection_FieldInfo_IsFamilyAndAssembly
|
// https://docs.microsoft.com/en-us/dotnet/api/system.reflection.fieldinfo.isfamilyandassembly?view=netframework-4.7.1#System_Reflection_FieldInfo_IsFamilyAndAssembly
|
||||||
@@ -88,7 +88,9 @@ namespace Il2CppInspector.Reflection {
|
|||||||
Offset = pkg.FieldOffsets[fieldIndex];
|
Offset = pkg.FieldOffsets[fieldIndex];
|
||||||
Name = pkg.Strings[Definition.nameIndex];
|
Name = pkg.Strings[Definition.nameIndex];
|
||||||
|
|
||||||
fieldType = pkg.TypeUsages[Definition.typeIndex];
|
fieldTypeUsage = Definition.typeIndex;
|
||||||
|
var fieldType = pkg.TypeUsages[fieldTypeUsage];
|
||||||
|
|
||||||
if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PRIVATE)
|
if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PRIVATE)
|
||||||
Attributes |= FieldAttributes.Private;
|
Attributes |= FieldAttributes.Private;
|
||||||
if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PUBLIC)
|
if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PUBLIC)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Il2CppInspector.Reflection {
|
|||||||
|
|
||||||
// Type that this type is declared in for nested types
|
// Type that this type is declared in for nested types
|
||||||
protected int declaringTypeDefinitionIndex { private get; set; } = -1;
|
protected int declaringTypeDefinitionIndex { private get; set; } = -1;
|
||||||
public TypeInfo DeclaringType => declaringTypeDefinitionIndex != -1? Assembly.Model.TypesByIndex[declaringTypeDefinitionIndex] : null;
|
public TypeInfo DeclaringType => declaringTypeDefinitionIndex != -1? Assembly.Model.TypesByDefinitionIndex[declaringTypeDefinitionIndex] : null;
|
||||||
|
|
||||||
// What sort of member this is, eg. method, field etc.
|
// What sort of member this is, eg. method, field etc.
|
||||||
public abstract MemberTypes MemberType { get; }
|
public abstract MemberTypes MemberType { get; }
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ namespace Il2CppInspector.Reflection
|
|||||||
public ParameterInfo ReturnParameter { get; }
|
public ParameterInfo ReturnParameter { get; }
|
||||||
|
|
||||||
// Return type of the method
|
// Return type of the method
|
||||||
private readonly Il2CppType returnType;
|
private readonly int returnTypeUsage;
|
||||||
public TypeInfo ReturnType => Assembly.Model.GetType(returnType, MemberTypes.TypeInfo);
|
public TypeInfo ReturnType => Assembly.Model.GetTypeFromUsage(returnTypeUsage, MemberTypes.TypeInfo);
|
||||||
|
|
||||||
// TODO: ReturnTypeCustomAttributes
|
// TODO: ReturnTypeCustomAttributes
|
||||||
|
|
||||||
public MethodInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType) {
|
public MethodInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType) {
|
||||||
// Add return parameter
|
// Add return parameter
|
||||||
returnType = pkg.TypeUsages[Definition.returnType];
|
returnTypeUsage = Definition.returnType;
|
||||||
ReturnParameter = new ParameterInfo(pkg, -1, this);
|
ReturnParameter = new ParameterInfo(pkg, -1, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ namespace Il2CppInspector.Reflection
|
|||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
// Type of this parameter
|
// Type of this parameter
|
||||||
private readonly Il2CppType paramType;
|
private readonly int paramTypeUsage;
|
||||||
public TypeInfo ParameterType => Member.Assembly.Model.GetType(paramType, MemberTypes.TypeInfo);
|
public TypeInfo ParameterType => Member.Assembly.Model.GetTypeFromUsage(paramTypeUsage, MemberTypes.TypeInfo);
|
||||||
|
|
||||||
// Zero-indexed position of the parameter in parameter list
|
// Zero-indexed position of the parameter in parameter list
|
||||||
public int Position { get; }
|
public int Position { get; }
|
||||||
@@ -46,7 +46,7 @@ namespace Il2CppInspector.Reflection
|
|||||||
|
|
||||||
if (paramIndex == -1) {
|
if (paramIndex == -1) {
|
||||||
Position = -1;
|
Position = -1;
|
||||||
paramType = pkg.TypeUsages[declaringMethod.Definition.returnType];
|
paramTypeUsage = declaringMethod.Definition.returnType;
|
||||||
Attributes |= ParameterAttributes.Retval;
|
Attributes |= ParameterAttributes.Retval;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,8 @@ namespace Il2CppInspector.Reflection
|
|||||||
var param = pkg.Params[paramIndex];
|
var param = pkg.Params[paramIndex];
|
||||||
Name = pkg.Strings[param.nameIndex];
|
Name = pkg.Strings[param.nameIndex];
|
||||||
Position = paramIndex - declaringMethod.Definition.parameterStart;
|
Position = paramIndex - declaringMethod.Definition.parameterStart;
|
||||||
paramType = pkg.TypeUsages[param.typeIndex];
|
paramTypeUsage = param.typeIndex;
|
||||||
|
var paramType = pkg.TypeUsages[paramTypeUsage];
|
||||||
|
|
||||||
if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_OPTIONAL) != 0)
|
if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_OPTIONAL) != 0)
|
||||||
Attributes |= ParameterAttributes.Optional;
|
Attributes |= ParameterAttributes.Optional;
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ namespace Il2CppInspector.Reflection {
|
|||||||
public TypeAttributes Attributes { get; }
|
public TypeAttributes Attributes { get; }
|
||||||
|
|
||||||
// Type that this type inherits from
|
// Type that this type inherits from
|
||||||
private Il2CppType baseType;
|
private int baseTypeUsage;
|
||||||
public TypeInfo BaseType => baseType != null? Assembly.Model.GetType(baseType, MemberTypes.TypeInfo) : null;
|
public TypeInfo BaseType => Assembly.Model.GetTypeFromUsage(baseTypeUsage, MemberTypes.TypeInfo);
|
||||||
|
|
||||||
// True if the type contains unresolved generic type parameters
|
// True if the type contains unresolved generic type parameters
|
||||||
public bool ContainsGenericParameters { get; }
|
public bool ContainsGenericParameters { get; }
|
||||||
@@ -49,7 +49,7 @@ namespace Il2CppInspector.Reflection {
|
|||||||
public List<MethodInfo> DeclaredMethods { get; } = new List<MethodInfo>();
|
public List<MethodInfo> DeclaredMethods { get; } = new List<MethodInfo>();
|
||||||
|
|
||||||
private int[] declaredNestedTypes;
|
private int[] declaredNestedTypes;
|
||||||
public IEnumerable<TypeInfo> DeclaredNestedTypes => declaredNestedTypes.Select(x => Assembly.Model.TypesByIndex[x]);
|
public IEnumerable<TypeInfo> DeclaredNestedTypes => declaredNestedTypes.Select(x => Assembly.Model.TypesByDefinitionIndex[x]);
|
||||||
|
|
||||||
public List<PropertyInfo> DeclaredProperties { get; } = new List<PropertyInfo>();
|
public List<PropertyInfo> DeclaredProperties { get; } = new List<PropertyInfo>();
|
||||||
|
|
||||||
@@ -57,12 +57,12 @@ namespace Il2CppInspector.Reflection {
|
|||||||
public MethodBase DeclaringMethod => throw new NotImplementedException();
|
public MethodBase DeclaringMethod => throw new NotImplementedException();
|
||||||
|
|
||||||
// Gets the type of the object encompassed or referred to by the current array, pointer or reference type
|
// Gets the type of the object encompassed or referred to by the current array, pointer or reference type
|
||||||
private Il2CppType enumElementType;
|
private int enumElementTypeUsage;
|
||||||
private TypeInfo elementType;
|
private TypeInfo elementType;
|
||||||
public TypeInfo ElementType {
|
public TypeInfo ElementType {
|
||||||
get {
|
get {
|
||||||
if (IsEnum && elementType == null)
|
if (IsEnum && elementType == null)
|
||||||
elementType = Assembly.Model.GetType(enumElementType, MemberTypes.TypeInfo);
|
elementType = Assembly.Model.GetTypeFromUsage(enumElementTypeUsage, MemberTypes.TypeInfo);
|
||||||
return elementType;
|
return elementType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,8 +82,8 @@ namespace Il2CppInspector.Reflection {
|
|||||||
|
|
||||||
public bool HasElementType => ElementType != null;
|
public bool HasElementType => ElementType != null;
|
||||||
|
|
||||||
private Il2CppType[] implementedInterfaces;
|
private int[] implementedInterfaceUsages;
|
||||||
public IEnumerable<TypeInfo> ImplementedInterfaces => implementedInterfaces.Select(x => Assembly.Model.GetType(x, MemberTypes.TypeInfo));
|
public IEnumerable<TypeInfo> ImplementedInterfaces => implementedInterfaceUsages.Select(x => Assembly.Model.GetTypeFromUsage(x, MemberTypes.TypeInfo));
|
||||||
|
|
||||||
public bool IsAbstract => (Attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract;
|
public bool IsAbstract => (Attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract;
|
||||||
public bool IsArray { get; }
|
public bool IsArray { get; }
|
||||||
@@ -155,15 +155,16 @@ namespace Il2CppInspector.Reflection {
|
|||||||
Name = pkg.Strings[Definition.nameIndex];
|
Name = pkg.Strings[Definition.nameIndex];
|
||||||
|
|
||||||
if (Definition.parentIndex >= 0)
|
if (Definition.parentIndex >= 0)
|
||||||
baseType = pkg.TypeUsages[Definition.parentIndex];
|
baseTypeUsage = Definition.parentIndex;
|
||||||
|
|
||||||
// Nested type?
|
// Nested type?
|
||||||
if (Definition.declaringTypeIndex >= 0) {
|
if (Definition.declaringTypeIndex >= 0) {
|
||||||
declaringTypeDefinitionIndex = (int) pkg.TypeUsages[Definition.declaringTypeIndex].datapoint;
|
declaringTypeDefinitionIndex = (int) pkg.TypeUsages[Definition.declaringTypeIndex].datapoint;
|
||||||
|
MemberType |= MemberTypes.NestedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to global type definition list
|
// Add to global type definition list
|
||||||
Assembly.Model.TypesByIndex[Index] = this;
|
Assembly.Model.TypesByDefinitionIndex[Index] = this;
|
||||||
|
|
||||||
if ((Definition.flags & Il2CppConstants.TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
|
if ((Definition.flags & Il2CppConstants.TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
|
||||||
Attributes |= TypeAttributes.Serializable;
|
Attributes |= TypeAttributes.Serializable;
|
||||||
@@ -196,16 +197,16 @@ namespace Il2CppInspector.Reflection {
|
|||||||
if ((Definition.flags & Il2CppConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
|
if ((Definition.flags & Il2CppConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
|
||||||
Attributes |= TypeAttributes.Interface;
|
Attributes |= TypeAttributes.Interface;
|
||||||
|
|
||||||
// Enumerations - bit 1 of bitfield indicates this (also the baseType will be System.Enum)
|
// Enumerations - bit 1 of bitfield indicates this (also the baseTypeUsage will be System.Enum)
|
||||||
if (((Definition.bitfield >> 1) & 1) == 1) {
|
if (((Definition.bitfield >> 1) & 1) == 1) {
|
||||||
IsEnum = true;
|
IsEnum = true;
|
||||||
enumElementType = pkg.TypeUsages[Definition.elementTypeIndex];
|
enumElementTypeUsage = Definition.elementTypeIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all implemented interfaces
|
// Add all implemented interfaces
|
||||||
implementedInterfaces = new Il2CppType[Definition.interfaces_count];
|
implementedInterfaceUsages = new int[Definition.interfaces_count];
|
||||||
for (var i = 0; i < Definition.interfaces_count; i++)
|
for (var i = 0; i < Definition.interfaces_count; i++)
|
||||||
implementedInterfaces[i] = pkg.TypeUsages[pkg.InterfaceUsageIndices[Definition.interfacesStart + i]];
|
implementedInterfaceUsages[i] = pkg.InterfaceUsageIndices[Definition.interfacesStart + i];
|
||||||
|
|
||||||
// Add all nested types
|
// Add all nested types
|
||||||
declaredNestedTypes = new int[Definition.nested_type_count];
|
declaredNestedTypes = new int[Definition.nested_type_count];
|
||||||
@@ -246,7 +247,7 @@ namespace Il2CppInspector.Reflection {
|
|||||||
// 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);
|
var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.datapoint);
|
||||||
var genericTypeDef = model.TypesByIndex[generic.typeDefinitionIndex];
|
var genericTypeDef = model.TypesByDefinitionIndex[generic.typeDefinitionIndex];
|
||||||
|
|
||||||
Namespace = genericTypeDef.Namespace;
|
Namespace = genericTypeDef.Namespace;
|
||||||
Name = genericTypeDef.Name;
|
Name = genericTypeDef.Name;
|
||||||
@@ -261,10 +262,10 @@ namespace Il2CppInspector.Reflection {
|
|||||||
|
|
||||||
GenericTypeParameters = new List<TypeInfo>();
|
GenericTypeParameters = new List<TypeInfo>();
|
||||||
foreach (var pArg in genericTypeParameters) {
|
foreach (var pArg in genericTypeParameters) {
|
||||||
var argType = image.ReadMappedObject<Il2CppType>((ulong) pArg);
|
var argType = model.GetTypeFromVirtualAddress((ulong) pArg);
|
||||||
// TODO: Detect whether unresolved or concrete (add concrete to GenericTypeArguments instead)
|
// TODO: Detect whether unresolved or concrete (add concrete to GenericTypeArguments instead)
|
||||||
// TODO: GenericParameterPosition etc. in types we generate here
|
// TODO: GenericParameterPosition etc. in types we generate here
|
||||||
GenericTypeParameters.Add(model.GetType(argType)); // TODO: Fix MemberType here
|
GenericTypeParameters.Add(argType); // TODO: Fix MemberType here
|
||||||
}
|
}
|
||||||
Attributes |= TypeAttributes.Class;
|
Attributes |= TypeAttributes.Class;
|
||||||
}
|
}
|
||||||
@@ -272,8 +273,7 @@ namespace Il2CppInspector.Reflection {
|
|||||||
// 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);
|
||||||
var elementType = image.ReadMappedObject<Il2CppType>(descriptor.etype);
|
elementType = model.GetTypeFromVirtualAddress(descriptor.etype);
|
||||||
this.elementType = model.GetType(elementType);
|
|
||||||
Namespace = ElementType.Namespace;
|
Namespace = ElementType.Namespace;
|
||||||
Name = ElementType.Name;
|
Name = ElementType.Name;
|
||||||
|
|
||||||
@@ -283,8 +283,7 @@ namespace Il2CppInspector.Reflection {
|
|||||||
|
|
||||||
// Dynamically allocated array
|
// Dynamically allocated array
|
||||||
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY) {
|
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY) {
|
||||||
var elementType = image.ReadMappedObject<Il2CppType>(pType.datapoint);
|
elementType = model.GetTypeFromVirtualAddress(pType.datapoint);
|
||||||
this.elementType = model.GetType(elementType);
|
|
||||||
Namespace = ElementType.Namespace;
|
Namespace = ElementType.Namespace;
|
||||||
Name = ElementType.Name;
|
Name = ElementType.Name;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user