diff --git a/Il2CppInspector/Reflection/MethodBase.cs b/Il2CppInspector/Reflection/MethodBase.cs index 8fa424d..d0b9876 100644 --- a/Il2CppInspector/Reflection/MethodBase.cs +++ b/Il2CppInspector/Reflection/MethodBase.cs @@ -13,6 +13,11 @@ namespace Il2CppInspector.Reflection { public abstract class MethodBase : MemberInfo { + // IL2CPP-specific data + public Il2CppMethodDefinition Definition { get; } + public int Index { get; } + public ulong VirtualAddress { get; } + // Information/flags about the method public MethodAttributes Attributes { get; protected set; } @@ -41,7 +46,73 @@ namespace Il2CppInspector.Reflection // TODO: GetMethodBody() - protected MethodBase(TypeInfo declaringType) : base(declaringType) { } + protected MethodBase(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(declaringType) { + Definition = pkg.Methods[methodIndex]; + Index = methodIndex; + Name = pkg.Strings[Definition.nameIndex]; + + // Find method pointer + if (Definition.methodIndex >= 0) { + + // Global method pointer array + if (pkg.Version <= 24.1) { + VirtualAddress = pkg.GlobalMethodPointers[Definition.methodIndex]; + } + + // Per-module method pointer array uses the bottom 24 bits of the method's metadata token + // Derived from il2cpp::vm::MetadataCache::GetMethodPointer + else { + var method = (Definition.token & 0xffffff); + if (method != 0) { + // In the event of an exception, the method pointer is not set in the file + // This probably means it has been optimized away by the compiler, or is an unused generic method + try { + pkg.BinaryImage.Position = pkg.BinaryImage.MapVATR(Assembly.Module.methodPointers + (ulong)((method - 1) * (pkg.BinaryImage.Bits / 8))); + VirtualAddress = (ulong)pkg.BinaryImage.ReadWord(); + } + catch (Exception) { } + } + } + + // Remove ARM Thumb marker LSB if necessary + VirtualAddress &= 0xffff_ffff_ffff_fffe; + } + + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PRIVATE) + Attributes |= MethodAttributes.Private; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PUBLIC) + Attributes |= MethodAttributes.Public; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAM_AND_ASSEM) + Attributes |= MethodAttributes.FamANDAssem; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_ASSEM) + Attributes |= MethodAttributes.Assembly; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAMILY) + Attributes |= MethodAttributes.Family; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAM_OR_ASSEM) + Attributes |= MethodAttributes.FamORAssem; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_VIRTUAL) != 0) + Attributes |= MethodAttributes.Virtual; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_ABSTRACT) != 0) + Attributes |= MethodAttributes.Abstract; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_STATIC) != 0) + Attributes |= MethodAttributes.Static; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_FINAL) != 0) + Attributes |= MethodAttributes.Final; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_HIDE_BY_SIG) != 0) + Attributes |= MethodAttributes.HideBySig; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_NEW_SLOT) + Attributes |= MethodAttributes.NewSlot; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_PINVOKE_IMPL) != 0) + Attributes |= MethodAttributes.PinvokeImpl; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_SPECIAL_NAME) != 0) + Attributes |= MethodAttributes.SpecialName; + if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_UNMANAGED_EXPORT) != 0) + Attributes |= MethodAttributes.UnmanagedExport; + + // Add arguments + for (var p = Definition.parameterStart; p < Definition.parameterStart + Definition.parameterCount; p++) + DeclaredParameters.Add(new ParameterInfo(pkg, p, this)); + } public string GetModifierString() { // Interface methods and properties have no visible modifiers (they are always declared 'public abstract') diff --git a/Il2CppInspector/Reflection/MethodInfo.cs b/Il2CppInspector/Reflection/MethodInfo.cs index 0986100..72b6a9f 100644 --- a/Il2CppInspector/Reflection/MethodInfo.cs +++ b/Il2CppInspector/Reflection/MethodInfo.cs @@ -4,7 +4,6 @@ All rights reserved. */ -using System; using System.Linq; using System.Reflection; @@ -12,12 +11,6 @@ namespace Il2CppInspector.Reflection { public class MethodInfo : MethodBase { - // IL2CPP-specific data - public Il2CppMethodDefinition Definition { get; } - public int Index { get; } - public ulong VirtualAddress { get; } - public bool HasBody { get; } - public override MemberTypes MemberType => MemberTypes.Method; // Info about the return parameter @@ -29,78 +22,10 @@ namespace Il2CppInspector.Reflection // TODO: ReturnTypeCustomAttributes - public MethodInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : - base(declaringType) { - Definition = pkg.Methods[methodIndex]; - Index = methodIndex; - Name = pkg.Strings[Definition.nameIndex]; - - // Find method pointer - if (Definition.methodIndex >= 0) { - - // Global method pointer array - if (pkg.Version <= 24.1) { - VirtualAddress = pkg.GlobalMethodPointers[Definition.methodIndex]; - } - - // Per-module method pointer array uses the bottom 24 bits of the method's metadata token - // Derived from il2cpp::vm::MetadataCache::GetMethodPointer - else { - var method = (Definition.token & 0xffffff); - if (method != 0) { - // In the event of an exception, the method pointer is not set in the file - // This probably means it has been optimized away by the compiler, or is an unused generic method - try { - pkg.BinaryImage.Position = pkg.BinaryImage.MapVATR(Assembly.Module.methodPointers + (ulong) ((method - 1) * (pkg.BinaryImage.Bits / 8))); - VirtualAddress = (ulong) pkg.BinaryImage.ReadWord(); - } catch (Exception) { } - } - } - - // Remove ARM Thumb marker LSB if necessary - VirtualAddress &= 0xffff_ffff_ffff_fffe; - - HasBody = true; - } - - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PRIVATE) - Attributes |= MethodAttributes.Private; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PUBLIC) - Attributes |= MethodAttributes.Public; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAM_AND_ASSEM) - Attributes |= MethodAttributes.FamANDAssem; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_ASSEM) - Attributes |= MethodAttributes.Assembly; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAMILY) - Attributes |= MethodAttributes.Family; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAM_OR_ASSEM) - Attributes |= MethodAttributes.FamORAssem; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_VIRTUAL) != 0) - Attributes |= MethodAttributes.Virtual; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_ABSTRACT) != 0) - Attributes |= MethodAttributes.Abstract; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_STATIC) != 0) - Attributes |= MethodAttributes.Static; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_FINAL) != 0) - Attributes |= MethodAttributes.Final; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_HIDE_BY_SIG) != 0) - Attributes |= MethodAttributes.HideBySig; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_NEW_SLOT) - Attributes |= MethodAttributes.NewSlot; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_PINVOKE_IMPL) != 0) - Attributes |= MethodAttributes.PinvokeImpl; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_SPECIAL_NAME) != 0) - Attributes |= MethodAttributes.SpecialName; - if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_UNMANAGED_EXPORT) != 0) - Attributes |= MethodAttributes.UnmanagedExport; - + public MethodInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType) { // Add return parameter returnType = pkg.TypeUsages[Definition.returnType]; ReturnParameter = new ParameterInfo(pkg, -1, this); - - // Add arguments - for (var p = Definition.parameterStart; p < Definition.parameterStart + Definition.parameterCount; p++) - DeclaredParameters.Add(new ParameterInfo(pkg, p, this)); } public override string ToString() => ReturnType.Name + " " + Name + "(" + string.Join(", ", DeclaredParameters.Select(x => x.ParameterType.Name)) + ")"; diff --git a/Il2CppInspector/Reflection/ParameterInfo.cs b/Il2CppInspector/Reflection/ParameterInfo.cs index 5fd67f7..a411802 100644 --- a/Il2CppInspector/Reflection/ParameterInfo.cs +++ b/Il2CppInspector/Reflection/ParameterInfo.cs @@ -41,7 +41,7 @@ namespace Il2CppInspector.Reflection public int Position { get; private set; } // Create a parameter. Specify paramIndex == -1 for a return type parameter - public ParameterInfo(Il2CppInspector pkg, int paramIndex, MethodInfo declaringMethod) { + public ParameterInfo(Il2CppInspector pkg, int paramIndex, MethodBase declaringMethod) { Member = declaringMethod; if (paramIndex == -1) { diff --git a/Il2CppInspector/Reflection/ReflectionClasses.cs b/Il2CppInspector/Reflection/ReflectionClasses.cs index 5011ead..db95245 100644 --- a/Il2CppInspector/Reflection/ReflectionClasses.cs +++ b/Il2CppInspector/Reflection/ReflectionClasses.cs @@ -1,5 +1,5 @@ /* - Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com All rights reserved. */ @@ -10,11 +10,15 @@ namespace Il2CppInspector.Reflection { public class ConstructorInfo : MethodBase { - // TODO - public override MemberTypes MemberType => MemberTypes.Constructor | MemberTypes.Method; + // IL names of constructor and static constructor + public static readonly string ConstructorName = ".ctor"; - public ConstructorInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : - base(declaringType) { } + public static readonly string TypeConstructorName = ".cctor"; + + // TODO + public override MemberTypes MemberType => MemberTypes.Constructor; + + public ConstructorInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType) { } } public class CustomAttributeData