Model: Handle generic methods and set DeclaringMethod
This commit is contained in:
@@ -24,12 +24,16 @@ namespace Il2CppInspector.Reflection
|
|||||||
// List of type usages that are initialized via pointers in the image
|
// List of type usages that are initialized via pointers in the image
|
||||||
public Dictionary<ulong, TypeInfo> TypesByVirtualAddress { get; } = new Dictionary<ulong, TypeInfo>();
|
public Dictionary<ulong, TypeInfo> TypesByVirtualAddress { get; } = new Dictionary<ulong, TypeInfo>();
|
||||||
|
|
||||||
|
// List of all methods ordered by their MethodDefinitionIndex
|
||||||
|
public MethodBase[] MethodsByDefinitionIndex { get; }
|
||||||
|
|
||||||
// List of all types
|
// List of all types
|
||||||
|
|
||||||
public Il2CppModel(Il2CppInspector package) {
|
public Il2CppModel(Il2CppInspector package) {
|
||||||
Package = package;
|
Package = package;
|
||||||
TypesByDefinitionIndex = new TypeInfo[package.TypeDefinitions.Length];
|
TypesByDefinitionIndex = new TypeInfo[package.TypeDefinitions.Length];
|
||||||
TypesByUsageIndex = new TypeInfo[package.TypeUsages.Count];
|
TypesByUsageIndex = new TypeInfo[package.TypeUsages.Count];
|
||||||
|
MethodsByDefinitionIndex = new MethodBase[package.Methods.Length];
|
||||||
|
|
||||||
// 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++)
|
||||||
|
|||||||
@@ -22,11 +22,12 @@ namespace Il2CppInspector.Reflection
|
|||||||
// Information/flags about the method
|
// Information/flags about the method
|
||||||
public MethodAttributes Attributes { get; protected set; }
|
public MethodAttributes Attributes { get; protected set; }
|
||||||
|
|
||||||
// True if the type contains unresolved generic type parameters
|
// True if the method contains unresolved generic type parameters
|
||||||
public bool ContainsGenericParameters => throw new NotImplementedException();
|
public bool ContainsGenericParameters { get; }
|
||||||
|
|
||||||
// TODO: Custom attribute stuff
|
// TODO: Custom attribute stuff
|
||||||
|
|
||||||
|
public List<TypeInfo> GenericTypeParameters { get; } // System.Reflection.MethodInfo.GetGenericArguments()
|
||||||
public List<ParameterInfo> DeclaredParameters { get; } = new List<ParameterInfo>();
|
public List<ParameterInfo> DeclaredParameters { get; } = new List<ParameterInfo>();
|
||||||
|
|
||||||
public bool IsAbstract => (Attributes & MethodAttributes.Abstract) == MethodAttributes.Abstract;
|
public bool IsAbstract => (Attributes & MethodAttributes.Abstract) == MethodAttributes.Abstract;
|
||||||
@@ -36,8 +37,8 @@ namespace Il2CppInspector.Reflection
|
|||||||
public bool IsFamilyAndAssembly => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem;
|
public bool IsFamilyAndAssembly => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem;
|
||||||
public bool IsFamilyOrAssembly => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;
|
public bool IsFamilyOrAssembly => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;
|
||||||
public bool IsFinal => (Attributes & MethodAttributes.Final) == MethodAttributes.Final;
|
public bool IsFinal => (Attributes & MethodAttributes.Final) == MethodAttributes.Final;
|
||||||
public bool IsGenericMethod => throw new NotImplementedException();
|
public bool IsGenericMethod { get; }
|
||||||
public bool IsGenericMethodDefinition => throw new NotImplementedException();
|
public bool IsGenericMethodDefinition { get; }
|
||||||
public bool IsHideBySig => (Attributes & MethodAttributes.HideBySig) == MethodAttributes.HideBySig;
|
public bool IsHideBySig => (Attributes & MethodAttributes.HideBySig) == MethodAttributes.HideBySig;
|
||||||
public bool IsPrivate => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
|
public bool IsPrivate => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
|
||||||
public bool IsPublic => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
|
public bool IsPublic => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
|
||||||
@@ -59,6 +60,24 @@ namespace Il2CppInspector.Reflection
|
|||||||
// Find method pointer
|
// Find method pointer
|
||||||
VirtualAddress = pkg.GetMethodPointer(Assembly.Module, Definition);
|
VirtualAddress = pkg.GetMethodPointer(Assembly.Module, Definition);
|
||||||
|
|
||||||
|
// Add to global method definition list
|
||||||
|
Assembly.Model.MethodsByDefinitionIndex[Index] = this;
|
||||||
|
|
||||||
|
// Generic method definition?
|
||||||
|
if (Definition.genericContainerIndex >= 0) {
|
||||||
|
IsGenericMethod = true;
|
||||||
|
IsGenericMethodDefinition = true; // TODO: Only if all of the parameters are unresolved generic type parameters
|
||||||
|
ContainsGenericParameters = true;
|
||||||
|
|
||||||
|
// Store the generic type parameters for later instantiation
|
||||||
|
var container = pkg.GenericContainers[Definition.genericContainerIndex];
|
||||||
|
|
||||||
|
GenericTypeParameters = pkg.GenericParameters.Skip((int)container.genericParameterStart).Take(container.type_argc).Select(p => new TypeInfo(this, p)).ToList();
|
||||||
|
|
||||||
|
// TODO: Constraints
|
||||||
|
// TODO: Attributes
|
||||||
|
}
|
||||||
|
|
||||||
// Set method attributes
|
// Set method attributes
|
||||||
if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PRIVATE)
|
if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PRIVATE)
|
||||||
Attributes |= MethodAttributes.Private;
|
Attributes |= MethodAttributes.Private;
|
||||||
@@ -142,6 +161,9 @@ namespace Il2CppInspector.Reflection
|
|||||||
public string GetParametersString() =>
|
public string GetParametersString() =>
|
||||||
string.Join(", ", DeclaredParameters.Select(p => $"{p.GetModifierString()}{p.ParameterType.CSharpName} {p.Name}"));
|
string.Join(", ", DeclaredParameters.Select(p => $"{p.GetModifierString()}{p.ParameterType.CSharpName} {p.Name}"));
|
||||||
|
|
||||||
|
public string GetTypeParametersString() => GenericTypeParameters == null? "" :
|
||||||
|
"<" + string.Join(", ", GenericTypeParameters.Select(p => p.CSharpName)) + ">";
|
||||||
|
|
||||||
// List of operator overload metadata names
|
// List of operator overload metadata names
|
||||||
// https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/operator-overloads
|
// https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/operator-overloads
|
||||||
public static Dictionary<string, string> OperatorMethodNames = new Dictionary<string, string> {
|
public static Dictionary<string, string> OperatorMethodNames = new Dictionary<string, string> {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace Il2CppInspector.Reflection
|
|||||||
ReturnParameter = new ParameterInfo(pkg, -1, this);
|
ReturnParameter = new ParameterInfo(pkg, -1, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Generic arguments (and on ConstructorInfo)
|
||||||
public override string ToString() => ReturnType.Name + " " + Name + "(" + string.Join(", ", DeclaredParameters.Select(x => x.ParameterType.Name)) + ")";
|
public override string ToString() => ReturnType.Name + " " + Name + "(" + string.Join(", ", DeclaredParameters.Select(x => x.ParameterType.Name)) + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,6 +30,11 @@ namespace Il2CppInspector.Reflection {
|
|||||||
// 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; }
|
||||||
|
|
||||||
|
public string BaseName => base.Name;
|
||||||
|
|
||||||
|
// Get rid of generic backticks
|
||||||
|
public string UnmangledBaseName => base.Name.IndexOf("`", StringComparison.Ordinal) == -1 ? base.Name : base.Name.Remove(base.Name.IndexOf("`", StringComparison.Ordinal));
|
||||||
|
|
||||||
// C# colloquial name of the type (if available)
|
// C# colloquial name of the type (if available)
|
||||||
public string CSharpName {
|
public string CSharpName {
|
||||||
get {
|
get {
|
||||||
@@ -46,6 +51,14 @@ namespace Il2CppInspector.Reflection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// C# name as it would be written in a type declaration
|
||||||
|
public string CSharpTypeDeclarationName =>
|
||||||
|
(IsPointer ? "void *" : "")
|
||||||
|
+ (base.Name.IndexOf("`", StringComparison.Ordinal) == -1 ? base.Name : base.Name.Remove(base.Name.IndexOf("`", StringComparison.Ordinal)))
|
||||||
|
+ (GenericTypeParameters != null ? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.Name)) + ">" : "")
|
||||||
|
+ (GenericTypeArguments != null ? "<" + string.Join(", ", GenericTypeArguments.Select(x => x.Name)) + ">" : "")
|
||||||
|
+ (IsArray ? "[]" : "");
|
||||||
|
|
||||||
public List<ConstructorInfo> DeclaredConstructors { get; } = new List<ConstructorInfo>();
|
public List<ConstructorInfo> DeclaredConstructors { get; } = new List<ConstructorInfo>();
|
||||||
public List<EventInfo> DeclaredEvents { get; } = new List<EventInfo>();
|
public List<EventInfo> DeclaredEvents { get; } = new List<EventInfo>();
|
||||||
public List<FieldInfo> DeclaredFields { get; } = new List<FieldInfo>();
|
public List<FieldInfo> DeclaredFields { get; } = new List<FieldInfo>();
|
||||||
@@ -58,7 +71,9 @@ namespace Il2CppInspector.Reflection {
|
|||||||
public List<PropertyInfo> DeclaredProperties { get; } = new List<PropertyInfo>();
|
public List<PropertyInfo> DeclaredProperties { get; } = new List<PropertyInfo>();
|
||||||
|
|
||||||
// Method that the type is declared in if this is a type parameter of a generic method
|
// Method that the type is declared in if this is a type parameter of a generic method
|
||||||
public MethodBase DeclaringMethod => null; // TODO: Implement for methods
|
public MethodBase DeclaringMethod;
|
||||||
|
|
||||||
|
// IsGenericTypeParameter and IsGenericMethodParameter from https://github.com/dotnet/corefx/issues/23883
|
||||||
public bool IsGenericTypeParameter => IsGenericParameter && DeclaringMethod == null;
|
public bool IsGenericTypeParameter => IsGenericParameter && DeclaringMethod == null;
|
||||||
public bool IsGenericMethodParameter => IsGenericParameter && DeclaringMethod != null;
|
public bool IsGenericMethodParameter => IsGenericParameter && DeclaringMethod != null;
|
||||||
|
|
||||||
@@ -127,17 +142,6 @@ namespace Il2CppInspector.Reflection {
|
|||||||
// May get overridden by Il2CppType-based constructor below
|
// May get overridden by Il2CppType-based constructor below
|
||||||
public override MemberTypes MemberType { get; } = MemberTypes.TypeInfo;
|
public override MemberTypes MemberType { get; } = MemberTypes.TypeInfo;
|
||||||
|
|
||||||
public string BaseName => base.Name;
|
|
||||||
|
|
||||||
public override string Name {
|
|
||||||
get => (IsPointer ? "void *" : "")
|
|
||||||
+ (base.Name.IndexOf("`", StringComparison.Ordinal) == -1? base.Name : base.Name.Remove(base.Name.IndexOf("`", StringComparison.Ordinal)))
|
|
||||||
+ (GenericTypeParameters != null? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.Name)) + ">" : "")
|
|
||||||
+ (GenericTypeArguments != null ? "<" + string.Join(", ", GenericTypeArguments.Select(x => x.Name)) + ">" : "")
|
|
||||||
+ (IsArray ? "[]" : "");
|
|
||||||
protected set => base.Name = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string @namespace;
|
private string @namespace;
|
||||||
public string Namespace {
|
public string Namespace {
|
||||||
get => !string.IsNullOrEmpty(@namespace) ? @namespace : DeclaringType?.Namespace ?? "";
|
get => !string.IsNullOrEmpty(@namespace) ? @namespace : DeclaringType?.Namespace ?? "";
|
||||||
@@ -179,7 +183,7 @@ namespace Il2CppInspector.Reflection {
|
|||||||
MemberType |= MemberTypes.NestedType;
|
MemberType |= MemberTypes.NestedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic type?
|
// Generic type definition?
|
||||||
if (Definition.genericContainerIndex >= 0) {
|
if (Definition.genericContainerIndex >= 0) {
|
||||||
IsGenericType = true;
|
IsGenericType = true;
|
||||||
IsGenericParameter = false;
|
IsGenericParameter = false;
|
||||||
@@ -358,6 +362,10 @@ namespace Il2CppInspector.Reflection {
|
|||||||
declaringTypeDefinitionIndex = ownerType.Index;
|
declaringTypeDefinitionIndex = ownerType.Index;
|
||||||
MemberType = memberType | MemberTypes.NestedType;
|
MemberType = memberType | MemberTypes.NestedType;
|
||||||
|
|
||||||
|
// All generic method type parameters have a declared method
|
||||||
|
if (container.is_method == 1)
|
||||||
|
DeclaringMethod = model.MethodsByDefinitionIndex[container.ownerIndex];
|
||||||
|
|
||||||
IsGenericParameter = true;
|
IsGenericParameter = true;
|
||||||
ContainsGenericParameters = true;
|
ContainsGenericParameters = true;
|
||||||
IsGenericType = false;
|
IsGenericType = false;
|
||||||
@@ -369,7 +377,7 @@ namespace Il2CppInspector.Reflection {
|
|||||||
IsPointer = (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_PTR);
|
IsPointer = (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_PTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a type that is a generic parameter
|
// Initialize a type that is a generic parameter of a generic type
|
||||||
// See: https://docs.microsoft.com/en-us/dotnet/api/system.type.isgenerictype?view=netframework-4.8
|
// See: https://docs.microsoft.com/en-us/dotnet/api/system.type.isgenerictype?view=netframework-4.8
|
||||||
public TypeInfo(TypeInfo declaringType, Il2CppGenericParameter param) : base(declaringType) {
|
public TypeInfo(TypeInfo declaringType, Il2CppGenericParameter param) : base(declaringType) {
|
||||||
// Same visibility attributes as declaring type
|
// Same visibility attributes as declaring type
|
||||||
@@ -389,5 +397,10 @@ namespace Il2CppInspector.Reflection {
|
|||||||
IsGenericTypeDefinition = false;
|
IsGenericTypeDefinition = false;
|
||||||
ContainsGenericParameters = true;
|
ContainsGenericParameters = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize a type that is a generic parameter of a generic method
|
||||||
|
public TypeInfo(MethodBase declaringMethod, Il2CppGenericParameter param) : this(declaringMethod.DeclaringType, param) {
|
||||||
|
DeclaringMethod = declaringMethod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user