Model: Ensure all TypeRefs are initialized with the model
Ensures that all types are output in the IDA Python script Includes TypeRefs that aren't used in any type definition or member
This commit is contained in:
@@ -47,7 +47,7 @@ namespace Il2CppInspector.Reflection
|
||||
continue;
|
||||
}
|
||||
|
||||
attribute = new CustomAttributeData { Index = customAttributeIndex, AttributeType = asm.Model.GetTypeFromUsage(typeIndex) };
|
||||
attribute = new CustomAttributeData { Index = customAttributeIndex, AttributeType = asm.Model.TypesByReferenceIndex[typeIndex] };
|
||||
|
||||
asm.Model.AttributesByIndices.TryAdd(i, attribute);
|
||||
yield return attribute;
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace Il2CppInspector.Reflection
|
||||
public MethodInfo RaiseMethod { get; }
|
||||
|
||||
// Event handler delegate type
|
||||
private int eventTypeUsage;
|
||||
public TypeInfo EventHandlerType => Assembly.Model.GetTypeFromUsage(eventTypeUsage, MemberTypes.TypeInfo);
|
||||
private int eventTypeReference;
|
||||
public TypeInfo EventHandlerType => Assembly.Model.TypesByReferenceIndex[eventTypeReference];
|
||||
|
||||
// True if the event has a special name
|
||||
public bool IsSpecialName => (Attributes & EventAttributes.SpecialName) == EventAttributes.SpecialName;
|
||||
@@ -42,8 +42,8 @@ namespace Il2CppInspector.Reflection
|
||||
Index = eventIndex;
|
||||
Name = pkg.Strings[Definition.nameIndex];
|
||||
|
||||
eventTypeUsage = Definition.typeIndex;
|
||||
var eventType = pkg.TypeReferences[eventTypeUsage];
|
||||
eventTypeReference = Definition.typeIndex;
|
||||
var eventType = pkg.TypeReferences[eventTypeReference];
|
||||
|
||||
if ((eventType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME) == Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME)
|
||||
Attributes |= EventAttributes.SpecialName;
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace Il2CppInspector.Reflection {
|
||||
public FieldAttributes Attributes { get; }
|
||||
|
||||
// Type of field
|
||||
private readonly int fieldTypeUsage;
|
||||
public TypeInfo FieldType => Assembly.Model.GetTypeFromUsage(fieldTypeUsage, MemberTypes.Field);
|
||||
private readonly int fieldTypeReference;
|
||||
public TypeInfo FieldType => Assembly.Model.TypesByReferenceIndex[fieldTypeReference];
|
||||
|
||||
// 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
|
||||
@@ -81,8 +81,8 @@ namespace Il2CppInspector.Reflection {
|
||||
Offset = pkg.FieldOffsets[fieldIndex];
|
||||
Name = pkg.Strings[Definition.nameIndex];
|
||||
|
||||
fieldTypeUsage = Definition.typeIndex;
|
||||
var fieldType = pkg.TypeReferences[fieldTypeUsage];
|
||||
fieldTypeReference = Definition.typeIndex;
|
||||
var fieldType = pkg.TypeReferences[fieldTypeReference];
|
||||
|
||||
if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PRIVATE)
|
||||
Attributes |= FieldAttributes.Private;
|
||||
|
||||
@@ -17,20 +17,20 @@ namespace Il2CppInspector.Reflection
|
||||
public Il2CppInspector Package { get; }
|
||||
public List<Assembly> Assemblies { get; } = new List<Assembly>();
|
||||
|
||||
// List of all types ordered by their TypeDefinitionIndex
|
||||
// List of all types from TypeDefs ordered by their TypeDefinitionIndex
|
||||
public TypeInfo[] TypesByDefinitionIndex { get; }
|
||||
|
||||
// List of all type definitions by fully qualified name
|
||||
// List of all types from TypeRefs ordered by index
|
||||
public TypeInfo[] TypesByReferenceIndex { get; }
|
||||
|
||||
// List of all type definitions by fully qualified name (TypeDefs only)
|
||||
public Dictionary<string, TypeInfo> TypesByFullName { get; } = new Dictionary<string, TypeInfo>();
|
||||
|
||||
// List of all type references ordered by index
|
||||
public TypeInfo[] TypeReferences { get; }
|
||||
|
||||
// List of type usages that are initialized via pointers in the image
|
||||
// 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, TypeReferences, TypesByVirtualAddress.Values}.SelectMany(t => t);
|
||||
public IEnumerable<TypeInfo> Types => new IEnumerable<TypeInfo>[] {TypesByDefinitionIndex, TypesByReferenceIndex, TypesByVirtualAddress.Values}.SelectMany(t => t);
|
||||
|
||||
// List of all methods ordered by their MethodDefinitionIndex
|
||||
public MethodBase[] MethodsByDefinitionIndex { get; }
|
||||
@@ -38,67 +38,66 @@ namespace Il2CppInspector.Reflection
|
||||
// List of all generated CustomAttributeData objects by their index into AttributeTypeIndices
|
||||
public ConcurrentDictionary<int, CustomAttributeData> AttributesByIndices { get; } = new ConcurrentDictionary<int, CustomAttributeData>();
|
||||
|
||||
public Il2CppModel(Il2CppInspector package) {
|
||||
Package = package;
|
||||
TypesByDefinitionIndex = new TypeInfo[package.TypeDefinitions.Length];
|
||||
TypeReferences = new TypeInfo[package.TypeReferences.Count];
|
||||
MethodsByDefinitionIndex = new MethodBase[package.Methods.Length];
|
||||
|
||||
// Create Assembly objects from Il2Cpp package
|
||||
for (var image = 0; image < package.Images.Length; image++)
|
||||
Assemblies.Add(new Assembly(this, image));
|
||||
}
|
||||
|
||||
// Get an assembly by its image name
|
||||
public Assembly GetAssembly(string name) => Assemblies.FirstOrDefault(a => a.ShortName == name);
|
||||
|
||||
private TypeInfo getNewTypeUsage(Il2CppType usage, MemberTypes memberType) {
|
||||
// Create type model
|
||||
public Il2CppModel(Il2CppInspector package) {
|
||||
Package = package;
|
||||
TypesByDefinitionIndex = new TypeInfo[package.TypeDefinitions.Length];
|
||||
TypesByReferenceIndex = new TypeInfo[package.TypeReferences.Count];
|
||||
MethodsByDefinitionIndex = new MethodBase[package.Methods.Length];
|
||||
|
||||
// Recursively create hierarchy of assemblies and types from TypeDefs
|
||||
// No code that executes here can access any type through a TypeRef (ie. via TypesByReferenceIndex)
|
||||
for (var image = 0; image < package.Images.Length; image++)
|
||||
Assemblies.Add(new Assembly(this, image));
|
||||
|
||||
// Create and reference types from TypeRefs
|
||||
// Note that you can't resolve any TypeRefs until all the TypeDefs have been processed
|
||||
for (int typeRefIndex = 0; typeRefIndex < package.TypeReferences.Count; typeRefIndex++) {
|
||||
var typeRef = Package.TypeReferences[typeRefIndex];
|
||||
var referencedType = resolveTypeReference(typeRef);
|
||||
|
||||
TypesByReferenceIndex[typeRefIndex] = referencedType;
|
||||
}
|
||||
}
|
||||
|
||||
private TypeInfo resolveTypeReference(Il2CppType typeRef) {
|
||||
TypeInfo underlyingType;
|
||||
|
||||
switch (usage.type) {
|
||||
switch (typeRef.type) {
|
||||
// Classes defined in the metadata (reference to a TypeDef)
|
||||
case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
|
||||
case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
|
||||
// Classes defined in the metadata
|
||||
underlyingType = TypesByDefinitionIndex[usage.datapoint]; // klassIndex
|
||||
underlyingType = TypesByDefinitionIndex[typeRef.datapoint]; // klassIndex
|
||||
break;
|
||||
|
||||
// Constructed types
|
||||
case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
|
||||
case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY:
|
||||
case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY:
|
||||
case Il2CppTypeEnum.IL2CPP_TYPE_PTR:
|
||||
|
||||
// Generic type and generic method parameters
|
||||
case Il2CppTypeEnum.IL2CPP_TYPE_VAR:
|
||||
case Il2CppTypeEnum.IL2CPP_TYPE_MVAR:
|
||||
// Everything that requires special handling
|
||||
underlyingType = new TypeInfo(this, usage, memberType);
|
||||
|
||||
underlyingType = new TypeInfo(this, typeRef);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Primitive types
|
||||
underlyingType = GetTypeFromTypeEnum(usage.type);
|
||||
default:
|
||||
underlyingType = getTypeDefinitionFromTypeEnum(typeRef.type);
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a reference type if necessary
|
||||
return usage.byref ? underlyingType.MakeByRefType() : underlyingType;
|
||||
return typeRef.byref ? underlyingType.MakeByRefType() : underlyingType;
|
||||
}
|
||||
|
||||
// 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 (TypeReferences[typeUsageIndex] != null)
|
||||
return TypeReferences[typeUsageIndex];
|
||||
|
||||
var usage = Package.TypeReferences[typeUsageIndex];
|
||||
var newUsage = getNewTypeUsage(usage, memberType);
|
||||
|
||||
TypeReferences[typeUsageIndex] = newUsage;
|
||||
return newUsage;
|
||||
}
|
||||
|
||||
// Basic primitive types
|
||||
public TypeInfo GetTypeFromTypeEnum(Il2CppTypeEnum t) {
|
||||
// Basic primitive types are specified via a flag value
|
||||
private TypeInfo getTypeDefinitionFromTypeEnum(Il2CppTypeEnum t) {
|
||||
if ((int) t >= Il2CppConstants.FullNameTypeString.Count)
|
||||
return null;
|
||||
|
||||
@@ -107,16 +106,17 @@ namespace Il2CppInspector.Reflection
|
||||
}
|
||||
|
||||
// Type from a virtual address pointer
|
||||
// These are always nested types frorm usages within another type
|
||||
// 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 type = Package.BinaryImage.ReadMappedObject<Il2CppType>(ptr);
|
||||
var newUsage = getNewTypeUsage(type, MemberTypes.NestedType);
|
||||
var referencedType = resolveTypeReference(type);
|
||||
|
||||
TypesByVirtualAddress.TryAdd(ptr, newUsage);
|
||||
return newUsage;
|
||||
TypesByVirtualAddress.TryAdd(ptr, referencedType);
|
||||
return referencedType;
|
||||
}
|
||||
|
||||
// The attribute index is an index into AttributeTypeRanges, each of which is a start-end range index into AttributeTypeIndices, each of which is a TypeIndex
|
||||
@@ -131,12 +131,12 @@ namespace Il2CppInspector.Reflection
|
||||
return index;
|
||||
}
|
||||
|
||||
// Get the name of a metadata usage
|
||||
// Get the name of a metadata typeRef
|
||||
public string GetMetadataUsageName(MetadataUsage usage) {
|
||||
switch (usage.Type) {
|
||||
case MetadataUsageType.TypeInfo:
|
||||
case MetadataUsageType.Type:
|
||||
var type = GetTypeFromUsage(usage.SourceIndex);
|
||||
var type = TypesByReferenceIndex[usage.SourceIndex];
|
||||
return type.Name;
|
||||
|
||||
case MetadataUsageType.MethodDef:
|
||||
@@ -145,7 +145,7 @@ namespace Il2CppInspector.Reflection
|
||||
|
||||
case MetadataUsageType.FieldInfo:
|
||||
var fieldRef = Package.FieldRefs[usage.SourceIndex];
|
||||
type = GetTypeFromUsage(fieldRef.typeIndex);
|
||||
type = TypesByReferenceIndex[fieldRef.typeIndex];
|
||||
var field = type.DeclaredFields.First(f => f.Index == type.Definition.fieldStart + fieldRef.fieldIndex);
|
||||
return $"{type.Name}.{field.Name}";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
@@ -17,8 +17,8 @@ namespace Il2CppInspector.Reflection
|
||||
public ParameterInfo ReturnParameter { get; }
|
||||
|
||||
// Return type of the method
|
||||
private readonly int returnTypeUsage;
|
||||
public TypeInfo ReturnType => Assembly.Model.GetTypeFromUsage(returnTypeUsage, MemberTypes.TypeInfo);
|
||||
private readonly int returnTypeReference;
|
||||
public TypeInfo ReturnType => Assembly.Model.TypesByReferenceIndex[returnTypeReference];
|
||||
|
||||
public override bool RequiresUnsafeContext => base.RequiresUnsafeContext || ReturnType.RequiresUnsafeContext;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Il2CppInspector.Reflection
|
||||
|
||||
public MethodInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType) {
|
||||
// Add return parameter
|
||||
returnTypeUsage = Definition.returnType;
|
||||
returnTypeReference = Definition.returnType;
|
||||
ReturnParameter = new ParameterInfo(pkg, -1, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ namespace Il2CppInspector.Reflection
|
||||
public string CSharpSafeName => Constants.Keywords.Contains(Name) ? "@" + Name : Name;
|
||||
|
||||
// Type of this parameter
|
||||
private readonly int paramTypeUsage;
|
||||
public TypeInfo ParameterType => DeclaringMethod.Assembly.Model.GetTypeFromUsage(paramTypeUsage, MemberTypes.TypeInfo);
|
||||
private readonly int paramTypeReference;
|
||||
public TypeInfo ParameterType => DeclaringMethod.Assembly.Model.TypesByReferenceIndex[paramTypeReference];
|
||||
|
||||
// Zero-indexed position of the parameter in parameter list
|
||||
public int Position { get; }
|
||||
@@ -56,7 +56,7 @@ namespace Il2CppInspector.Reflection
|
||||
|
||||
if (paramIndex == -1) {
|
||||
Position = -1;
|
||||
paramTypeUsage = declaringMethod.Definition.returnType;
|
||||
paramTypeReference = declaringMethod.Definition.returnType;
|
||||
Attributes |= ParameterAttributes.Retval;
|
||||
return;
|
||||
}
|
||||
@@ -69,8 +69,8 @@ namespace Il2CppInspector.Reflection
|
||||
Name = string.Format($"param_{Index:x8}");
|
||||
|
||||
Position = paramIndex - declaringMethod.Definition.parameterStart;
|
||||
paramTypeUsage = Definition.typeIndex;
|
||||
var paramType = pkg.TypeReferences[paramTypeUsage];
|
||||
paramTypeReference = Definition.typeIndex;
|
||||
var paramType = pkg.TypeReferences[paramTypeReference];
|
||||
|
||||
if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_HAS_DEFAULT) != 0)
|
||||
Attributes |= ParameterAttributes.HasDefault;
|
||||
|
||||
@@ -22,11 +22,11 @@ namespace Il2CppInspector.Reflection {
|
||||
public TypeAttributes Attributes { get; }
|
||||
|
||||
// Type that this type inherits from
|
||||
private readonly int baseTypeUsage = -1;
|
||||
private readonly int baseTypeReference = -1;
|
||||
|
||||
public TypeInfo BaseType => IsPointer? null :
|
||||
baseTypeUsage != -1?
|
||||
Assembly.Model.GetTypeFromUsage(baseTypeUsage, MemberTypes.TypeInfo)
|
||||
baseTypeReference != -1?
|
||||
Assembly.Model.TypesByReferenceIndex[baseTypeReference]
|
||||
: IsArray? Assembly.Model.TypesByFullName["System.Array"]
|
||||
: Namespace != "System" || BaseName != "Object" ? Assembly.Model.TypesByFullName["System.Object"]
|
||||
: null;
|
||||
@@ -109,7 +109,7 @@ namespace Il2CppInspector.Reflection {
|
||||
public TypeInfo[] GetGenericParameterConstraints() {
|
||||
var types = new TypeInfo[genericConstraintCount];
|
||||
for (int c = 0; c < genericConstraintCount; c++)
|
||||
types[c] = Assembly.Model.GetTypeFromUsage(Assembly.Model.Package.GenericConstraintIndices[genericConstraintIndex + c], MemberTypes.TypeInfo);
|
||||
types[c] = Assembly.Model.TypesByReferenceIndex[Assembly.Model.Package.GenericConstraintIndices[genericConstraintIndex + c]];
|
||||
return types;
|
||||
}
|
||||
|
||||
@@ -373,14 +373,14 @@ namespace Il2CppInspector.Reflection {
|
||||
// See: https://docs.microsoft.com/en-us/dotnet/api/system.type.haselementtype?view=netframework-4.8
|
||||
public bool HasElementType => ElementType != null;
|
||||
|
||||
private readonly int[] implementedInterfaceUsages;
|
||||
public IEnumerable<TypeInfo> ImplementedInterfaces => implementedInterfaceUsages.Select(x => Assembly.Model.GetTypeFromUsage(x, MemberTypes.TypeInfo));
|
||||
private readonly int[] implementedInterfaceReferences;
|
||||
public IEnumerable<TypeInfo> ImplementedInterfaces => implementedInterfaceReferences.Select(x => Assembly.Model.TypesByReferenceIndex[x]);
|
||||
|
||||
public bool IsAbstract => (Attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract;
|
||||
public bool IsArray { get; }
|
||||
public bool IsByRef { get; }
|
||||
public bool IsClass => (Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class;
|
||||
public bool IsEnum => enumUnderlyingTypeUsage != -1;
|
||||
public bool IsEnum => enumUnderlyingTypeReference != -1;
|
||||
public bool IsGenericParameter { get; }
|
||||
public bool IsGenericType { get; }
|
||||
public bool IsGenericTypeDefinition => genericArguments.Any() && genericArguments.All(a => a.IsGenericTypeParameter);
|
||||
@@ -422,21 +422,19 @@ namespace Il2CppInspector.Reflection {
|
||||
public string[] GetEnumNames() => IsEnum? DeclaredFields.Where(x => x.Name != "value__").Select(x => x.Name).ToArray() : throw new InvalidOperationException("Type is not an enumeration");
|
||||
|
||||
// The underlying type of an enumeration (int by default)
|
||||
private readonly int enumUnderlyingTypeUsage = -1;
|
||||
private readonly int enumUnderlyingTypeReference = -1;
|
||||
private TypeInfo enumUnderlyingType;
|
||||
|
||||
public TypeInfo GetEnumUnderlyingType() {
|
||||
if (!IsEnum)
|
||||
return null;
|
||||
enumUnderlyingType ??= Assembly.Model.GetTypeFromUsage(enumUnderlyingTypeUsage, MemberTypes.TypeInfo);
|
||||
enumUnderlyingType ??= Assembly.Model.TypesByReferenceIndex[enumUnderlyingTypeReference];
|
||||
return enumUnderlyingType;
|
||||
}
|
||||
|
||||
public Array GetEnumValues() => IsEnum? DeclaredFields.Where(x => x.Name != "value__").Select(x => x.DefaultValue).ToArray() : throw new InvalidOperationException("Type is not an enumeration");
|
||||
|
||||
// Initialize from specified type index in metadata
|
||||
|
||||
// Top-level types
|
||||
// Initialize type from TypeDef using specified index in metadata
|
||||
public TypeInfo(int typeIndex, Assembly owner) : base(owner) {
|
||||
var pkg = Assembly.Model.Package;
|
||||
|
||||
@@ -447,7 +445,7 @@ namespace Il2CppInspector.Reflection {
|
||||
|
||||
// Derived type?
|
||||
if (Definition.parentIndex >= 0)
|
||||
baseTypeUsage = Definition.parentIndex;
|
||||
baseTypeReference = Definition.parentIndex;
|
||||
|
||||
// Nested type?
|
||||
if (Definition.declaringTypeIndex >= 0) {
|
||||
@@ -501,18 +499,18 @@ namespace Il2CppInspector.Reflection {
|
||||
if ((Definition.flags & Il2CppConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
|
||||
Attributes |= TypeAttributes.Interface;
|
||||
|
||||
// Enumerations - bit 1 of bitfield indicates this (also the baseTypeUsage will be System.Enum)
|
||||
// Enumerations - bit 1 of bitfield indicates this (also the baseTypeReference will be System.Enum)
|
||||
if (((Definition.bitfield >> 1) & 1) == 1)
|
||||
enumUnderlyingTypeUsage = Definition.elementTypeIndex;
|
||||
enumUnderlyingTypeReference = Definition.elementTypeIndex;
|
||||
|
||||
// Pass-by-reference type
|
||||
// NOTE: This should actually always evaluate to false in the current implementation
|
||||
IsByRef = Index == Definition.byrefTypeIndex;
|
||||
|
||||
// Add all implemented interfaces
|
||||
implementedInterfaceUsages = new int[Definition.interfaces_count];
|
||||
implementedInterfaceReferences = new int[Definition.interfaces_count];
|
||||
for (var i = 0; i < Definition.interfaces_count; i++)
|
||||
implementedInterfaceUsages[i] = pkg.InterfaceUsageIndices[Definition.interfacesStart + i];
|
||||
implementedInterfaceReferences[i] = pkg.InterfaceUsageIndices[Definition.interfacesStart + i];
|
||||
|
||||
// Add all nested types
|
||||
declaredNestedTypes = new int[Definition.nested_type_count];
|
||||
@@ -575,14 +573,20 @@ namespace Il2CppInspector.Reflection {
|
||||
DeclaredEvents.Add(new EventInfo(pkg, e, this));
|
||||
}
|
||||
|
||||
// Initialize type from type reference
|
||||
// Initialize type from type reference (TypeRef)
|
||||
// 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) {
|
||||
var image = model.Package.BinaryImage;
|
||||
|
||||
// Open and closed generic types
|
||||
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST) {
|
||||
var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.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;
|
||||
|
||||
var genericTypeDef = model.TypesByDefinitionIndex[generic.typeDefinitionIndex];
|
||||
|
||||
Assembly = genericTypeDef.Assembly;
|
||||
@@ -592,12 +596,12 @@ namespace Il2CppInspector.Reflection {
|
||||
|
||||
// Derived type?
|
||||
if (genericTypeDef.Definition.parentIndex >= 0)
|
||||
baseTypeUsage = genericTypeDef.Definition.parentIndex;
|
||||
baseTypeReference = genericTypeDef.Definition.parentIndex;
|
||||
|
||||
// Nested type?
|
||||
if (genericTypeDef.Definition.declaringTypeIndex >= 0) {
|
||||
declaringTypeDefinitionIndex = (int)model.Package.TypeReferences[genericTypeDef.Definition.declaringTypeIndex].datapoint;
|
||||
MemberType = memberType | MemberTypes.NestedType;
|
||||
MemberType |= MemberTypes.NestedType;
|
||||
}
|
||||
|
||||
IsGenericType = true;
|
||||
@@ -665,11 +669,11 @@ namespace Il2CppInspector.Reflection {
|
||||
|
||||
// Derived type?
|
||||
if (ownerType.Definition.parentIndex >= 0)
|
||||
baseTypeUsage = ownerType.Definition.parentIndex;
|
||||
baseTypeReference = ownerType.Definition.parentIndex;
|
||||
|
||||
// Nested type always - sets DeclaringType used below
|
||||
declaringTypeDefinitionIndex = ownerType.Index;
|
||||
MemberType = memberType | MemberTypes.NestedType;
|
||||
MemberType |= MemberTypes.NestedType;
|
||||
|
||||
// All generic method type parameters have a declared method
|
||||
if (container.is_method == 1)
|
||||
|
||||
Reference in New Issue
Block a user