diff --git a/Il2CppInspector.Common/IL2CPP/CustomAttributeDataReader.cs b/Il2CppInspector.Common/IL2CPP/CustomAttributeDataReader.cs index 8901ba8..423646a 100644 --- a/Il2CppInspector.Common/IL2CPP/CustomAttributeDataReader.cs +++ b/Il2CppInspector.Common/IL2CPP/CustomAttributeDataReader.cs @@ -4,6 +4,8 @@ using System.Diagnostics; using System.IO; using System.Linq; using dnlib.DotNet; +using Il2CppInspector.Next.BinaryMetadata; +using Il2CppInspector.Next.Metadata; using Il2CppInspector.Reflection; using Il2CppInspector.Utils; using NoisyCowStudios.Bin2Object; @@ -143,7 +145,7 @@ namespace Il2CppInspector } private TypeInfo ConvertTypeDef(Il2CppTypeDefinition typeDef, Il2CppTypeEnum type) - => typeDef == null + => typeDef.IsValid ? _assembly.Model.GetTypeDefinitionFromTypeEnum(type) : _assembly.Model.TypesByDefinitionIndex[Array.IndexOf(_inspector.TypeDefinitions, typeDef)]; diff --git a/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs b/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs index 586a3e3..16fd620 100644 --- a/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs +++ b/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs @@ -13,6 +13,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; +using Il2CppInspector.Next.BinaryMetadata; using VersionedSerialization; namespace Il2CppInspector @@ -284,20 +285,20 @@ namespace Il2CppInspector // genericAdjustorThunks was inserted before invokerPointersCount in 24.5 and 27.1 // pointer expected if we need to bump version - if (Image.Version == MetadataVersions.V244 && CodeRegistration.invokerPointersCount > 0x50000) + if (Image.Version == MetadataVersions.V244 && CodeRegistration.InvokerPointersCount > 0x50000) { Image.Version = MetadataVersions.V245; CodeRegistration = Image.ReadMappedObject(codeRegistration); } - if (Image.Version == MetadataVersions.V244 && CodeRegistration.reversePInvokeWrapperCount > 0x50000) { + if (Image.Version == MetadataVersions.V244 && CodeRegistration.ReversePInvokeWrapperCount > 0x50000) { Image.Version = MetadataVersions.V245; codeRegistration -= 1 * pointerSize; CodeRegistration = Image.ReadMappedObject(codeRegistration); } if ((Image.Version == MetadataVersions.V290 || Image.Version == MetadataVersions.V310) && - (long)CodeRegistration.genericMethodPointersCount - MetadataRegistration.genericMethodTableCount > 0x10000) + (long)CodeRegistration.GenericMethodPointersCount - MetadataRegistration.GenericMethodTableCount > 0x10000) { Image.Version = new StructVersion(Image.Version.Major, 1, Image.Version.Tag); codeRegistration -= 2 * pointerSize; @@ -316,16 +317,16 @@ namespace Il2CppInspector * typeRefPointers must be a series of pointers in __const * MethodInvokePointers must be a series of pointers in __text or .text, and in sequential order */ - if ((Metadata != null && Metadata.Types.Length != MetadataRegistration.typeDefinitionsSizesCount) - || CodeRegistration.reversePInvokeWrapperCount > 0x10000 - || CodeRegistration.unresolvedVirtualCallCount > 0x4000 // >= 22 - || CodeRegistration.interopDataCount > 0x1000 // >= 23 - || (Image.Version <= MetadataVersions.V241 && CodeRegistration.invokerPointersCount > CodeRegistration.methodPointersCount)) + if ((Metadata != null && Metadata.Types.Length != MetadataRegistration.TypeDefinitionsSizesCount) + || CodeRegistration.ReversePInvokeWrapperCount > 0x10000 + || CodeRegistration.UnresolvedVirtualCallCount > 0x4000 // >= 22 + || CodeRegistration.InteropDataCount > 0x1000 // >= 23 + || (Image.Version <= MetadataVersions.V241 && CodeRegistration.InvokerPointersCount > CodeRegistration.MethodPointersCount)) throw new NotSupportedException("The detected Il2CppCodeRegistration / Il2CppMetadataRegistration structs do not pass validation. This may mean that their fields have been re-ordered as a form of obfuscation and Il2CppInspector has not been able to restore the original order automatically. Consider re-ordering the fields in Il2CppBinaryClasses.cs and try again."); // The global method pointer list was deprecated in v24.2 in favour of Il2CppCodeGenModule if (Image.Version <= MetadataVersions.V241) - GlobalMethodPointers = Image.ReadMappedArray(CodeRegistration.pmethodPointers, (int) CodeRegistration.methodPointersCount); + GlobalMethodPointers = Image.ReadMappedArray(CodeRegistration.MethodPointers, (int) CodeRegistration.MethodPointersCount); // After v24 method pointers and RGCTX data were stored in Il2CppCodeGenModules if (Image.Version >= MetadataVersions.V242) { @@ -333,19 +334,19 @@ namespace Il2CppInspector // In v24.3, windowsRuntimeFactoryTable collides with codeGenModules. So far no samples have had windowsRuntimeFactoryCount > 0; // if this changes we'll have to get smarter about disambiguating these two. - if (CodeRegistration.codeGenModulesCount == 0) { + if (CodeRegistration.CodeGenModulesCount == 0) { Image.Version = MetadataVersions.V243; CodeRegistration = Image.ReadMappedObject(codeRegistration); } // Array of pointers to Il2CppCodeGenModule - var codeGenModulePointers = Image.ReadMappedArray(CodeRegistration.pcodeGenModules, (int) CodeRegistration.codeGenModulesCount); - var modules = Image.ReadMappedObjectPointerArray(CodeRegistration.pcodeGenModules, (int) CodeRegistration.codeGenModulesCount); + var codeGenModulePointers = Image.ReadMappedArray(CodeRegistration.CodeGenModules, (int) CodeRegistration.CodeGenModulesCount); + var modules = Image.ReadMappedObjectPointerArray(CodeRegistration.CodeGenModules, (int) CodeRegistration.CodeGenModulesCount); foreach (var mp in modules.Zip(codeGenModulePointers, (m, p) => new { Module = m, Pointer = p })) { var module = mp.Module; - var name = Image.ReadMappedNullTerminatedString(module.moduleName); + var name = Image.ReadMappedNullTerminatedString(module.ModuleName); Modules.Add(name, module); CodeGenModulePointers.Add(name, mp.Pointer); @@ -354,13 +355,13 @@ namespace Il2CppInspector // the entire method pointer array will be NULL values, causing the methodPointer to be mapped to .bss // and therefore out of scope of the binary image try { - ModuleMethodPointers.Add(module, Image.ReadMappedArray(module.methodPointers, (int) module.methodPointerCount)); + ModuleMethodPointers.Add(module, Image.ReadMappedArray(module.MethodPointers, (int) module.MethodPointerCount)); } catch (InvalidOperationException) { - ModuleMethodPointers.Add(module, new ulong[module.methodPointerCount]); + ModuleMethodPointers.Add(module, new ulong[module.MethodPointerCount]); } // Read method invoker pointer indices - one per method - MethodInvokerIndices.Add(module, Image.ReadMappedArray(module.invokerIndices, (int) module.methodPointerCount)); + MethodInvokerIndices.Add(module, Image.ReadMappedArray(module.InvokerIndices, (int) module.MethodPointerCount)); } } @@ -371,7 +372,7 @@ namespace Il2CppInspector // Some variants of 21 also use an array of pointers if (Image.Version == MetadataVersions.V210) { - var fieldTest = Image.ReadMappedWordArray(MetadataRegistration.pfieldOffsets, 6); + var fieldTest = Image.ReadMappedWordArray(MetadataRegistration.FieldOffsets, 6); // We detect this by relying on the fact Module, Object, ValueType, Attribute, _Attribute and Int32 // are always the first six defined types, and that all but Int32 have no fields @@ -380,29 +381,24 @@ namespace Il2CppInspector // All older versions use values directly in the array if (!fieldOffsetsArePointers) - FieldOffsets = Image.ReadMappedArray(MetadataRegistration.pfieldOffsets, (int)MetadataRegistration.fieldOffsetsCount); + FieldOffsets = Image.ReadMappedArray(MetadataRegistration.FieldOffsets, (int)MetadataRegistration.FieldOffsetsCount); else - FieldOffsetPointers = Image.ReadMappedWordArray(MetadataRegistration.pfieldOffsets, (int)MetadataRegistration.fieldOffsetsCount); + FieldOffsetPointers = Image.ReadMappedWordArray(MetadataRegistration.FieldOffsets, (int)MetadataRegistration.FieldOffsetsCount); // Type references (pointer array) - var typeRefPointers = Image.ReadMappedArray(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount); + var typeRefPointers = Image.ReadMappedArray(MetadataRegistration.Types, (int) MetadataRegistration.TypesCount); TypeReferenceIndicesByAddress = typeRefPointers.Zip(Enumerable.Range(0, typeRefPointers.Length), (a, i) => new { a, i }).ToDictionary(x => x.a, x => x.i); - TypeReferences = - Image.Version >= MetadataVersions.V272 - ? Image.ReadMappedObjectPointerArray(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount) - .Cast() - .ToList() - : Image.ReadMappedObjectPointerArray(MetadataRegistration.ptypes, (int)MetadataRegistration.typesCount); + TypeReferences = Image.ReadMappedObjectPointerArray(MetadataRegistration.Types, (int)MetadataRegistration.TypesCount); // Custom attribute constructors (function pointers) // This is managed in Il2CppInspector for metadata >= 27 if (Image.Version < MetadataVersions.V270) { - CustomAttributeGenerators = Image.ReadMappedArray(CodeRegistration.customAttributeGenerators, (int) CodeRegistration.customAttributeCount); + CustomAttributeGenerators = Image.ReadMappedArray(CodeRegistration.CustomAttributeGenerators, (int) CodeRegistration.CustomAttributeCount); } // Method.Invoke function pointers - MethodInvokePointers = Image.ReadMappedArray(CodeRegistration.invokerPointers, (int) CodeRegistration.invokerPointersCount); + MethodInvokePointers = Image.ReadMappedArray(CodeRegistration.InvokerPointers, (int) CodeRegistration.InvokerPointersCount); // TODO: Function pointers as shown below // reversePInvokeWrappers @@ -412,25 +408,25 @@ namespace Il2CppInspector // >=23: interopData if (Image.Version < MetadataVersions.V190) { - VTableMethodReferences = Image.ReadMappedArray(MetadataRegistration.methodReferences, (int)MetadataRegistration.methodReferencesCount); + VTableMethodReferences = Image.ReadMappedArray(MetadataRegistration.MethodReferences, (int)MetadataRegistration.MethodReferencesCount); } // Generic type and method specs (open and closed constructed types) - MethodSpecs = Image.ReadMappedArray(MetadataRegistration.methodSpecs, (int) MetadataRegistration.methodSpecsCount); + MethodSpecs = Image.ReadMappedArray(MetadataRegistration.MethodSpecs, (int) MetadataRegistration.MethodSpecsCount); // Concrete generic class and method signatures - GenericInstances = Image.ReadMappedObjectPointerArray(MetadataRegistration.genericInsts, (int) MetadataRegistration.genericInstsCount); + GenericInstances = Image.ReadMappedObjectPointerArray(MetadataRegistration.GenericInsts, (int) MetadataRegistration.GenericInstsCount); // Concrete generic method pointers - var genericMethodPointers = Image.ReadMappedArray(CodeRegistration.genericMethodPointers, (int) CodeRegistration.genericMethodPointersCount); - var genericMethodTable = Image.ReadMappedArray(MetadataRegistration.genericMethodTable, (int) MetadataRegistration.genericMethodTableCount); + var genericMethodPointers = Image.ReadMappedArray(CodeRegistration.GenericMethodPointers, (int) CodeRegistration.GenericMethodPointersCount); + var genericMethodTable = Image.ReadMappedArray(MetadataRegistration.GenericMethodTable, (int) MetadataRegistration.GenericMethodTableCount); foreach (var tableEntry in genericMethodTable) { - GenericMethodPointers.Add(MethodSpecs[tableEntry.genericMethodIndex], genericMethodPointers[tableEntry.indices.methodIndex]); - GenericMethodInvokerIndices.Add(MethodSpecs[tableEntry.genericMethodIndex], tableEntry.indices.invokerIndex); + GenericMethodPointers.Add(MethodSpecs[tableEntry.GenericMethodIndex], genericMethodPointers[tableEntry.Indices.MethodIndex]); + GenericMethodInvokerIndices.Add(MethodSpecs[tableEntry.GenericMethodIndex], tableEntry.Indices.InvokerIndex); } TypeDefinitionSizes = Image.ReadMappedObjectPointerArray( - MetadataRegistration.typeDefinitionsSizes, (int) MetadataRegistration.typeDefinitionsSizesCount); + MetadataRegistration.TypeDefinitionsSizes, (int) MetadataRegistration.TypeDefinitionsSizesCount); // Plugin hook to pre-process binary isModified |= PluginHooks.PostProcessBinary(this).IsStreamModified; diff --git a/Il2CppInspector.Common/IL2CPP/Il2CppBinaryClasses.cs b/Il2CppInspector.Common/IL2CPP/Il2CppBinaryClasses.cs deleted file mode 100644 index fee8920..0000000 --- a/Il2CppInspector.Common/IL2CPP/Il2CppBinaryClasses.cs +++ /dev/null @@ -1,306 +0,0 @@ -/* - Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper - Copyright 2017-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty - - All rights reserved. -*/ - -using NoisyCowStudios.Bin2Object; - -namespace Il2CppInspector -{ - // From class-internals.h / il2cpp-class-internals.h - public class Il2CppCodeRegistration - { - // Moved to Il2CppCodeGenModule in v24.2 - [Version(Max = 24.1)] - public ulong methodPointersCount; - [Version(Max = 24.1)] - public ulong pmethodPointers; - - public ulong reversePInvokeWrapperCount; // (was renamed from delegateWrappersFromNativeToManagedCount in v22) - public ulong reversePInvokeWrappers; // (was renamed from delegateWrappersFromNativeToManaged in v22) - - // Removed in metadata v23 - [Version(Max = 22)] - public ulong delegateWrappersFromManagedToNativeCount; - [Version(Max = 22)] - public ulong delegateWrappersFromManagedToNative; - [Version(Max = 22)] - public ulong marshalingFunctionsCount; - [Version(Max = 22)] - public ulong marshalingFunctions; - [Version(Min = 21, Max = 22)] - public ulong ccwMarshalingFunctionsCount; - [Version(Min = 21, Max = 22)] - public ulong ccwMarshalingFunctions; - - public ulong genericMethodPointersCount; - public ulong genericMethodPointers; - [Version(Min = 24.5, Max = 24.5)] - [Version(Min = 27.1)] - public ulong genericAdjustorThunks; - - public ulong invokerPointersCount; - public ulong invokerPointers; - - // Removed in metadata v27 - [Version(Max = 24.5)] - public long customAttributeCount; - [Version(Max = 24.5)] - public ulong customAttributeGenerators; - - // Removed in metadata v23 - [Version(Min = 21, Max = 22)] - public long guidCount; - [Version(Min = 21, Max = 22)] - public ulong guids; // Il2CppGuid - - // Added in metadata v22 - [Version(Min = 22, Max = 29)] - public ulong unresolvedVirtualCallCount; - - [Version(Min = 29.1, Max = 29.2)] - [Version(Min = 31.1, Max = 31.2)] - public ulong unresolvedIndirectCallCount; - - [Version(Min = 22)] - public ulong unresolvedVirtualCallPointers; - - [Version(Min = 29.1, Max = 29.2)] - [Version(Min = 31.1, Max = 31.2)] - public ulong unresolvedInstanceCallPointers; - - [Version(Min = 29.1, Max = 29.2)] - [Version(Min = 31.1, Max = 31.2)] - public ulong unresolvedStaticCallPointers; - - // Added in metadata v23 - [Version(Min = 23)] - public ulong interopDataCount; - [Version(Min = 23)] - public ulong interopData; - - [Version(Min = 24.3)] - public ulong windowsRuntimeFactoryCount; - [Version(Min = 24.3)] - public ulong windowsRuntimeFactoryTable; - - // Added in metadata v24.2 to replace methodPointers and methodPointersCount - [Version(Min = 24.2)] - public ulong codeGenModulesCount; - [Version(Min = 24.2)] - public ulong pcodeGenModules; - } - - // Introduced in metadata v24.2 (replaces method pointers in Il2CppCodeRegistration) - public class Il2CppCodeGenModule - { - public ulong moduleName; - public ulong methodPointerCount; - public ulong methodPointers; - [Version(Min = 24.5, Max = 24.5)] - [Version(Min = 27.1)] - public long adjustorThunkCount; - [Version(Min = 24.5, Max = 24.5)] - [Version(Min = 27.1)] - public ulong adjustorThunks; //Pointer - public ulong invokerIndices; - public ulong reversePInvokeWrapperCount; - public ulong reversePInvokeWrapperIndices; - public ulong rgctxRangesCount; - public ulong rgctxRanges; - public ulong rgctxsCount; - public ulong rgctxs; - public ulong debuggerMetadata; - - // Added in metadata v27 - [Version(Min = 27, Max = 27.2)] - public ulong customAttributeCacheGenerator; // CustomAttributesCacheGenerator* - [Version(Min = 27)] - public ulong moduleInitializer; // Il2CppMethodPointer - [Version(Min = 27)] - public ulong staticConstructorTypeIndices; // TypeDefinitionIndex* - [Version(Min = 27)] - public ulong metadataRegistration; // Il2CppMetadataRegistration* // Per-assembly mode only - [Version(Min = 27)] - public ulong codeRegistration; // Il2CppCodeRegistration* // Per-assembly mode only - } - -#pragma warning disable CS0649 - public class Il2CppMetadataRegistration - { - public long genericClassesCount; - public ulong genericClasses; - public long genericInstsCount; - public ulong genericInsts; - public long genericMethodTableCount; - public ulong genericMethodTable; // Il2CppGenericMethodFunctionsDefinitions - public long typesCount; - public ulong ptypes; - public long methodSpecsCount; - public ulong methodSpecs; - [Version(Max = 16)] - public long methodReferencesCount; - [Version(Max = 16)] - public ulong methodReferences; - - public long fieldOffsetsCount; - public ulong pfieldOffsets; // Changed from int32_t* to int32_t** after 5.4.0f3, before 5.5.0f3 - - public long typeDefinitionsSizesCount; - public ulong typeDefinitionsSizes; - [Version(Min = 19)] - public ulong metadataUsagesCount; - [Version(Min = 19)] - public ulong metadataUsages; - } -#pragma warning restore CS0649 - - // From blob.h / il2cpp-blob.h - public enum Il2CppTypeEnum - { - IL2CPP_TYPE_END = 0x00, /* End of List */ - IL2CPP_TYPE_VOID = 0x01, - IL2CPP_TYPE_BOOLEAN = 0x02, - IL2CPP_TYPE_CHAR = 0x03, - IL2CPP_TYPE_I1 = 0x04, - IL2CPP_TYPE_U1 = 0x05, - IL2CPP_TYPE_I2 = 0x06, - IL2CPP_TYPE_U2 = 0x07, - IL2CPP_TYPE_I4 = 0x08, - IL2CPP_TYPE_U4 = 0x09, - IL2CPP_TYPE_I8 = 0x0a, - IL2CPP_TYPE_U8 = 0x0b, - IL2CPP_TYPE_R4 = 0x0c, - IL2CPP_TYPE_R8 = 0x0d, - IL2CPP_TYPE_STRING = 0x0e, - IL2CPP_TYPE_PTR = 0x0f, /* arg: token */ - IL2CPP_TYPE_BYREF = 0x10, /* arg: token */ - IL2CPP_TYPE_VALUETYPE = 0x11, /* arg: token */ - IL2CPP_TYPE_CLASS = 0x12, /* arg: token */ - IL2CPP_TYPE_VAR = 0x13, /* Generic parameter in a generic type definition, represented as number (compressed unsigned integer) number */ - IL2CPP_TYPE_ARRAY = 0x14, /* type, rank, boundsCount, bound1, loCount, lo1 */ - IL2CPP_TYPE_GENERICINST = 0x15, /* \x{2026} */ - IL2CPP_TYPE_TYPEDBYREF = 0x16, - IL2CPP_TYPE_I = 0x18, - IL2CPP_TYPE_U = 0x19, - IL2CPP_TYPE_FNPTR = 0x1b, /* arg: full method signature */ - IL2CPP_TYPE_OBJECT = 0x1c, - IL2CPP_TYPE_SZARRAY = 0x1d, /* 0-based one-dim-array */ - IL2CPP_TYPE_MVAR = 0x1e, /* Generic parameter in a generic method definition, represented as number (compressed unsigned integer) */ - IL2CPP_TYPE_CMOD_REQD = 0x1f, /* arg: typedef or typeref token */ - IL2CPP_TYPE_CMOD_OPT = 0x20, /* optional arg: typedef or typref token */ - IL2CPP_TYPE_INTERNAL = 0x21, /* CLR internal type */ - - IL2CPP_TYPE_MODIFIER = 0x40, /* Or with the following types */ - IL2CPP_TYPE_SENTINEL = 0x41, /* Sentinel for varargs method signature */ - IL2CPP_TYPE_PINNED = 0x45, /* Local var that points to pinned object */ - - IL2CPP_TYPE_ENUM = 0x55, /* an enumeration */ - IL2CPP_TYPE_IL2CPP_TYPE_INDEX = 0xff /* Type index metadata table */ - } - - // From metadata.h / il2cpp-runtime-metadata.h - public class Il2CppType - { - public ulong datapoint; - public ulong bits; // this should be private but we need it to be public for BinaryObjectReader to work - //public Union data { get; set; } - - public virtual uint attrs => (uint) bits & 0xffff; - public virtual Il2CppTypeEnum type => (Il2CppTypeEnum)((bits >> 16) & 0xff); - - public virtual uint num_mods => (uint) (bits >> 24) & 0x3f; - public virtual bool byref => ((bits >> 30) & 1) == 1; - public virtual bool pinned => ((bits >> 31) & 1) == 1; - public virtual bool valuetype => false; - - /* - union - { - TypeDefinitionIndex klassIndex; // for VALUETYPE and CLASS ( (uint) (bits >> 24) & 0x1f; - public override bool byref => ((bits >> 29) & 1) == 1; - public override bool pinned => ((bits >> 30) & 1) == 1; - public override bool valuetype => ((bits >> 31) & 1) == 1; - } - - public class Il2CppGenericClass - { - [Version(Max = 24.5)] - public long typeDefinitionIndex; /* the generic type definition */ - [Version(Min = 27)] - public ulong type; // Il2CppType* /* the generic type definition */ - - public Il2CppGenericContext context; /* a context that contains the type instantiation doesn't contain any method instantiation */ - public ulong cached_class; /* if present, the Il2CppClass corresponding to the instantiation. */ - } - - public class Il2CppGenericContext - { - /* The instantiation corresponding to the class generic parameters */ - public ulong class_inst; - /* The instantiation corresponding to the method generic parameters */ - public ulong method_inst; - } - - public class Il2CppGenericInst - { - public ulong type_argc; - public ulong type_argv; - } - - public class Il2CppArrayType - { - public ulong etype; - public byte rank; - public byte numsizes; - public byte numlobounds; - public ulong sizes; - public ulong lobounds; - } - - public class Il2CppMethodSpec - { - public int methodDefinitionIndex; - public int classIndexIndex; - public int methodIndexIndex; - } - - public class Il2CppGenericMethodFunctionsDefinitions - { - public int genericMethodIndex; - public Il2CppGenericMethodIndices indices; - } - - public class Il2CppGenericMethodIndices - { - public int methodIndex; - public int invokerIndex; - [Version(Min = 24.5, Max = 24.5)] - [Version(Min = 27.1)] - public int adjustorThunk; - } - - public class Il2CppTypeDefinitionSizes - { - public uint instanceSize; - public int nativeSize; - public uint staticFieldsSize; - public uint threadStaticFieldsSize; - } -} diff --git a/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs b/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs index 9702702..8eb5570 100644 --- a/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs +++ b/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs @@ -13,6 +13,8 @@ using System.IO; using System.IO.Compression; using System.Linq; using System.Text; +using Il2CppInspector.Next.BinaryMetadata; +using Il2CppInspector.Next.Metadata; using VersionedSerialization; namespace Il2CppInspector @@ -81,7 +83,7 @@ namespace Il2CppInspector return (0ul, null); // Get pointer in binary to default value - var pValue = Metadata.Header.fieldAndParameterDefaultValueDataOffset + dataIndex; + var pValue = Metadata.Header.FieldAndParameterDefaultValueDataOffset + dataIndex; var typeRef = TypeReferences[typeIndex]; // Default value is null @@ -89,7 +91,7 @@ namespace Il2CppInspector return (0ul, null); Metadata.Position = pValue; - var value = BlobReader.GetConstantValueFromBlob(this, typeRef.type, Metadata); + var value = BlobReader.GetConstantValueFromBlob(this, typeRef.Type, Metadata); return ((ulong) pValue, value); } @@ -108,10 +110,10 @@ namespace Il2CppInspector var usages = new Dictionary(); foreach (var metadataUsageList in Metadata.MetadataUsageLists) { - for (var i = 0; i < metadataUsageList.count; i++) + for (var i = 0; i < metadataUsageList.Count; i++) { - var metadataUsagePair = Metadata.MetadataUsagePairs[metadataUsageList.start + i]; - usages.TryAdd(metadataUsagePair.destinationindex, MetadataUsage.FromEncodedIndex(this, metadataUsagePair.encodedSourceIndex)); + var metadataUsagePair = Metadata.MetadataUsagePairs[metadataUsageList.Start + i]; + usages.TryAdd(metadataUsagePair.DestinationIndex, MetadataUsage.FromEncodedIndex(this, metadataUsagePair.EncodedSourceIndex)); } } @@ -119,7 +121,7 @@ namespace Il2CppInspector // Unfortunately the value supplied in MetadataRegistration.matadataUsagesCount seems to be incorrect, // so we have to calculate the correct number of usages above before reading the usage address list from the binary var count = usages.Keys.Max() + 1; - var addresses = Binary.Image.ReadMappedArray(Binary.MetadataRegistration.metadataUsages, (int) count); + var addresses = Binary.Image.ReadMappedArray(Binary.MetadataRegistration.MetadataUsages, (int) count); foreach (var usage in usages) usage.Value.SetAddress(addresses[usage.Key]); @@ -184,11 +186,11 @@ namespace Il2CppInspector // Get all field default values foreach (var fdv in Metadata.FieldDefaultValues) - FieldDefaultValue.Add(fdv.fieldIndex, ((ulong,object)) getDefaultValue(fdv.typeIndex, fdv.dataIndex)); + FieldDefaultValue.Add(fdv.FieldIndex, ((ulong,object)) getDefaultValue(fdv.TypeIndex, fdv.DataIndex)); // Get all parameter default values foreach (var pdv in Metadata.ParameterDefaultValues) - ParameterDefaultValue.Add(pdv.parameterIndex, ((ulong,object)) getDefaultValue(pdv.typeIndex, pdv.dataIndex)); + ParameterDefaultValue.Add(pdv.ParameterIndex, ((ulong,object)) getDefaultValue(pdv.TypeIndex, pdv.DataIndex)); // Get all field offsets if (Binary.FieldOffsets != null) { @@ -212,8 +214,8 @@ namespace Il2CppInspector available = false; } - for (var f = 0; f < def.field_count; f++) - offsets.Add(def.fieldStart + f, available? BinaryImage.ReadUInt32() : 0); + for (var f = 0; f < def.FieldCount; f++) + offsets.Add(def.FieldIndex + f, available? BinaryImage.ReadUInt32() : 0); } } @@ -225,16 +227,16 @@ namespace Il2CppInspector CustomAttributeGenerators = Binary.CustomAttributeGenerators; else if (Version < MetadataVersions.V290) { - var cagCount = Images.Sum(i => i.customAttributeCount); + var cagCount = Images.Sum(i => i.CustomAttributeCount); CustomAttributeGenerators = new ulong[cagCount]; foreach (var image in Images) { // Get CodeGenModule for this image - var codeGenModule = Binary.Modules[Strings[image.nameIndex]]; - var cags = BinaryImage.ReadMappedWordArray(codeGenModule.customAttributeCacheGenerator, - (int) image.customAttributeCount); - cags.CopyTo(CustomAttributeGenerators, image.customAttributeStart); + var codeGenModule = Binary.Modules[Strings[image.NameIndex]]; + var cags = BinaryImage.ReadMappedWordArray(codeGenModule.CustomAttributeCacheGenerator, + (int) image.CustomAttributeCount); + cags.CopyTo(CustomAttributeGenerators, image.CustomAttributeStart); } } else @@ -270,15 +272,15 @@ namespace Il2CppInspector foreach (var image in Images) { var attsByToken = new Dictionary(); - for (int i = 0; i < image.customAttributeCount; i++) + for (int i = 0; i < image.CustomAttributeCount; i++) { - var index = image.customAttributeStart + i; - var token = Version >= MetadataVersions.V290 ? AttributeDataRanges[index].token : AttributeTypeRanges[index].token; + var index = image.CustomAttributeStart + i; + var token = Version >= MetadataVersions.V290 ? AttributeDataRanges[index].Token : AttributeTypeRanges[index].Token; attsByToken.Add(token, index); } if (attsByToken.Count > 0) - AttributeIndicesByToken.Add(image.customAttributeStart, attsByToken); + AttributeIndicesByToken.Add(image.CustomAttributeStart, attsByToken); } } @@ -292,20 +294,20 @@ namespace Il2CppInspector // Get a method pointer if available public (ulong Start, ulong End)? GetMethodPointer(Il2CppCodeGenModule module, Il2CppMethodDefinition methodDef) { // Find method pointer - if (methodDef.methodIndex < 0) + if (methodDef.MethodIndex < 0) return null; ulong start = 0; // Global method pointer array if (Version <= MetadataVersions.V241) { - start = Binary.GlobalMethodPointers[methodDef.methodIndex]; + start = Binary.GlobalMethodPointers[methodDef.MethodIndex]; } // Per-module method pointer array uses the bottom 24 bits of the method's metadata token // Derived from il2cpp::vm::MetadataCache::GetMethodPointer if (Version >= MetadataVersions.V242) { - var method = (methodDef.token & 0xffffff); + var method = (methodDef.Token & 0xffffff); if (method == 0) return null; @@ -340,18 +342,18 @@ namespace Il2CppInspector // Get a method invoker index from a method definition public int GetInvokerIndex(Il2CppCodeGenModule module, Il2CppMethodDefinition methodDef) { if (Version <= MetadataVersions.V241) { - return methodDef.invokerIndex; + return methodDef.InvokerIndex; } // Version >= 24.2 - var methodInModule = (methodDef.token & 0xffffff); + var methodInModule = (methodDef.Token & 0xffffff); return Binary.MethodInvokerIndices[module][methodInModule - 1]; } public MetadataUsage[] GetVTable(Il2CppTypeDefinition definition) { - MetadataUsage[] res = new MetadataUsage[definition.vtable_count]; - for (int i = 0; i < definition.vtable_count; i++) { - var encodedIndex = VTableMethodIndices[definition.vtableStart + i]; + MetadataUsage[] res = new MetadataUsage[definition.VTableCount]; + for (int i = 0; i < definition.VTableCount; i++) { + var encodedIndex = VTableMethodIndices[definition.VTableIndex + i]; MetadataUsage usage = MetadataUsage.FromEncodedIndex(this, encodedIndex); if (usage.SourceIndex != 0) res[i] = usage; diff --git a/Il2CppInspector.Common/IL2CPP/ImageScan.cs b/Il2CppInspector.Common/IL2CPP/ImageScan.cs index 91a05af..869abf3 100644 --- a/Il2CppInspector.Common/IL2CPP/ImageScan.cs +++ b/Il2CppInspector.Common/IL2CPP/ImageScan.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Il2CppInspector.Next; +using Il2CppInspector.Next.BinaryMetadata; namespace Il2CppInspector { @@ -211,12 +212,12 @@ namespace Il2CppInspector // if this changes we'll have to get smarter about disambiguating these two. var cr = Image.ReadMappedObject(codeRegistration); - if (Image.Version == MetadataVersions.V242 && cr.interopDataCount == 0) { + if (Image.Version == MetadataVersions.V242 && cr.InteropDataCount == 0) { Image.Version = MetadataVersions.V243; codeRegistration -= ptrSize * 2; // two extra words for WindowsRuntimeFactory } - if (Image.Version == MetadataVersions.V270 && cr.reversePInvokeWrapperCount > 0x30000) + if (Image.Version == MetadataVersions.V270 && cr.ReversePInvokeWrapperCount > 0x30000) { // If reversePInvokeWrapperCount is a pointer, then it's because we're actually on 27.1 and there's a genericAdjustorThunks pointer interfering. // We need to bump version to 27.1 and back up one more pointer. @@ -229,7 +230,7 @@ namespace Il2CppInspector // <= 24.1 else { // The first item in CodeRegistration is the total number of method pointers - vas = FindAllMappedWords(imageBytes, (ulong) metadata.Methods.Count(m => (uint) m.methodIndex != 0xffff_ffff)); + vas = FindAllMappedWords(imageBytes, (ulong) metadata.Methods.Count(m => (uint) m.MethodIndex != 0xffff_ffff)); if (!vas.Any()) return (0, 0); @@ -240,7 +241,7 @@ namespace Il2CppInspector foreach (var va in vas) { var cr = Image.ReadMappedObject(va); - if (cr.customAttributeCount == metadata.AttributeTypeRanges.Length) + if (cr.CustomAttributeCount == metadata.AttributeTypeRanges.Length) codeRegistration = va; } @@ -263,7 +264,7 @@ namespace Il2CppInspector if (Image.Version < MetadataVersions.V270) foreach (var va in vas) { var mr = Image.ReadMappedObject(va); - if (mr.metadataUsagesCount == (ulong) metadata.MetadataUsageLists.Length) + if (mr.MetadataUsagesCount == (ulong) metadata.MetadataUsageLists.Length) metadataRegistration = va; } diff --git a/Il2CppInspector.Common/IL2CPP/Metadata.cs b/Il2CppInspector.Common/IL2CPP/Metadata.cs index a814585..63116d1 100644 --- a/Il2CppInspector.Common/IL2CPP/Metadata.cs +++ b/Il2CppInspector.Common/IL2CPP/Metadata.cs @@ -11,6 +11,7 @@ using System.IO; using System.Linq; using System.Reflection; using Il2CppInspector.Next; +using Il2CppInspector.Next.Metadata; using NoisyCowStudios.Bin2Object; using VersionedSerialization; @@ -83,15 +84,15 @@ namespace Il2CppInspector Header = ReadObject(0); // Check for correct magic bytes - if (Header.signature != Il2CppConstants.MetadataSignature) { + if (!Header.SanityValid) { throw new InvalidOperationException("The supplied metadata file is not valid."); } // Set object versioning for Bin2Object from metadata version - Version = new StructVersion(Header.version); + Version = new StructVersion(Header.Version); if (Version < MetadataVersions.V160 || Version > MetadataVersions.V310) { - throw new InvalidOperationException($"The supplied metadata file is not of a supported version ({Header.version})."); + throw new InvalidOperationException($"The supplied metadata file is not of a supported version ({Header.Version})."); } // Rewind and read metadata header with the correct version settings @@ -107,7 +108,7 @@ namespace Il2CppInspector // we can use this value to determine the actual header length and therefore narrow down the metadata version to 24.0/24.1 or 24.2. if (!pluginResult.SkipValidation) { - var realHeaderLength = Header.stringLiteralOffset; + var realHeaderLength = Header.StringLiteralOffset; if (realHeaderLength != Sizeof(typeof(Il2CppGlobalMetadataHeader))) { if (Version == MetadataVersions.V240) { @@ -123,43 +124,43 @@ namespace Il2CppInspector // Load all the relevant metadata using offsets provided in the header if (Version >= MetadataVersions.V160) - Images = ReadArray(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition))); + Images = ReadArray(Header.ImagesOffset, Header.ImagesSize / Sizeof(typeof(Il2CppImageDefinition))); // As an additional sanity check, all images in the metadata should have Mono.Cecil.MetadataToken == 1 // In metadata v24.1, two extra fields were added which will cause the below test to fail. // In that case, we can then adjust the version number and reload // Tokens were introduced in v19 - we don't bother testing earlier versions - if (Version >= MetadataVersions.V190 && Images.Any(x => x.token != 1)) + if (Version >= MetadataVersions.V190 && Images.Any(x => x.Token != 1)) if (Version == MetadataVersions.V240) { Version = MetadataVersions.V241; // No need to re-read the header, it's the same for both sub-versions - Images = ReadArray(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition))); + Images = ReadArray(Header.ImagesOffset, Header.ImagesSize / Sizeof(typeof(Il2CppImageDefinition))); - if (Images.Any(x => x.token != 1)) + if (Images.Any(x => x.Token != 1)) throw new InvalidOperationException("Could not verify the integrity of the metadata file image list"); } - Types = ReadArray(Header.typeDefinitionsOffset, Header.typeDefinitionsCount / Sizeof(typeof(Il2CppTypeDefinition))); - Methods = ReadArray(Header.methodsOffset, Header.methodsCount / Sizeof(typeof(Il2CppMethodDefinition))); - Params = ReadArray(Header.parametersOffset, Header.parametersCount / Sizeof(typeof(Il2CppParameterDefinition))); - Fields = ReadArray(Header.fieldsOffset, Header.fieldsCount / Sizeof(typeof(Il2CppFieldDefinition))); - FieldDefaultValues = ReadArray(Header.fieldDefaultValuesOffset, Header.fieldDefaultValuesCount / Sizeof(typeof(Il2CppFieldDefaultValue))); - Properties = ReadArray(Header.propertiesOffset, Header.propertiesCount / Sizeof(typeof(Il2CppPropertyDefinition))); - Events = ReadArray(Header.eventsOffset, Header.eventsCount / Sizeof(typeof(Il2CppEventDefinition))); - InterfaceUsageIndices = ReadArray(Header.interfacesOffset, Header.interfacesCount / sizeof(int)); - NestedTypeIndices = ReadArray(Header.nestedTypesOffset, Header.nestedTypesCount / sizeof(int)); - GenericContainers = ReadArray(Header.genericContainersOffset, Header.genericContainersCount / Sizeof(typeof(Il2CppGenericContainer))); - GenericParameters = ReadArray(Header.genericParametersOffset, Header.genericParametersCount / Sizeof(typeof(Il2CppGenericParameter))); - GenericConstraintIndices = ReadArray(Header.genericParameterConstraintsOffset, Header.genericParameterConstraintsCount / sizeof(int)); - InterfaceOffsets = ReadArray(Header.interfaceOffsetsOffset, Header.interfaceOffsetsCount / Sizeof(typeof(Il2CppInterfaceOffsetPair))); - VTableMethodIndices = ReadArray(Header.vtableMethodsOffset, Header.vtableMethodsCount / sizeof(uint)); + Types = ReadArray(Header.TypeDefinitionsOffset, Header.TypeDefinitionsSize / Sizeof(typeof(Il2CppTypeDefinition))); + Methods = ReadArray(Header.MethodsOffset, Header.MethodsSize / Sizeof(typeof(Il2CppMethodDefinition))); + Params = ReadArray(Header.ParametersOffset, Header.ParametersSize / Sizeof(typeof(Il2CppParameterDefinition))); + Fields = ReadArray(Header.FieldsOffset, Header.FieldsSize / Sizeof(typeof(Il2CppFieldDefinition))); + FieldDefaultValues = ReadArray(Header.FieldDefaultValuesOffset, Header.FieldDefaultValuesSize / Sizeof(typeof(Il2CppFieldDefaultValue))); + Properties = ReadArray(Header.PropertiesOffset, Header.PropertiesSize / Sizeof(typeof(Il2CppPropertyDefinition))); + Events = ReadArray(Header.EventsOffset, Header.EventsSize / Sizeof(typeof(Il2CppEventDefinition))); + InterfaceUsageIndices = ReadArray(Header.InterfacesOffset, Header.InterfacesSize / sizeof(int)); + NestedTypeIndices = ReadArray(Header.NestedTypesOffset, Header.NestedTypesSize / sizeof(int)); + GenericContainers = ReadArray(Header.GenericContainersOffset, Header.GenericContainersSize / Sizeof(typeof(Il2CppGenericContainer))); + GenericParameters = ReadArray(Header.GenericParametersOffset, Header.GenericParametersSize / Sizeof(typeof(Il2CppGenericParameter))); + GenericConstraintIndices = ReadArray(Header.GenericParameterConstraintsOffset, Header.GenericParameterConstraintsSize / sizeof(int)); + InterfaceOffsets = ReadArray(Header.InterfaceOffsetsOffset, Header.InterfaceOffsetsSize / Sizeof(typeof(Il2CppInterfaceOffsetPair))); + VTableMethodIndices = ReadArray(Header.VTableMethodsOffset, Header.VTableMethodsSize / sizeof(uint)); if (Version >= MetadataVersions.V160) { // In v24.4 hashValueIndex was removed from Il2CppAssemblyNameDefinition, which is a field in Il2CppAssemblyDefinition // The number of images and assemblies should be the same. If they are not, we deduce that we are using v24.4 // Note the version comparison matches both 24.2 and 24.3 here since 24.3 is tested for during binary loading - var assemblyCount = Header.assembliesCount / Sizeof(typeof(Il2CppAssemblyDefinition)); + var assemblyCount = Header.AssembliesSize / Sizeof(typeof(Il2CppAssemblyDefinition)); var changedAssemblyDefStruct = false; if ((Version == MetadataVersions.V241 || Version == MetadataVersions.V242 || Version == MetadataVersions.V243) && assemblyCount < Images.Length) { @@ -168,29 +169,29 @@ namespace Il2CppInspector Version = MetadataVersions.V244; } - Assemblies = ReadArray(Header.assembliesOffset, Images.Length); + Assemblies = ReadArray(Header.AssembliesOffset, Images.Length); if (changedAssemblyDefStruct) Version = MetadataVersions.V241; - ParameterDefaultValues = ReadArray(Header.parameterDefaultValuesOffset, Header.parameterDefaultValuesCount / Sizeof(typeof(Il2CppParameterDefaultValue))); + ParameterDefaultValues = ReadArray(Header.ParameterDefaultValuesOffset, Header.ParameterDefaultValuesSize / Sizeof(typeof(Il2CppParameterDefaultValue))); } if (Version >= MetadataVersions.V190 && Version < MetadataVersions.V270) { - MetadataUsageLists = ReadArray(Header.metadataUsageListsOffset, Header.metadataUsageListsCount / Sizeof(typeof(Il2CppMetadataUsageList))); - MetadataUsagePairs = ReadArray(Header.metadataUsagePairsOffset, Header.metadataUsagePairsCount / Sizeof(typeof(Il2CppMetadataUsagePair))); + MetadataUsageLists = ReadArray(Header.MetadataUsageListsOffset, Header.MetadataUsageListsCount / Sizeof(typeof(Il2CppMetadataUsageList))); + MetadataUsagePairs = ReadArray(Header.MetadataUsagePairsOffset, Header.MetadataUsagePairsCount / Sizeof(typeof(Il2CppMetadataUsagePair))); } if (Version >= MetadataVersions.V190) { - FieldRefs = ReadArray(Header.fieldRefsOffset, Header.fieldRefsCount / Sizeof(typeof(Il2CppFieldRef))); + FieldRefs = ReadArray(Header.FieldRefsOffset, Header.FieldRefsSize / Sizeof(typeof(Il2CppFieldRef))); } if (Version >= MetadataVersions.V210 && Version < MetadataVersions.V290) { - AttributeTypeIndices = ReadArray(Header.attributeTypesOffset, Header.attributeTypesCount / sizeof(int)); - AttributeTypeRanges = ReadArray(Header.attributesInfoOffset, Header.attributesInfoCount / Sizeof(typeof(Il2CppCustomAttributeTypeRange))); + AttributeTypeIndices = ReadArray(Header.AttributesTypesOffset, Header.AttributesTypesCount / sizeof(int)); + AttributeTypeRanges = ReadArray(Header.AttributesInfoOffset, Header.AttributesInfoCount / Sizeof(typeof(Il2CppCustomAttributeTypeRange))); } if (Version >= MetadataVersions.V290) { - AttributeDataRanges = ReadArray(Header.attributeDataRangeOffset, - Header.attributeDataRangeSize / Sizeof(typeof(Il2CppCustomAttributeDataRange))); + AttributeDataRanges = ReadArray(Header.AttributeDataRangeOffset, + Header.AttributeDataRangeSize / Sizeof(typeof(Il2CppCustomAttributeDataRange))); } if (Version == MetadataVersions.V290 || Version == MetadataVersions.V310) @@ -201,13 +202,13 @@ namespace Il2CppInspector if (Methods.Length >= 2) { - var secondToken = Methods[1].token; + var secondToken = Methods[1].Token; if (secondToken >> 24 != 0x6) { Version = new StructVersion(Version.Major, 1, Version.Tag); - Methods = ReadArray(Header.methodsOffset, - Header.methodsCount / Sizeof(typeof(Il2CppMethodDefinition))); + Methods = ReadArray(Header.MethodsOffset, + Header.MethodsSize / Sizeof(typeof(Il2CppMethodDefinition))); } } } @@ -218,10 +219,10 @@ namespace Il2CppInspector Strings = pluginGetStringsResult.Strings; else { - Position = Header.stringOffset; + Position = Header.StringOffset; - while (Position < Header.stringOffset + Header.stringCount) - Strings.Add((int) Position - Header.stringOffset, ReadNullTerminatedString()); + while (Position < Header.StringOffset + Header.StringSize) + Strings.Add((int) Position - Header.StringOffset, ReadNullTerminatedString()); } // Get all string literals @@ -230,11 +231,11 @@ namespace Il2CppInspector StringLiterals = pluginGetStringLiteralsResult.StringLiterals.ToArray(); else { - var stringLiteralList = ReadArray(Header.stringLiteralOffset, Header.stringLiteralCount / Sizeof(typeof(Il2CppStringLiteral))); + var stringLiteralList = ReadArray(Header.StringLiteralOffset, Header.StringLiteralSize / Sizeof(typeof(Il2CppStringLiteral))); StringLiterals = new string[stringLiteralList.Length]; for (var i = 0; i < stringLiteralList.Length; i++) - StringLiterals[i] = ReadFixedLengthString(Header.stringLiteralDataOffset + stringLiteralList[i].dataIndex, stringLiteralList[i].length); + StringLiterals[i] = ReadFixedLengthString(Header.StringLiteralDataOffset + stringLiteralList[i].DataIndex, (int)stringLiteralList[i].Length); } // Post-processing hook diff --git a/Il2CppInspector.Common/IL2CPP/MetadataClasses.cs b/Il2CppInspector.Common/IL2CPP/MetadataClasses.cs deleted file mode 100644 index e2c3cfc..0000000 --- a/Il2CppInspector.Common/IL2CPP/MetadataClasses.cs +++ /dev/null @@ -1,483 +0,0 @@ -/* - Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper - Copyright 2017-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty - - All rights reserved. -*/ - -using NoisyCowStudios.Bin2Object; - -namespace Il2CppInspector -{ - // Unity 4.6.1p5 - first release, no global-metadata.dat - // Unity 5.2.0f3 -> v15 - // Unity 5.3.0f4 -> v16 - // Unity 5.3.2f1 -> v19 - // Unity 5.3.3f1 -> v20 - // Unity 5.3.5f1 -> v21 - // Unity 5.5.0f3 -> v22 - // Unity 5.6.0f3 -> v23 - // Unity 2017.1.0f3 -> v24 - // Unity 2018.3.0f2 -> v24.1 - // Unity 2019.1.0f2 -> v24.2 - // Unity 2019.3.7f1 -> v24.3 - // Unity 2019.4.15f1 -> v24.4 - // Unity 2019.4.21f1 -> v24.5 - // Unity 2020.1.0f1 -> v24.3 - // Unity 2020.1.11f1 -> v24.4 - // Unity 2020.2.0f1 -> v27 - // Unity 2020.2.4f1 -> v27.1 - // Unity 2021.1.0f1 -> v27.2 - // https://unity3d.com/get-unity/download/archive - // Metadata version is written at the end of Unity.IL2CPP.MetadataCacheWriter.WriteLibIl2CppMetadata or WriteMetadata (Unity.IL2CPP.dll) - - // From il2cpp-metadata.h -#pragma warning disable CS0649 - public class Il2CppGlobalMetadataHeader - { - public uint signature; - public int version; - public int stringLiteralOffset; // string data for managed code - public int stringLiteralCount; - public int stringLiteralDataOffset; - public int stringLiteralDataCount; - public int stringOffset; // string data for metadata - public int stringCount; - public int eventsOffset; // Il2CppEventDefinition - public int eventsCount; - public int propertiesOffset; // Il2CppPropertyDefinition - public int propertiesCount; - public int methodsOffset; // Il2CppMethodDefinition - public int methodsCount; - - [Version(Min = 16)] - public int parameterDefaultValuesOffset; // Il2CppParameterDefaultValue - [Version(Min = 16)] - public int parameterDefaultValuesCount; - - public int fieldDefaultValuesOffset; // Il2CppFieldDefaultValue - public int fieldDefaultValuesCount; - public int fieldAndParameterDefaultValueDataOffset; // uint8_t - public int fieldAndParameterDefaultValueDataCount; - - [Version(Min = 16)] - public int fieldMarshaledSizesOffset; // Il2CppFieldMarshaledSize - [Version(Min = 16)] - public int fieldMarshaledSizesCount; - - public int parametersOffset; // Il2CppParameterDefinition - public int parametersCount; - public int fieldsOffset; // Il2CppFieldDefinition - public int fieldsCount; - public int genericParametersOffset; // Il2CppGenericParameter - public int genericParametersCount; - public int genericParameterConstraintsOffset; // TypeIndex - public int genericParameterConstraintsCount; - public int genericContainersOffset; // Il2CppGenericContainer - public int genericContainersCount; - public int nestedTypesOffset; // TypeDefinitionIndex - public int nestedTypesCount; - public int interfacesOffset; // TypeIndex - public int interfacesCount; - public int vtableMethodsOffset; // EncodedMethodIndex - public int vtableMethodsCount; - public int interfaceOffsetsOffset; // Il2CppInterfaceOffsetPair - public int interfaceOffsetsCount; - public int typeDefinitionsOffset; // Il2CppTypeDefinition - public int typeDefinitionsCount; - - [Version(Max = 24.1)] - public int rgctxEntriesOffset; // Il2CppRGCTXDefinition - [Version(Max = 24.1)] - public int rgctxEntriesCount; - - [Version(Min = 16)] - public int imagesOffset; // Il2CppImageDefinition - [Version(Min = 16)] - public int imagesCount; - [Version(Min = 16)] - public int assembliesOffset; // Il2CppAssemblyDefinition - [Version(Min = 16)] - public int assembliesCount; - - [Version(Min = 19, Max = 24.5)] - public int metadataUsageListsOffset; // Il2CppMetadataUsageList - [Version(Min = 19, Max = 24.5)] - public int metadataUsageListsCount; - [Version(Min = 19, Max = 24.5)] - public int metadataUsagePairsOffset; // Il2CppMetadataUsagePair - [Version(Min = 19, Max = 24.5)] - public int metadataUsagePairsCount; - [Version(Min = 19)] - public int fieldRefsOffset; // Il2CppFieldRef - [Version(Min = 19)] - public int fieldRefsCount; - [Version(Min = 20)] - public int referencedAssembliesOffset; // int32_t - [Version(Min = 20)] - public int referencedAssembliesCount; - - [Version(Min = 21, Max = 27.2)] - public int attributesInfoOffset; // Il2CppCustomAttributeTypeRange - [Version(Min = 21, Max = 27.2)] - public int attributesInfoCount; - [Version(Min = 21, Max = 27.2)] - public int attributeTypesOffset; // TypeIndex - [Version(Min = 21, Max = 27.2)] - public int attributeTypesCount; - [Version(Min = 29)] - public uint attributeDataOffset; - [Version(Min = 29)] - public int attributeDataSize; - [Version(Min = 29)] - public uint attributeDataRangeOffset; - [Version(Min = 29)] - public int attributeDataRangeSize; - - // Added in metadata v22 - [Version(Min = 22)] - public int unresolvedVirtualCallParameterTypesOffset; // TypeIndex - [Version(Min = 22)] - public int unresolvedVirtualCallParameterTypesCount; - [Version(Min = 22)] - public int unresolvedVirtualCallParameterRangesOffset; // Il2CppRange - [Version(Min = 22)] - public int unresolvedVirtualCallParameterRangesCount; - - // Added in metadata v23 - [Version(Min = 23)] - public int windowsRuntimeTypeNamesOffset; // Il2CppWindowsRuntimeTypeNamePair - [Version(Min = 23)] - public int windowsRuntimeTypeNamesSize; - - // Added in metadata v27 - [Version(Min = 27)] - public int windowsRuntimeStringsOffset; // const char* - [Version(Min = 27)] - public int windowsRuntimeStringsSize; - - // Added in metadata v24 - [Version(Min = 24)] - public int exportedTypeDefinitionsOffset; // TypeDefinitionIndex - [Version(Min = 24)] - public int exportedTypeDefinitionsCount; - } - - public class Il2CppImageDefinition - { - public int nameIndex; - public int assemblyIndex; - - public int typeStart; - public uint typeCount; - - [Version(Min = 24)] - public int exportedTypeStart; - [Version(Min = 24)] - public uint exportedTypeCount; - - public int entryPointIndex; - - [Version(Min = 19)] - public uint token; - - [Version(Min = 24.1)] - public int customAttributeStart; - [Version(Min = 24.1)] - public uint customAttributeCount; - } -#pragma warning restore CS0649 - - // Renamed from Il2CppAssembly somewhere after Unity 2017.2f3 up to Unity 2018.2.0f2 - public class Il2CppAssemblyDefinition - { - // They moved the position of aname in v16 from the top to the bottom of the struct - public Il2CppAssemblyNameDefinition aname => aname_pre16 ?? aname_post16; - - [Version(Max = 15)] - public Il2CppAssemblyNameDefinition aname_pre16; - - public int imageIndex; - - [Version(Min = 24.1)] - public uint token; - - [Version(Max = 24.0)] - public int customAttributeIndex; - - [Version(Min = 20)] - public int referencedAssemblyStart; - [Version(Min = 20)] - public int referencedAssemblyCount; - - [Version(Min = 16)] - public Il2CppAssemblyNameDefinition aname_post16; - } - - // Renamed from Il2CppAssemblyName somewhere after Unity 2017.2f3 up to Unity 2018.2.0f2 - public class Il2CppAssemblyNameDefinition - { - // They moved the position of publicKeyToken in v16 from the middle to the bottom of the struct - public byte[] publicKeyToken => publicKeyToken_post16; - - public int nameIndex; - public int cultureIndex; - [Version(Max = 24.3)] - public int hashValueIndex; - public int publicKeyIndex; - [Version(Max = 15), ArrayLength(FixedSize = 8)] - public byte[] publicKeyToken_pre16; - public uint hash_alg; - public int hash_len; - public uint flags; - public int major; - public int minor; - public int build; - public int revision; - [Version(Min = 16), ArrayLength(FixedSize = 8)] - public byte[] publicKeyToken_post16; - } - - public class Il2CppTypeDefinition - { - public int nameIndex; - public int namespaceIndex; - - // Removed in metadata v24.1 - [Version(Max = 24.0)] - public int customAttributeIndex; - - public int byvalTypeIndex; - [Version(Max = 24.5)] - public int byrefTypeIndex; - - public int declaringTypeIndex; - public int parentIndex; - public int elementTypeIndex; // we can probably remove this one. Only used for enums - - [Version(Max = 24.1)] - public int rgctxStartIndex; - [Version(Max = 24.1)] - public int rgctxCount; - - public int genericContainerIndex; - - // Removed in metadata v23 - [Version(Max = 22)] - public int delegateWrapperFromManagedToNativeIndex; // (was renamed to reversePInvokeWrapperIndex in v22) - [Version(Max = 22)] - public int marshalingFunctionsIndex; - [Version(Min = 21, Max = 22)] - public int ccwFunctionIndex; - [Version(Min = 21, Max = 22)] - public int guidIndex; - - public uint flags; - - public int fieldStart; - public int methodStart; - public int eventStart; - public int propertyStart; - public int nestedTypesStart; - public int interfacesStart; - public int vtableStart; - public int interfaceOffsetsStart; - - public ushort method_count; - public ushort property_count; - public ushort field_count; - public ushort event_count; - public ushort nested_type_count; - public ushort vtable_count; - public ushort interfaces_count; - public ushort interface_offsets_count; - - // bitfield to portably encode boolean values as single bits - // 01 - valuetype; - // 02 - enumtype; - // 03 - has_finalize; - // 04 - has_cctor; - // 05 - is_blittable; - // 06 - is_import; (from v22: is_import_or_windows_runtime) - // 07-10 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128) - public uint bitfield; - - [Version(Min = 19)] - public uint token; - } - - public class Il2CppMethodDefinition - { - public int nameIndex; - - [Version(Min = 16)] - public int declaringType; - - public int returnType; - - [Version(Min = 31)] - public int returnParameterToken; - - public int parameterStart; - - [Version(Max = 24.0)] - public int customAttributeIndex; - - public int genericContainerIndex; - - [Version(Max = 24.1)] - public int methodIndex; - [Version(Max = 24.1)] - public int invokerIndex; - [Version(Max = 24.1)] - public int reversePInvokeWrapperIndex; // (was renamed from delegateWrapperIndex in v22) - [Version(Max = 24.1)] - public int rgctxStartIndex; - [Version(Max = 24.1)] - public int rgctxCount; - - public uint token; - public ushort flags; - public ushort iflags; - public ushort slot; - public ushort parameterCount; - - [Version(Min = 29.2, Max = 29.2)] - [Version(Min = 31.2, Max = 31.2)] - public bool isUnmanagedCallersOnly; - } - - public class Il2CppParameterDefinition - { - public int nameIndex; - public uint token; - - [Version(Max = 24.0)] - public int customAttributeIndex; - - public int typeIndex; - } - - public class Il2CppParameterDefaultValue - { - public int parameterIndex; - public int typeIndex; - public int dataIndex; - } - - public class Il2CppFieldDefinition - { - public int nameIndex; - public int typeIndex; - - [Version(Max = 24.0)] - public int customAttributeIndex; - - [Version(Min = 19)] - public uint token; - } - - public class Il2CppFieldDefaultValue - { - public int fieldIndex; - public int typeIndex; - public int dataIndex; - } - - public class Il2CppPropertyDefinition - { - public int nameIndex; - public int get; - public int set; - public uint attrs; - - [Version(Max = 24.0)] - public int customAttributeIndex; - - [Version(Min = 19)] - public uint token; - } - - public class Il2CppEventDefinition - { - public int nameIndex; - public int typeIndex; - public int add; - public int remove; - public int raise; - - [Version(Max = 24.0)] - public int customAttributeIndex; - - [Version(Min = 19)] - public uint token; - } - - public class Il2CppGenericContainer - { - /* index of the generic type definition or the generic method definition corresponding to this container */ - public int ownerIndex; // either index into Il2CppClass metadata array or Il2CppMethodDefinition array - public int type_argc; - /* If true, we're a generic method, otherwise a generic type definition. */ - public int is_method; - /* Our type parameters. */ - public uint genericParameterStart; // GenericParameterIndex - } - - public class Il2CppGenericParameter - { - public int ownerIndex; /* Type or method this parameter was defined in. */ // GenericContainerIndex - public int nameIndex; // StringIndex - public short constraintsStart; // GenericParameterConstraintIndex - public short constraintsCount; - public ushort num; // Generic parameter position - public ushort flags; // GenericParameterAttributes - } - - public class Il2CppCustomAttributeTypeRange - { - [Version(Min = 24.1)] - public uint token; - - public int start; - public int count; - } - - public class Il2CppInterfaceOffsetPair - { - public int interfaceTypeIndex; - public int offset; - } - - // Removed in metadata v27 - public class Il2CppMetadataUsageList - { - public uint start; - public uint count; - } - - // Removed in metadata v27 - public class Il2CppMetadataUsagePair - { - public uint destinationindex; - public uint encodedSourceIndex; - } - - public class Il2CppStringLiteral - { - public int length; - public int dataIndex; - } - - public class Il2CppFieldRef - { - public int typeIndex; - public int fieldIndex; // local offset into type fields - } - - public class Il2CppCustomAttributeDataRange - { - public uint token; - public uint startOffset; - } -} diff --git a/Il2CppInspector.Common/Il2CppInspector.csproj b/Il2CppInspector.Common/Il2CppInspector.csproj index bf4f2d7..fa982aa 100644 --- a/Il2CppInspector.Common/Il2CppInspector.csproj +++ b/Il2CppInspector.Common/Il2CppInspector.csproj @@ -2,6 +2,8 @@ net9.0 + enable + preview Il2CppInspector.Common Katy Coe 2023.1 @@ -47,7 +49,7 @@ - + diff --git a/Il2CppInspector.Common/Model/AddressMap.cs b/Il2CppInspector.Common/Model/AddressMap.cs index 2fa7fde..44aa0c1 100644 --- a/Il2CppInspector.Common/Model/AddressMap.cs +++ b/Il2CppInspector.Common/Model/AddressMap.cs @@ -126,7 +126,7 @@ namespace Il2CppInspector.Model if (Model.Package.Version >= MetadataVersions.V242) { // TODO: Add some kind of AppArray composite type for arrays as we'll be adding more later - Add(binary.CodeRegistration.pcodeGenModules, binary.CodeGenModulePointers); + Add(binary.CodeRegistration.CodeGenModules, binary.CodeGenModulePointers); foreach (var ptr in binary.CodeGenModulePointers) Add(ptr.Value, binary.Modules[ptr.Key]); diff --git a/Il2CppInspector.Common/Model/AppModel.cs b/Il2CppInspector.Common/Model/AppModel.cs index 65adac9..1f3b3e3 100644 --- a/Il2CppInspector.Common/Model/AppModel.cs +++ b/Il2CppInspector.Common/Model/AppModel.cs @@ -253,11 +253,11 @@ namespace Il2CppInspector.Model case MetadataUsageType.FieldInfo or MetadataUsageType.FieldRva: var fieldRef = TypeModel.Package.FieldRefs[usage.SourceIndex]; var fieldType = TypeModel.GetMetadataUsageType(usage); - var field = fieldType.DeclaredFields.First(f => f.Index == fieldType.Definition.fieldStart + fieldRef.fieldIndex); + var field = fieldType.DeclaredFields.First(f => f.Index == fieldType.Definition.FieldIndex + fieldRef.FieldIndex); var value = field.HasFieldRVA ? Convert.ToHexString(Package.Metadata.ReadBytes( - (long) field.DefaultValueMetadataAddress, field.FieldType.Sizes.nativeSize)) + (long) field.DefaultValueMetadataAddress, field.FieldType.Sizes.NativeSize)) : ""; diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppArrayType.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppArrayType.cs new file mode 100644 index 0000000..1296aaa --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppArrayType.cs @@ -0,0 +1,18 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppArrayType +{ + public Pointer ElementType; + public byte Rank; + public byte NumSizes; + public byte NumLowerBound; + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong Sizes; // int* + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong LoBounds; // int* +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppCodeGenModule.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppCodeGenModule.cs new file mode 100644 index 0000000..f9f1808 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppCodeGenModule.cs @@ -0,0 +1,61 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppCodeGenModule +{ + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong ModuleName; // const char* + + [Aligned(0)] + public uint MethodPointerCount; + + public Pointer MethodPointers; + + [Aligned(0)] + [VersionCondition(EqualTo = "24.5")] + [VersionCondition(GreaterThan = "27.1")] + public uint AdjustorThunksCount; + + [VersionCondition(EqualTo = "24.5")] + [VersionCondition(GreaterThan = "27.1")] + public Pointer AdjustorThunks; + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong InvokerIndices; // int* + + [Aligned(0)] + public uint ReversePInvokeWrapperCount; + + public Pointer ReversePInvokeWrapperIndices; + + [Aligned(0)] + public uint RgctxRangesCount; + public Pointer RgctxRanges; + + [Aligned(0)] + public uint RgctxsCount; + public Pointer Rgctxs; + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong DebuggerMetadata; // Pointer DebuggerMetadata; + + [VersionCondition(GreaterThan = "27.0", LessThan = "27.2")] + public Pointer CustomAttributeCacheGenerator; + + [VersionCondition(GreaterThan = "27.0")] + public Il2CppMethodPointer ModuleInitializer; + + [VersionCondition(GreaterThan = "27.0")] + [Aligned(0)] + public ulong StaticConstructorTypeIndices; // TypeDefinitionIndex* + + [VersionCondition(GreaterThan = "27.0")] + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong MetadataRegistration; // Pointer + + [VersionCondition(GreaterThan = "27.0")] + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong CodeRegistration; // Pointer +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppCodeRegistration.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppCodeRegistration.cs new file mode 100644 index 0000000..428f044 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppCodeRegistration.cs @@ -0,0 +1,101 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using InvokerMethod = Il2CppMethodPointer; + +[VersionedStruct] +public partial struct Il2CppCodeRegistration +{ + [VersionCondition(LessThan = "24.1"), Aligned(0)] + public uint MethodPointersCount; + + [VersionCondition(LessThan = "24.1")] + public Pointer MethodPointers; + + [Aligned(0)] + public uint ReversePInvokeWrapperCount; + + public Pointer ReversePInvokeWrappers; + + [VersionCondition(LessThan = "22.0"), Aligned(0)] + public uint DelegateWrappersFromManagedToNativeCount; + + [VersionCondition(LessThan = "22.0")] + public Pointer DelegateWrappersFromManagedToNative; + + [VersionCondition(LessThan = "22.0"), Aligned(0)] + public uint MarshalingFunctionsCount; + + [VersionCondition(LessThan = "22.0")] + public Pointer MarshalingFunctions; + + [VersionCondition(GreaterThan = "21.0", LessThan = "22.0"), Aligned(0)] + public uint CcwMarshalingFunctionsCount; + + [VersionCondition(GreaterThan = "21.0", LessThan = "22.0")] + public Pointer CcwMarshalingFunctions; + + [Aligned(0)] + public uint GenericMethodPointersCount; + + public Pointer GenericMethodPointers; + + [VersionCondition(EqualTo = "24.5")] + [VersionCondition(GreaterThan = "27.1")] + public Pointer GenericAdjustorThunks; + + [Aligned(0)] + public uint InvokerPointersCount; + + public Pointer InvokerPointers; + + [VersionCondition(LessThan = "24.5"), Aligned(0)] + public int CustomAttributeCount; + + [VersionCondition(LessThan = "24.5")] + public Pointer CustomAttributeGenerators; + + [VersionCondition(GreaterThan = "21.0", LessThan = "22.0"), Aligned(0)] + public int GuidCount; + + [VersionCondition(GreaterThan = "21.0", LessThan = "22.0")] + public Pointer Guids; + + [VersionCondition(GreaterThan = "22.0", LessThan = "29.0")] + public int UnresolvedVirtualCallCount; + + [VersionCondition(EqualTo = "29.1"), VersionCondition(EqualTo = "31.1")] + [VersionCondition(EqualTo = "29.2"), VersionCondition(EqualTo = "31.2")] + [Aligned(0)] + public uint UnresolvedIndirectCallCount; // UnresolvedVirtualCallCount pre 29.1 + + [VersionCondition(GreaterThan = "22.0")] + public Pointer UnresolvedVirtualCallPointers; + + [VersionCondition(EqualTo = "29.1"), VersionCondition(EqualTo = "31.1")] + [VersionCondition(EqualTo = "29.2"), VersionCondition(EqualTo = "31.2")] + public Pointer UnresolvedInstanceCallWrappers; + + [VersionCondition(EqualTo = "29.1"), VersionCondition(EqualTo = "31.1")] + [VersionCondition(EqualTo = "29.2"), VersionCondition(EqualTo = "31.2")] + public Pointer UnresolvedStaticCallPointers; + + [VersionCondition(GreaterThan = "23.0"), Aligned(0)] + public uint InteropDataCount; + + [VersionCondition(GreaterThan = "23.0")] + public Pointer InteropData; + + [VersionCondition(GreaterThan = "24.3"), Aligned(0)] + public uint WindowsRuntimeFactoryCount; + + [VersionCondition(GreaterThan = "24.3")] + public Pointer WindowsRuntimeFactoryTable; + + [VersionCondition(GreaterThan = "24.2"), Aligned(0)] + public uint CodeGenModulesCount; + + [VersionCondition(GreaterThan = "24.2")] + public Pointer> CodeGenModules; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericClass.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericClass.cs new file mode 100644 index 0000000..9259a0c --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericClass.cs @@ -0,0 +1,18 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppGenericClass +{ + [VersionCondition(LessThan = "24.5"), Aligned(0)] + public int TypeDefinitionIndex; + + [VersionCondition(GreaterThan = "27.0")] + public Pointer Type; + + public Il2CppGenericContext Context; + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong CachedClass; // Il2CppClass*, optional +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericContext.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericContext.cs new file mode 100644 index 0000000..1737bcf --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericContext.cs @@ -0,0 +1,10 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppGenericContext +{ + public Pointer ClassInst; + public Pointer MethodInst; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericInst.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericInst.cs new file mode 100644 index 0000000..0a55c91 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericInst.cs @@ -0,0 +1,14 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppGenericInst +{ + public readonly bool Valid => TypeArgc > 0; + + [Aligned(0)] + public uint TypeArgc; + + public Pointer> TypeArgv; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericMethodFunctionsDefinitions.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericMethodFunctionsDefinitions.cs new file mode 100644 index 0000000..97478ef --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericMethodFunctionsDefinitions.cs @@ -0,0 +1,12 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using GenericMethodIndex = int; + +[VersionedStruct] +public partial struct Il2CppGenericMethodFunctionsDefinitions +{ + public GenericMethodIndex GenericMethodIndex; + public Il2CppGenericMethodIndices Indices; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericMethodIndices.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericMethodIndices.cs new file mode 100644 index 0000000..e18bf10 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGenericMethodIndices.cs @@ -0,0 +1,16 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using MethodIndex = int; + +[VersionedStruct] +public partial struct Il2CppGenericMethodIndices +{ + public MethodIndex MethodIndex; + public MethodIndex InvokerIndex; + + [VersionCondition(EqualTo = "24.5")] + [VersionCondition(GreaterThan = "27.1")] + public MethodIndex AdjustorThunkIndex; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGuid.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGuid.cs new file mode 100644 index 0000000..341ab1e --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppGuid.cs @@ -0,0 +1,22 @@ +using VersionedSerialization; + +namespace Il2CppInspector.Next.BinaryMetadata; + + +public struct Il2CppGuid : IReadable +{ + public Guid Value; + + public void Read(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct + { + var guid = reader.ReadBytes(16); + Value = new Guid(guid, false); + } + + public static int Size(in StructVersion version = default, bool is32Bit = false) + { + return 16; + } + + public static implicit operator Guid(Il2CppGuid value) => value.Value; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppInteropData.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppInteropData.cs new file mode 100644 index 0000000..9305569 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppInteropData.cs @@ -0,0 +1,20 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using PInvokeMarshalToNativeFunc = Il2CppMethodPointer; +using PInvokeMarshalFromNativeFunc = Il2CppMethodPointer; +using PInvokeMarshalCleanupFunc = Il2CppMethodPointer; +using CreateCCWFunc = Il2CppMethodPointer; + +[VersionedStruct] +public partial struct Il2CppInteropData +{ + public Il2CppMethodPointer DelegatePInvokeWrapperFunction; + public PInvokeMarshalToNativeFunc PInvokeMarshalToNativeFunction; + public PInvokeMarshalFromNativeFunc PInvokeMarshalFromNativeFunction; + public PInvokeMarshalCleanupFunc PInvokeMarshalCleanupFunction; + public CreateCCWFunc CreateCCWFunction; + public Pointer Guid; + public Pointer Type; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMetadataRegistration.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMetadataRegistration.cs new file mode 100644 index 0000000..2df65c9 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMetadataRegistration.cs @@ -0,0 +1,60 @@ +using Il2CppInspector.Next.Metadata; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using FieldIndex = int; +using TypeDefinitionIndex = int; + +[VersionedStruct] +public partial struct Il2CppMetadataRegistration +{ + [Aligned(0)] + public int GenericClassesCount; + + public Pointer> GenericClasses; + + [Aligned(0)] + public int GenericInstsCount; + + public Pointer> GenericInsts; + + [Aligned(0)] + public int GenericMethodTableCount; + + public Pointer GenericMethodTable; + + [Aligned(0)] + public int TypesCount; + + public Pointer> Types; + + [Aligned(0)] + public int MethodSpecsCount; + + public Pointer MethodSpecs; + + [VersionCondition(LessThan = "16.0")] + public int MethodReferencesCount; + + [VersionCondition(LessThan = "16.0")] + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong MethodReferences; // uint** + + [Aligned(0)] + public FieldIndex FieldOffsetsCount; + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong FieldOffsets; // int** + + [Aligned(0)] + public TypeDefinitionIndex TypeDefinitionsSizesCount; + public Pointer> TypeDefinitionsSizes; + + [Aligned(0)] + [VersionCondition(GreaterThan = "19.0")] + public ulong MetadataUsagesCount; + + [VersionCondition(GreaterThan = "19.0")] + public Pointer> MetadataUsages; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMethodPointer.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMethodPointer.cs new file mode 100644 index 0000000..a6d1005 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMethodPointer.cs @@ -0,0 +1,19 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppMethodPointer(ulong addr = 0) +{ + public static readonly Il2CppMethodPointer Null = new(); + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong Value { get; set; } = addr; + + public readonly bool IsNull => Value == 0; + + public readonly override string ToString() => $"0x{Value:X}"; + + public static implicit operator ulong(Il2CppMethodPointer ptr) => ptr.Value; + public static implicit operator Il2CppMethodPointer(ulong ptr) => new(ptr); +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMethodSpec.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMethodSpec.cs new file mode 100644 index 0000000..0fa7d04 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppMethodSpec.cs @@ -0,0 +1,14 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using MethodIndex = int; +using GenericInstIndex = int; + +[VersionedStruct] +public partial struct Il2CppMethodSpec +{ + public MethodIndex MethodDefinitionIndex; + public GenericInstIndex ClassIndexIndex; + public GenericInstIndex MethodIndexIndex; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRange.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRange.cs new file mode 100644 index 0000000..557861e --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRange.cs @@ -0,0 +1,10 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppRange +{ + public int Start; + public int Length; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxConstrainedData.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxConstrainedData.cs new file mode 100644 index 0000000..f51ddd3 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxConstrainedData.cs @@ -0,0 +1,13 @@ +using Il2CppInspector.Next.Metadata; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using TypeIndex = int; + +[VersionedStruct] +public partial struct Il2CppRgctxConstrainedData +{ + public TypeIndex TypeIndex; + public Il2CppMetadataUsage EncodedMethodIndex; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDataType.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDataType.cs new file mode 100644 index 0000000..fecde53 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDataType.cs @@ -0,0 +1,12 @@ +// ReSharper disable InconsistentNaming +namespace Il2CppInspector.Next.BinaryMetadata; + +public enum Il2CppRgctxDataType +{ + IL2CPP_RGCTX_DATA_INVALID, + IL2CPP_RGCTX_DATA_TYPE, + IL2CPP_RGCTX_DATA_CLASS, + IL2CPP_RGCTX_DATA_METHOD, + IL2CPP_RGCTX_DATA_ARRAY, + IL2CPP_RGCTX_DATA_CONSTRAINED, +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDefinition.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDefinition.cs new file mode 100644 index 0000000..0fb2efe --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDefinition.cs @@ -0,0 +1,16 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppRgctxDefinition +{ + [Aligned(0)] + public Il2CppRgctxDataType Type; + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong Data; // void* + + public readonly Pointer Definition => Data; + public readonly Pointer Constrained => Data; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDefinitionData.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDefinitionData.cs new file mode 100644 index 0000000..a6b19a2 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppRgctxDefinitionData.cs @@ -0,0 +1,15 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using MethodIndex = int; +using TypeIndex = int; + +[VersionedStruct] +public partial struct Il2CppRgctxDefinitionData +{ + public int Value; + + public readonly MethodIndex MethodIndex => Value; + public readonly TypeIndex TypeIndex => Value; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenAdjustorThunkPair.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenAdjustorThunkPair.cs new file mode 100644 index 0000000..e6ac2c5 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenAdjustorThunkPair.cs @@ -0,0 +1,12 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppTokenAdjustorThunkPair +{ + [Aligned(0)] + public uint Token; + + public Il2CppMethodPointer AdjustorThunk; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenIndexMethodTuple.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenIndexMethodTuple.cs new file mode 100644 index 0000000..6109901 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenIndexMethodTuple.cs @@ -0,0 +1,15 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppTokenIndexMethodTuple +{ + public uint Token; + public int Index; + + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + public ulong Method; // void** + + public uint GenericMethodIndex; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenRangePair.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenRangePair.cs new file mode 100644 index 0000000..dfc7836 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTokenRangePair.cs @@ -0,0 +1,10 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppTokenRangePair +{ + public uint Token; + public Il2CppRange Range; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppType.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppType.cs new file mode 100644 index 0000000..7b518ac --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppType.cs @@ -0,0 +1,111 @@ +using Il2CppInspector.Next.Metadata; +using System.Reflection; +using VersionedSerialization; + +namespace Il2CppInspector.Next.BinaryMetadata; + +using TypeDefinitionIndex = int; +using GenericParameterIndex = int; +using Il2CppMetadataTypeHandle = Pointer; +using Il2CppMetadataGenericParameterHandle = Pointer; + +public record struct Il2CppType : IReadable +{ + public record struct DataUnion : IReadable + { + public ulong Value; + + public readonly TypeDefinitionIndex KlassIndex => (int)Value; + public readonly Il2CppMetadataTypeHandle TypeHandle => Value; + public readonly Pointer Type => Value; + public readonly Pointer ArrayType => Value; + public readonly GenericParameterIndex GenericParameterIndex => (int)Value; + public readonly Il2CppMetadataGenericParameterHandle GenericParameterHandle => Value; + public readonly Pointer GenericClass => Value; + + public void Read(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct + { + Value = reader.ReadNUInt(); + } + + public static int Size(in StructVersion version = default, bool is32Bit = false) + { + return is32Bit ? 4 : 8; + } + } + + public DataUnion Data; + public uint Value; + + public TypeAttributes Attrs + { + readonly get => (TypeAttributes)(Value & 0xFFFF); + set => Value = (Value & 0xFFFF0000) | (uint)value; + } + + public Il2CppTypeEnum Type + { + readonly get => (Il2CppTypeEnum)((Value >> 16) & 0b11111111); + set => Value = (Value & 0xFF00FFFF) | ((uint)value) << 16; + } + + public uint NumModifiers + { + readonly get => (Value >> 24) & 0b11111; + set => Value = (Value & 0xE0FFFFFF) | value << 24; + } + + public bool ByRef + { + readonly get => ((Value >> 29) & 1) == 1; + set => Value = (Value & 0xDFFFFFFF) | (value ? 1u : 0u) << 29; + } + + public bool Pinned + { + readonly get => ((Value >> 30) & 1) == 1; + set => Value = (Value & 0xBFFFFFFF) | (value ? 1u : 0u) << 30; + } + + public bool ValueType + { + readonly get => ((Value >> 31) & 1) == 1; + set => Value = (Value & 0x7FFFFFFF) | (value ? 1u : 0u) << 31; + } + + public void Read(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct + { + Data.Read(ref reader, version); + Value = reader.Read(); + + if (MetadataVersions.V272 > version) + { + // Versions pre-27.2 had NumModifiers at 6 bits and no ValueType bit + var numModifiers = (Value >> 24) & 0b111111; + + // If NumModifiers > 31, we throw here (as the old behavior isn't implemented + if (numModifiers > 31) + throw new InvalidOperationException( + "Versions pre-27.2 with a type having more than 31 modifiers are not supported yet"); + + // Else, we do some bit-juggling to convert the old value into the new format: + Value = + (Value & 0xFFFFFF) | // Attributes + Type + (((Value >> 24) & 0b111111) << 24) | // 5 Bits for the modifiers + (((Value >> 30) & 1) << 29) | // Shifted ByRef + (((Value >> 31) & 1) << 30) | // Shifted Pinned + 0; // 0 ValueType + } + } + + public static int Size(in StructVersion version = default, bool is32Bit = false) + { + return DataUnion.Size(version, is32Bit) + sizeof(uint); + } + + public static Il2CppType FromTypeEnum(Il2CppTypeEnum type) + => new() + { + Value = (uint)type << 16 + }; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeDefinitionSizes.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeDefinitionSizes.cs new file mode 100644 index 0000000..dc46ae4 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeDefinitionSizes.cs @@ -0,0 +1,12 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppTypeDefinitionSizes +{ + public uint InstanceSize; + public int NativeSize; + public uint StaticFieldsSize; + public uint ThreadStaticFieldsSize; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeEnum.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeEnum.cs new file mode 100644 index 0000000..0c44142 --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeEnum.cs @@ -0,0 +1,45 @@ +// ReSharper disable InconsistentNaming +namespace Il2CppInspector.Next.BinaryMetadata; + +public enum Il2CppTypeEnum : byte +{ + Il2CPP_TYPE_END, + IL2CPP_TYPE_VOID, + IL2CPP_TYPE_BOOLEAN, + IL2CPP_TYPE_CHAR, + IL2CPP_TYPE_I1, + IL2CPP_TYPE_U1, + IL2CPP_TYPE_I2, + IL2CPP_TYPE_U2, + IL2CPP_TYPE_I4, + IL2CPP_TYPE_U4, + IL2CPP_TYPE_I8, + IL2CPP_TYPE_U8, + IL2CPP_TYPE_R4, + IL2CPP_TYPE_R8, + IL2CPP_TYPE_STRING, + IL2CPP_TYPE_PTR, + IL2CPP_TYPE_BYREF, + IL2CPP_TYPE_VALUETYPE, + IL2CPP_TYPE_CLASS, + IL2CPP_TYPE_VAR, + IL2CPP_TYPE_ARRAY, + IL2CPP_TYPE_GENERICINST, + IL2CPP_TYPE_TYPEDBYREF, + IL2CPP_TYPE_I = 0x18, + IL2CPP_TYPE_U, + IL2CPP_TYPE_FNPTR = 0x1b, + IL2CPP_TYPE_OBJECT, + IL2CPP_TYPE_SZARRAY, + IL2CPP_TYPE_MVAR, + IL2CPP_TYPE_CMOD_REQD, + IL2CPP_TYPE_CMOD_OPT, + IL2CPP_TYPE_INTERNAL, + + IL2CPP_TYPE_MODIFIER = 0x40, + IL2CPP_TYPE_SENTINEL = 0x41, + IL2CPP_TYPE_PINNED = 0x45, + + IL2CPP_TYPE_ENUM = 0x55, + IL2CPP_TYPE_IL2CPP_TYPE_INDEX = 0xff +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppWindowsRuntimeFactoryTableEntry.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppWindowsRuntimeFactoryTableEntry.cs new file mode 100644 index 0000000..1c42edc --- /dev/null +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppWindowsRuntimeFactoryTableEntry.cs @@ -0,0 +1,10 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.BinaryMetadata; + +[VersionedStruct] +public partial struct Il2CppWindowsRuntimeFactoryTableEntry +{ + public Pointer Type; + public Il2CppMethodPointer CreateFactoryFunction; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppAssemblyDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppAssemblyDefinition.cs new file mode 100644 index 0000000..ca62195 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppAssemblyDefinition.cs @@ -0,0 +1,37 @@ +using System.Runtime.InteropServices; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using ImageIndex = int; + +[VersionedStruct] +[StructLayout(LayoutKind.Explicit)] +public partial struct Il2CppAssemblyDefinition +{ + [FieldOffset(20)] + [VersionCondition(LessThan = "15.0")] + public Il2CppAssemblyNameDefinition LegacyAname; + + [FieldOffset(0)] + public ImageIndex ImageIndex; + + [FieldOffset(4)] + [VersionCondition(GreaterThan = "24.1")] + public uint Token; + + [FieldOffset(8)] + [VersionCondition(LessThan = "24.0")] + public int CustomAttributeIndex; + + [FieldOffset(12)] + [VersionCondition(GreaterThan = "20.0")] + public int ReferencedAssemblyStart; + + [FieldOffset(16)] + [VersionCondition(GreaterThan = "20.0")] + public int ReferencedAssemblyCount; + + [FieldOffset(20)] + public Il2CppAssemblyNameDefinition Aname; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppAssemblyNameDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppAssemblyNameDefinition.cs new file mode 100644 index 0000000..f93ab69 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppAssemblyNameDefinition.cs @@ -0,0 +1,64 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using StringIndex = int; + +[InlineArray(PublicKeyLength)] +public struct PublicKeyToken +{ + private const int PublicKeyLength = 8; + + private byte _value; +} + +[VersionedStruct] +[StructLayout(LayoutKind.Explicit)] +public partial struct Il2CppAssemblyNameDefinition +{ + [FieldOffset(0)] + public StringIndex NameIndex; + + [FieldOffset(4)] + public StringIndex CultureIndex; + + [FieldOffset(8)] + [VersionCondition(LessThan = "24.3")] + public int HashValueIndex; + + [FieldOffset(12)] + public StringIndex PublicKeyIndex; + + [FieldOffset(44)] + [VersionCondition(LessThan = "15.0")] + [CustomSerialization("reader.Read();", "8")] + private PublicKeyToken _legacyPublicKeyToken; + + [FieldOffset(16)] + public AssemblyHashAlgorithm HashAlg; + + [FieldOffset(20)] + public int HashLen; + + [FieldOffset(24)] + public AssemblyNameFlags Flags; + + [FieldOffset(28)] + public int Major; + + [FieldOffset(32)] + public int Minor; + + [FieldOffset(36)] + public int Build; + + [FieldOffset(40)] + public int Revision; + + [FieldOffset(44)] + [CustomSerialization("reader.Read();", "8")] + public PublicKeyToken PublicKeyToken; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppCustomAttributeDataRange.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppCustomAttributeDataRange.cs new file mode 100644 index 0000000..a38db96 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppCustomAttributeDataRange.cs @@ -0,0 +1,10 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +[VersionedStruct] +public partial struct Il2CppCustomAttributeDataRange +{ + public uint Token { get; private set; } + public uint StartOffset { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppCustomAttributeTypeRange.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppCustomAttributeTypeRange.cs new file mode 100644 index 0000000..4be20de --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppCustomAttributeTypeRange.cs @@ -0,0 +1,13 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +[VersionedStruct] +public partial struct Il2CppCustomAttributeTypeRange +{ + [VersionCondition(GreaterThan = "24.1")] + public uint Token { get; private set; } + + public int Start { get; private set; } + public int Count { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppEventDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppEventDefinition.cs new file mode 100644 index 0000000..7658f5b --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppEventDefinition.cs @@ -0,0 +1,24 @@ +namespace Il2CppInspector.Next.Metadata; + +using StringIndex = int; +using TypeIndex = int; +using MethodIndex = int; +using VersionedSerialization.Attributes; + +[VersionedStruct] +public partial struct Il2CppEventDefinition +{ + public StringIndex NameIndex { get; private set; } + public TypeIndex TypeIndex { get; private set; } + public MethodIndex Add { get; private set; } + public MethodIndex Remove { get; private set; } + public MethodIndex Raise { get; private set; } + + [VersionCondition(LessThan = "24.0")] + public int CustomAttributeIndex { get; private set; } + + [VersionCondition(GreaterThan = "19.0")] + public uint Token { get; private set; } + + public readonly bool IsValid => NameIndex != 0; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefaultValue.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefaultValue.cs new file mode 100644 index 0000000..ed984e2 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefaultValue.cs @@ -0,0 +1,15 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using FieldIndex = int; +using TypeIndex = int; +using DefaultValueDataIndex = int; + +[VersionedStruct] +public partial struct Il2CppFieldDefaultValue +{ + public FieldIndex FieldIndex { get; private set; } + public TypeIndex TypeIndex { get; private set; } + public DefaultValueDataIndex DataIndex { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefinition.cs new file mode 100644 index 0000000..84d0ef4 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefinition.cs @@ -0,0 +1,20 @@ +namespace Il2CppInspector.Next.Metadata; + +using VersionedSerialization.Attributes; +using StringIndex = int; +using TypeIndex = int; + +[VersionedStruct] +public partial struct Il2CppFieldDefinition +{ + public StringIndex NameIndex { get; private set; } + public TypeIndex TypeIndex { get; private set; } + + [VersionCondition(LessThan = "24.0")] + public int CustomAttributeIndex { get; private set; } + + [VersionCondition(GreaterThan = "19.0")] + public uint Token { get; private set; } + + public readonly bool IsValid => NameIndex != 0; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldMarshaledSize.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldMarshaledSize.cs new file mode 100644 index 0000000..bc71ad7 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldMarshaledSize.cs @@ -0,0 +1,13 @@ +namespace Il2CppInspector.Next.Metadata; + +using VersionedSerialization.Attributes; +using FieldIndex = int; +using TypeIndex = int; + +[VersionedStruct] +public partial struct Il2CppFieldMarshaledSize +{ + public FieldIndex FieldIndex { get; private set; } + public TypeIndex TypeIndex { get; private set; } + public int MarshaledSize { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldRef.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldRef.cs new file mode 100644 index 0000000..d02500d --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldRef.cs @@ -0,0 +1,13 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using FieldIndex = int; +using TypeIndex = int; + +[VersionedStruct] +public partial struct Il2CppFieldRef +{ + public TypeIndex TypeIndex { get; private set; } + public FieldIndex FieldIndex { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppGenericContainer.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppGenericContainer.cs new file mode 100644 index 0000000..43421c3 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppGenericContainer.cs @@ -0,0 +1,13 @@ +namespace Il2CppInspector.Next.Metadata; + +using VersionedSerialization.Attributes; +using GenericParameterIndex = int; + +[VersionedStruct] +public partial struct Il2CppGenericContainer +{ + public int OwnerIndex { get; private set; } + public int TypeArgc { get; private set; } + public int IsMethod { get; private set; } + public GenericParameterIndex GenericParameterStart { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppGenericParameter.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppGenericParameter.cs new file mode 100644 index 0000000..beaa94a --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppGenericParameter.cs @@ -0,0 +1,21 @@ +using System.Reflection; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using GenericContainerIndex = int; +using StringIndex = int; +using GenericParameterConstraintIndex = short; + +[VersionedStruct] +public partial struct Il2CppGenericParameter +{ + public GenericContainerIndex OwnerIndex { get; private set; } + public StringIndex NameIndex { get; private set; } + public GenericParameterConstraintIndex ConstraintsStart { get; private set; } + public short ConstraintsCount { get; private set; } + public ushort Num { get; private set; } + public ushort Flags { get; private set; } + + public readonly GenericParameterAttributes Attributes => (GenericParameterAttributes)Flags; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppGlobalMetadataHeader.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppGlobalMetadataHeader.cs new file mode 100644 index 0000000..d137be3 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppGlobalMetadataHeader.cs @@ -0,0 +1,182 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +// Unity 4.6.1p5 - first release, no global-metadata.dat +// Unity 5.2.0f3 -> v15 +// Unity 5.3.0f4 -> v16 +// Unity 5.3.2f1 -> v19 +// Unity 5.3.3f1 -> v20 +// Unity 5.3.5f1 -> v21 +// Unity 5.5.0f3 -> v22 +// Unity 5.6.0f3 -> v23 +// Unity 2017.1.0f3 -> v24 +// Unity 2018.3.0f2 -> v24.1 +// Unity 2019.1.0f2 -> v24.2 +// Unity 2019.3.7f1 -> v24.3 +// Unity 2019.4.15f1 -> v24.4 +// Unity 2019.4.21f1 -> v24.5 +// Unity 2020.1.0f1 -> v24.3 +// Unity 2020.1.11f1 -> v24.4 +// Unity 2020.2.0f1 -> v27 +// Unity 2020.2.4f1 -> v27.1 +// Unity 2021.1.0f1 -> v27.2 +// https://unity3d.com/get-unity/download/archive +// Metadata version is written at the end of Unity.IL2CPP.MetadataCacheWriter.WriteLibIl2CppMetadata or WriteMetadata (Unity.IL2CPP.dll) + +[VersionedStruct] +public partial struct Il2CppGlobalMetadataHeader +{ + public int Sanity { get; private set; } + public int Version { get; private set; } + public int StringLiteralOffset { get; private set; } + public int StringLiteralSize { get; private set; } + public int StringLiteralDataOffset { get; private set; } + public int StringLiteralDataSize { get; private set; } + public int StringOffset { get; private set; } + public int StringSize { get; private set; } + public int EventsOffset { get; private set; } + public int EventsSize { get; private set; } + public int PropertiesOffset { get; private set; } + public int PropertiesSize { get; private set; } + public int MethodsOffset { get; private set; } + public int MethodsSize { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + [VersionCondition(EqualTo = "16.0")] + public int ParameterDefaultValuesOffset { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + [VersionCondition(EqualTo = "16.0")] + public int ParameterDefaultValuesSize { get; private set; } + public int FieldDefaultValuesOffset { get; private set; } + public int FieldDefaultValuesSize { get; private set; } + public int FieldAndParameterDefaultValueDataOffset { get; private set; } + public int FieldAndParameterDefaultValueDataSize { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + public int FieldMarshaledSizesOffset { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + public int FieldMarshaledSizesSize { get; private set; } + public int ParametersOffset { get; private set; } + public int ParametersSize { get; private set; } + public int FieldsOffset { get; private set; } + public int FieldsSize { get; private set; } + public int GenericParametersOffset { get; private set; } + public int GenericParametersSize { get; private set; } + public int GenericParameterConstraintsOffset { get; private set; } + public int GenericParameterConstraintsSize { get; private set; } + public int GenericContainersOffset { get; private set; } + public int GenericContainersSize { get; private set; } + public int NestedTypesOffset { get; private set; } + public int NestedTypesSize { get; private set; } + public int InterfacesOffset { get; private set; } + public int InterfacesSize { get; private set; } + public int VTableMethodsOffset { get; private set; } + public int VTableMethodsSize { get; private set; } + public int InterfaceOffsetsOffset { get; private set; } + public int InterfaceOffsetsSize { get; private set; } + public int TypeDefinitionsOffset { get; private set; } + public int TypeDefinitionsSize { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int RgctxEntriesOffset { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int RgctxEntriesCount { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + public int ImagesOffset { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + public int ImagesSize { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + public int AssembliesOffset { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + public int AssembliesSize { get; private set; } + + [VersionCondition(GreaterThan = "19.0", LessThan = "24.5")] + public int MetadataUsageListsOffset { get; private set; } + + [VersionCondition(GreaterThan = "19.0", LessThan = "24.5")] + public int MetadataUsageListsCount { get; private set; } + + [VersionCondition(GreaterThan = "19.0", LessThan = "24.5")] + public int MetadataUsagePairsOffset { get; private set; } + + [VersionCondition(GreaterThan = "19.0", LessThan = "24.5")] + public int MetadataUsagePairsCount { get; private set; } + + [VersionCondition(GreaterThan = "19.0")] + public int FieldRefsOffset { get; private set; } + + [VersionCondition(GreaterThan = "19.0")] + public int FieldRefsSize { get; private set; } + + [VersionCondition(GreaterThan = "20.0")] + public int ReferencedAssembliesOffset { get; private set; } + + [VersionCondition(GreaterThan = "20.0")] + public int ReferencedAssembliesSize { get; private set; } + + [VersionCondition(GreaterThan = "21.0", LessThan = "27.2")] + public int AttributesInfoOffset { get; private set; } + + [VersionCondition(GreaterThan = "21.0", LessThan = "27.2")] + public int AttributesInfoCount { get; private set; } + + [VersionCondition(GreaterThan = "21.0", LessThan = "27.2")] + public int AttributesTypesOffset { get; private set; } + + [VersionCondition(GreaterThan = "21.0", LessThan = "27.2")] + public int AttributesTypesCount { get; private set; } + + [VersionCondition(GreaterThan = "29.0")] + public int AttributeDataOffset { get; private set; } + + [VersionCondition(GreaterThan = "29.0")] + public int AttributeDataSize { get; private set; } + + [VersionCondition(GreaterThan = "29.0")] + public int AttributeDataRangeOffset { get; private set; } + + [VersionCondition(GreaterThan = "29.0")] + public int AttributeDataRangeSize { get; private set; } + + [VersionCondition(GreaterThan = "22.0")] + public int UnresolvedIndirectCallParameterTypesOffset { get; private set; } + + [VersionCondition(GreaterThan = "22.0")] + public int UnresolvedIndirectCallParameterTypesSize { get; private set; } + + [VersionCondition(GreaterThan = "22.0")] + public int UnresolvedIndirectCallParameterRangesOffset { get; private set; } + + [VersionCondition(GreaterThan = "22.0")] + public int UnresolvedIndirectCallParameterRangesSize { get; private set; } + + [VersionCondition(GreaterThan = "23.0")] + public int WindowsRuntimeTypeNamesOffset { get; private set; } + + [VersionCondition(GreaterThan = "23.0")] + public int WindowsRuntimeTypeNamesSize { get; private set; } + + [VersionCondition(GreaterThan = "27.0")] + public int WindowsRuntimeStringsOffset { get; private set; } + + [VersionCondition(GreaterThan = "27.0")] + public int WindowsRuntimeStringsSize { get; private set; } + + [VersionCondition(GreaterThan = "24.0")] + public int ExportedTypeDefinitionsOffset { get; private set; } + + [VersionCondition(GreaterThan = "24.0")] + public int ExportedTypeDefinitionsSize { get; private set; } + + + public const int ExpectedSanity = unchecked((int)0xFAB11BAF); + public readonly bool SanityValid => Sanity == ExpectedSanity; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppImageDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppImageDefinition.cs new file mode 100644 index 0000000..56bc753 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppImageDefinition.cs @@ -0,0 +1,37 @@ +namespace Il2CppInspector.Next.Metadata; + +using StringIndex = int; +using AssemblyIndex = int; +using TypeDefinitionIndex = int; +using MethodIndex = int; +using CustomAttributeIndex = int; +using VersionedSerialization.Attributes; + +[VersionedStruct] +public partial struct Il2CppImageDefinition +{ + public StringIndex NameIndex { get; private set; } + public AssemblyIndex AssemblyIndex { get; private set; } + + public TypeDefinitionIndex TypeStart { get; private set; } + public uint TypeCount { get; private set; } + + [VersionCondition(GreaterThan = "24.0")] + public TypeDefinitionIndex ExportedTypeStart { get; private set; } + + [VersionCondition(GreaterThan = "24.0")] + public uint ExportedTypeCount { get; private set; } + + public MethodIndex EntryPointIndex { get; private set; } + + [VersionCondition(GreaterThan = "19.0")] + public uint Token { get; private set; } + + [VersionCondition(GreaterThan = "24.1")] + public CustomAttributeIndex CustomAttributeStart { get; private set; } + + [VersionCondition(GreaterThan = "24.1")] + public uint CustomAttributeCount { get; private set; } + + public readonly bool IsValid => NameIndex != 0; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppInterfaceOffsetPair.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppInterfaceOffsetPair.cs new file mode 100644 index 0000000..93337b2 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppInterfaceOffsetPair.cs @@ -0,0 +1,12 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using TypeIndex = int; + +[VersionedStruct] +public partial struct Il2CppInterfaceOffsetPair +{ + public TypeIndex InterfaceTypeIndex { get; private set; } + public int Offset { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataRange.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataRange.cs new file mode 100644 index 0000000..4ab7a24 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataRange.cs @@ -0,0 +1,10 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +[VersionedStruct] +public partial struct Il2CppMetadataRange +{ + public int Start { get; private set; } + public int Length { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsage.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsage.cs new file mode 100644 index 0000000..70855f1 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsage.cs @@ -0,0 +1,64 @@ +using System.Diagnostics; +using VersionedSerialization; + +namespace Il2CppInspector.Next.Metadata; + +using VersionedSerialization.Attributes; +using EncodedMethodIndex = uint; + +[VersionedStruct] +public partial struct Il2CppMetadataUsage +{ + private const uint TypeMask = 0b111u << 29; + private const uint InflatedMask = 0b1; + private const uint IndexMask = ~(TypeMask | InflatedMask); + + public readonly Il2CppMetadataUsageType Type => (Il2CppMetadataUsageType)((EncodedValue & TypeMask) >> 29); + public readonly uint Index => (EncodedValue & IndexMask) >> 1; + public readonly bool Inflated => (EncodedValue & InflatedMask) == 1; + + public EncodedMethodIndex EncodedValue; + + public static Il2CppMetadataUsage FromValue(in StructVersion version, uint encodedValue) + { + if (version >= MetadataVersions.V270) + { + return new Il2CppMetadataUsage + { + EncodedValue = encodedValue + }; + } + + if (version >= MetadataVersions.V190) + { + // Below v27 we need to fake the 'inflated' flag, so shift the value by one + + var type = (encodedValue & TypeMask) >> 29; + var value = encodedValue & (IndexMask | 1); + Debug.Assert((value & 0x10000000) == 0); + + return new Il2CppMetadataUsage + { + EncodedValue = (type << 29) | (value << 1) + }; + } + + /* These encoded indices appear only in vtables, and are decoded by IsGenericMethodIndex/GetDecodedMethodIndex */ + var methodType = (encodedValue >> 31) != 0 + ? Il2CppMetadataUsageType.MethodRef + : Il2CppMetadataUsageType.MethodDef; + + var index = encodedValue & 0x7FFFFFFF; + Debug.Assert((index & 0x60000000) == 0); + + return new Il2CppMetadataUsage + { + EncodedValue = ((uint)methodType << 29) | (index << 1) + }; + } + + public readonly override string ToString() + { + return $"{Type} @ 0x{Index:X}"; + } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsageList.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsageList.cs new file mode 100644 index 0000000..517a05a --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsageList.cs @@ -0,0 +1,10 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +[VersionedStruct] +public partial struct Il2CppMetadataUsageList +{ + public int Start { get; private set; } + public int Count { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsagePair.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsagePair.cs new file mode 100644 index 0000000..b5b2359 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsagePair.cs @@ -0,0 +1,10 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +[VersionedStruct] +public partial struct Il2CppMetadataUsagePair +{ + public uint DestinationIndex { get; private set; } + public uint EncodedSourceIndex { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsageType.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsageType.cs new file mode 100644 index 0000000..485036e --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsageType.cs @@ -0,0 +1,13 @@ +namespace Il2CppInspector.Next.Metadata; + +public enum Il2CppMetadataUsageType +{ + Invalid = 0b000, + TypeInfo = 0b001, + Il2CppType = 0b010, + MethodDef = 0b011, + FieldInfo = 0b100, + StringLiteral = 0b101, + MethodRef = 0b110, + FieldRva = 0b111, +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppMethodDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppMethodDefinition.cs new file mode 100644 index 0000000..360f0c5 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppMethodDefinition.cs @@ -0,0 +1,62 @@ +using System.Reflection; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using StringIndex = int; +using TypeDefinitionIndex = int; +using TypeIndex = int; +using ParameterIndex = int; +using GenericContainerIndex = int; + +[VersionedStruct] +public partial struct Il2CppMethodDefinition +{ + public StringIndex NameIndex { get; private set; } + + [VersionCondition(GreaterThan = "16.0")] + public TypeDefinitionIndex DeclaringType { get; private set; } + public TypeIndex ReturnType { get; private set; } + + [VersionCondition(EqualTo = "31.0")] + [VersionCondition(EqualTo = "31.1")] + [VersionCondition(EqualTo = "31.2")] + public uint ReturnParameterToken { get; private set; } + + public ParameterIndex ParameterStart { get; private set; } + + [VersionCondition(LessThan = "24.0")] + public int CustomAttributeIndex { get; private set; } + + public GenericContainerIndex GenericContainerIndex { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int MethodIndex { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int InvokerIndex { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int ReversePInvokeWrapperIndex { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int RgctxStartIndex { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int RgctxCount { get; private set; } + + public uint Token { get; private set; } + public ushort Flags { get; private set; } + public ushort ImplFlags { get; private set; } + public ushort Slot { get; private set; } + public ushort ParameterCount { get; private set; } + + [VersionCondition(EqualTo = "29.2")] + [VersionCondition(EqualTo = "31.2")] + public bool IsUnmanagedCallersOnly { get; private set; } + + public readonly MethodAttributes Attributes => (MethodAttributes)Flags; + public readonly MethodImplAttributes ImplAttributes => (MethodImplAttributes)ImplFlags; + + public readonly bool IsValid => NameIndex != 0; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefaultValue.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefaultValue.cs new file mode 100644 index 0000000..1a3e473 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefaultValue.cs @@ -0,0 +1,14 @@ +namespace Il2CppInspector.Next.Metadata; + +using ParameterIndex = int; +using TypeIndex = int; +using DefaultValueDataIndex = int; +using VersionedSerialization.Attributes; + +[VersionedStruct] +public partial struct Il2CppParameterDefaultValue +{ + public ParameterIndex ParameterIndex { get; private set; } + public TypeIndex TypeIndex { get; private set; } + public DefaultValueDataIndex DataIndex { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefinition.cs new file mode 100644 index 0000000..a66af4d --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefinition.cs @@ -0,0 +1,19 @@ +namespace Il2CppInspector.Next.Metadata; + +using VersionedSerialization.Attributes; +using StringIndex = int; +using TypeIndex = int; + +[VersionedStruct] +public partial struct Il2CppParameterDefinition +{ + public StringIndex NameIndex { get; private set; } + public uint Token { get; private set; } + + [VersionCondition(LessThan = "24.0")] + public int CustomAttributeIndex { get; private set; } + + public TypeIndex TypeIndex { get; private set; } + + public readonly bool IsValid => NameIndex != 0; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppPropertyDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppPropertyDefinition.cs new file mode 100644 index 0000000..6ba2ad8 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppPropertyDefinition.cs @@ -0,0 +1,24 @@ +using System.Reflection; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using StringIndex = int; +using MethodIndex = int; + +[VersionedStruct] +public partial struct Il2CppPropertyDefinition +{ + public StringIndex NameIndex { get; private set; } + public MethodIndex Get { get; private set; } + public MethodIndex Set { get; private set; } + public PropertyAttributes Attrs { get; private set; } + + [VersionCondition(LessThan = "24.0")] + public int CustomAttributeIndex { get; private set; } + + [VersionCondition(GreaterThan = "19.0")] + public uint Token { get; private set; } + + public readonly bool IsValid => NameIndex != 0; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppStringLiteral.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppStringLiteral.cs new file mode 100644 index 0000000..93f4ac6 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppStringLiteral.cs @@ -0,0 +1,11 @@ +namespace Il2CppInspector.Next.Metadata; + +using VersionedSerialization.Attributes; +using StringLiteralIndex = int; + +[VersionedStruct] +public partial struct Il2CppStringLiteral +{ + public uint Length { get; private set; } + public StringLiteralIndex DataIndex { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinition.cs new file mode 100644 index 0000000..cb89a97 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinition.cs @@ -0,0 +1,83 @@ +using System.Reflection; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +using StringIndex = int; +using TypeIndex = int; +using GenericContainerIndex = int; +using FieldIndex = int; +using MethodIndex = int; +using EventIndex = int; +using PropertyIndex = int; +using NestedTypeIndex = int; +using InterfacesIndex = int; +using VTableIndex = int; + +[VersionedStruct] +public partial struct Il2CppTypeDefinition +{ + public const TypeIndex InvalidTypeIndex = -1; + + public StringIndex NameIndex { get; private set; } + public StringIndex NamespaceIndex { get; private set; } + + [VersionCondition(LessThan = "24.0")] + public int CustomAttributeIndex { get; private set; } + + public TypeIndex ByValTypeIndex { get; private set; } + + [VersionCondition(LessThan = "24.5")] + public TypeIndex ByRefTypeIndex { get; private set; } + + public TypeIndex DeclaringTypeIndex { get; private set; } + public TypeIndex ParentIndex { get; private set; } + public TypeIndex ElementTypeIndex { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int RgctxStartIndex { get; private set; } + + [VersionCondition(LessThan = "24.1")] + public int RgctxCount { get; private set; } + + public GenericContainerIndex GenericContainerIndex { get; private set; } + + [VersionCondition(LessThan = "22.0")] + public int ReversePInvokeWrapperIndex { get; private set; } + + [VersionCondition(LessThan = "22.0")] + public int MarshalingFunctionsIndex { get; private set; } + + [VersionCondition(GreaterThan = "21.0", LessThan = "22.0")] + public int CcwFunctionIndex { get; private set; } + + [VersionCondition(GreaterThan = "21.0", LessThan = "22.0")] + public int GuidIndex { get; private set; } + + public TypeAttributes Flags { get; private set; } + + public FieldIndex FieldIndex { get; private set; } + public MethodIndex MethodIndex { get; private set; } + public EventIndex EventIndex { get; private set; } + public PropertyIndex PropertyIndex { get; private set; } + public NestedTypeIndex NestedTypeIndex { get; private set; } + public InterfacesIndex InterfacesIndex { get; private set; } + public VTableIndex VTableIndex { get; private set; } + public InterfacesIndex InterfaceOffsetsStart { get; private set; } + + public ushort MethodCount { get; private set; } + public ushort PropertyCount { get; private set; } + public ushort FieldCount { get; private set; } + public ushort EventCount { get; private set; } + public ushort NestedTypeCount { get; private set; } + public ushort VTableCount { get; private set; } + public ushort InterfacesCount { get; private set; } + public ushort InterfaceOffsetsCount { get; private set; } + + public Il2CppTypeDefinitionBitfield Bitfield { get; private set; } + + [VersionCondition(GreaterThan = "19.0")] + public uint Token { get; private set; } + + public readonly bool IsValid => NameIndex != 0; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinitionBitfield.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinitionBitfield.cs new file mode 100644 index 0000000..28875b8 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinitionBitfield.cs @@ -0,0 +1,21 @@ +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next.Metadata; + +[VersionedStruct] +public partial struct Il2CppTypeDefinitionBitfield +{ + private uint _value; + + public bool ValueType => ((_value >> 0) & 1) == 1; + public bool EnumType => ((_value >> 1) & 1) == 1; + public bool HasFinalize => ((_value >> 2) & 1) == 1; + public bool HasCctor => ((_value >> 3) & 1) == 1; + public bool IsBlittable => ((_value >> 4) & 1) == 1; + public bool IsImportOrWindowsRuntime => ((_value >> 5) & 1) == 1; + public PackingSize PackingSize => (PackingSize)((_value >> 6) & 0b1111); + public bool DefaultPackingSize => ((_value >> 10) & 1) == 1; + public bool DefaultClassSize => ((_value >> 11) & 1) == 1; + public PackingSize ClassSize => (PackingSize)((_value >> 12) & 0b1111); + public bool IsByRefLike => ((_value >> 13) & 1) == 1; +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppWindowsRuntimeTypeNamePair.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppWindowsRuntimeTypeNamePair.cs new file mode 100644 index 0000000..217a212 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppWindowsRuntimeTypeNamePair.cs @@ -0,0 +1,12 @@ +namespace Il2CppInspector.Next.Metadata; + +using VersionedSerialization.Attributes; +using StringIndex = int; +using TypeIndex = int; + +[VersionedStruct] +public partial struct Il2CppWindowsRuntimeTypeNamePair +{ + public StringIndex NameIndex { get; private set; } + public TypeIndex TypeIndex { get; private set; } +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/PackingSize.cs b/Il2CppInspector.Common/Next/Metadata/PackingSize.cs new file mode 100644 index 0000000..5938056 --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/PackingSize.cs @@ -0,0 +1,14 @@ +namespace Il2CppInspector.Next.Metadata; + +public enum PackingSize +{ + Zero, + One, + Two, + Four, + Eight, + Sixteen, + ThirtyTwo, + SixtyFour, + OneHundredTwentyEight +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Pointer.cs b/Il2CppInspector.Common/Next/Pointer.cs new file mode 100644 index 0000000..a3a1113 --- /dev/null +++ b/Il2CppInspector.Common/Next/Pointer.cs @@ -0,0 +1,60 @@ +using System.Collections.Immutable; +using VersionedSerialization; +using VersionedSerialization.Attributes; + +namespace Il2CppInspector.Next; + +public struct Pointer(ulong value = 0) : IReadable, IEquatable> where T : IReadable, new() +{ + [CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")] + private ulong _value = value; + + public readonly ulong PointerValue => _value; + public readonly bool Null => _value == 0; + + public void Read(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct + { + _value = reader.ReadNUInt(); + } + + public static int Size(in StructVersion version = default, bool is32Bit = false) + { + return is32Bit ? 4 : 8; + } + + public readonly T Read(ref SpanReader reader, in StructVersion version) + { + reader.Offset = (int)PointerValue; + return reader.ReadObject(version); + } + + public readonly ImmutableArray ReadArray(ref SpanReader reader, long count, in StructVersion version) + { + reader.Offset = (int)PointerValue; + return reader.ReadObjectArray(count, version); + } + + public static implicit operator Pointer(ulong value) => new(value); + public static implicit operator ulong(Pointer ptr) => ptr.PointerValue; + + #region Equality operators + ToString + + public static bool operator ==(Pointer left, Pointer right) + => left._value == right._value; + + public static bool operator !=(Pointer left, Pointer right) + => !(left == right); + + public readonly override bool Equals(object? obj) + => obj is Pointer other && Equals(other); + + public readonly bool Equals(Pointer other) + => this == other; + + public readonly override int GetHashCode() + => HashCode.Combine(_value); + + public readonly override string ToString() => $"0x{_value:X} <{typeof(T).Name}>"; + + #endregion +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Outputs/AssemblyShims.cs b/Il2CppInspector.Common/Outputs/AssemblyShims.cs index f54fa25..c111691 100644 --- a/Il2CppInspector.Common/Outputs/AssemblyShims.cs +++ b/Il2CppInspector.Common/Outputs/AssemblyShims.cs @@ -187,7 +187,7 @@ namespace Il2CppInspector.Outputs }; if (mType.IsExplicitLayout || mType.IsSequentialLayout) - mType.ClassLayout = new ClassLayoutUser(1, (uint)type.Sizes.nativeSize); + mType.ClassLayout = new ClassLayoutUser(1, (uint)type.Sizes.NativeSize); // Add nested types foreach (var nestedType in type.DeclaredNestedTypes) @@ -242,7 +242,7 @@ namespace Il2CppInspector.Outputs AddMethod(module, mType, method); // Add token attribute - if (type.Definition != null) + if (type.Definition.IsValid) mType.AddAttribute(module, tokenAttribute, ("Token", $"0x{type.MetadataToken:X8}")); // Add custom attribute attributes @@ -270,7 +270,7 @@ namespace Il2CppInspector.Outputs if (field.HasFieldRVA) { // Attempt to get field size - var fieldSize = field.FieldType.Sizes.nativeSize; + var fieldSize = field.FieldType.Sizes.NativeSize; var preview = model.Package.Metadata.ReadBytes((long) field.DefaultValueMetadataAddress, fieldSize); mField.InitialValue = preview; @@ -311,7 +311,7 @@ namespace Il2CppInspector.Outputs // Add token attribute // Generic properties and constructed properties (from disperate get/set methods) have no definition - if (prop.Definition != null) + if (prop.Definition.IsValid) mProp.AddAttribute(module, tokenAttribute, ("Token", $"0x{prop.MetadataToken:X8}")); // Add custom attribute attributes @@ -433,8 +433,8 @@ namespace Il2CppInspector.Outputs ("Offset", string.Format("0x{0:X}", model.Package.BinaryImage.MapVATR(method.VirtualAddress.Value.Start))), ("VA", method.VirtualAddress.Value.Start.ToAddressString()) }; - if (method.Definition.slot != ushort.MaxValue) - args.Add(("Slot", method.Definition.slot.ToString())); + if (method.Definition.Slot != ushort.MaxValue) + args.Add(("Slot", method.Definition.Slot.ToString())); mMethod.AddAttribute(module, addressAttribute, args.ToArray()); } @@ -649,7 +649,7 @@ namespace Il2CppInspector.Outputs AddCustomAttribute(module, module.Assembly, ca); // Add token attributes - module.AddAttribute(module, tokenAttribute, ("Token", $"0x{asm.ImageDefinition.token:X8}")); + module.AddAttribute(module, tokenAttribute, ("Token", $"0x{asm.ImageDefinition.Token:X8}")); module.Assembly.AddAttribute(module, tokenAttribute, ("Token", $"0x{asm.MetadataToken:X8}")); if (types.TryGetValue(module, out var shallowTypes)) diff --git a/Il2CppInspector.Common/Outputs/CSharpCodeStubs.cs b/Il2CppInspector.Common/Outputs/CSharpCodeStubs.cs index 1d6b204..52768a7 100644 --- a/Il2CppInspector.Common/Outputs/CSharpCodeStubs.cs +++ b/Il2CppInspector.Common/Outputs/CSharpCodeStubs.cs @@ -353,7 +353,7 @@ namespace Il2CppInspector.Outputs foreach (var asm in assemblies) { text.Append($"// Image {asm.Index}: {asm.ShortName} - Assembly: {asm.FullName}"); if (!SuppressMetadata) - text.Append($" - Types {asm.ImageDefinition.typeStart}-{asm.ImageDefinition.typeStart + asm.ImageDefinition.typeCount - 1}"); + text.Append($" - Types {asm.ImageDefinition.TypeStart}-{asm.ImageDefinition.TypeStart + asm.ImageDefinition.TypeCount - 1}"); text.AppendLine(); // Assembly-level attributes @@ -426,7 +426,7 @@ namespace Il2CppInspector.Outputs sb.Append($" // Metadata: {field.DefaultValueMetadataAddress.ToAddressString()}"); // For static array initializers, output metadata address and preview if (field.HasFieldRVA && !SuppressMetadata) { - var preview = model.Package.Metadata.ReadBytes((long) field.DefaultValueMetadataAddress, field.FieldType.Sizes.nativeSize); + var preview = model.Package.Metadata.ReadBytes((long) field.DefaultValueMetadataAddress, field.FieldType.Sizes.NativeSize); sb.Append($" // Static value (base64): {Convert.ToBase64String(preview)} - Metadata: {field.DefaultValueMetadataAddress.ToAddressString()}"); } sb.Append("\n"); diff --git a/Il2CppInspector.Common/Outputs/JSONMetadata.cs b/Il2CppInspector.Common/Outputs/JSONMetadata.cs index 42df77c..57a27c0 100644 --- a/Il2CppInspector.Common/Outputs/JSONMetadata.cs +++ b/Il2CppInspector.Common/Outputs/JSONMetadata.cs @@ -184,7 +184,7 @@ namespace Il2CppInspector.Outputs // TODO: In the future, add data ranges for the entire IL2CPP metadata tree writeArray("arrayMetadata", () => { if (model.Package.Version >= MetadataVersions.V242) { - writeObject(() => writeTypedArray(binary.CodeRegistration.pcodeGenModules, binary.Modules.Count, "struct Il2CppCodeGenModule *", "g_CodeGenModules")); + writeObject(() => writeTypedArray(binary.CodeRegistration.CodeGenModules, binary.Modules.Count, "struct Il2CppCodeGenModule *", "g_CodeGenModules")); } }, "IL2CPP Array Metadata"); } diff --git a/Il2CppInspector.Common/Reflection/Assembly.cs b/Il2CppInspector.Common/Reflection/Assembly.cs index a84a6e4..30b0b10 100644 --- a/Il2CppInspector.Common/Reflection/Assembly.cs +++ b/Il2CppInspector.Common/Reflection/Assembly.cs @@ -7,6 +7,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Il2CppInspector.Next.BinaryMetadata; +using Il2CppInspector.Next.Metadata; namespace Il2CppInspector.Reflection { public class Assembly @@ -43,37 +45,37 @@ namespace Il2CppInspector.Reflection { public Assembly(TypeModel model, int imageIndex) { Model = model; ImageDefinition = Model.Package.Images[imageIndex]; - AssemblyDefinition = Model.Package.Assemblies[ImageDefinition.assemblyIndex]; + AssemblyDefinition = Model.Package.Assemblies[ImageDefinition.AssemblyIndex]; - if (AssemblyDefinition.imageIndex != imageIndex) + if (AssemblyDefinition.ImageIndex != imageIndex) throw new InvalidOperationException("Assembly/image index mismatch"); - MetadataToken = (int) AssemblyDefinition.token; - Index = ImageDefinition.assemblyIndex; - ShortName = Model.Package.Strings[ImageDefinition.nameIndex]; + MetadataToken = (int) AssemblyDefinition.Token; + Index = ImageDefinition.AssemblyIndex; + ShortName = Model.Package.Strings[ImageDefinition.NameIndex]; // Get full assembly name - var nameDef = AssemblyDefinition.aname; - var name = Regex.Replace(Model.Package.Strings[nameDef.nameIndex], @"[^A-Za-z0-9_\-\.()]", ""); - var culture = Model.Package.Strings[nameDef.cultureIndex]; + var nameDef = AssemblyDefinition.Aname; + var name = Regex.Replace(Model.Package.Strings[nameDef.NameIndex], @"[^A-Za-z0-9_\-\.()]", ""); + var culture = Model.Package.Strings[nameDef.CultureIndex]; if (string.IsNullOrEmpty(culture)) culture = "neutral"; - var pkt = BitConverter.ToString(nameDef.publicKeyToken).Replace("-", ""); + var pkt = Convert.ToHexString(nameDef.PublicKeyToken); if (pkt == "0000000000000000") pkt = "null"; - var version = string.Format($"{nameDef.major}.{nameDef.minor}.{nameDef.build}.{nameDef.revision}"); + var version = string.Format($"{nameDef.Major}.{nameDef.Minor}.{nameDef.Build}.{nameDef.Revision}"); FullName = string.Format($"{name}, Version={version}, Culture={culture}, PublicKeyToken={pkt.ToLower()}"); - if (ImageDefinition.entryPointIndex != -1) { + if (ImageDefinition.EntryPointIndex != -1) { // TODO: Generate EntryPoint method from entryPointIndex } // Find corresponding module (we'll need this for method pointers) - ModuleDefinition = Model.Package.Modules?[ShortName]; + ModuleDefinition = Model.Package.Modules[ShortName]; // Generate types in DefinedTypes from typeStart to typeStart+typeCount-1 - for (var t = ImageDefinition.typeStart; t < ImageDefinition.typeStart + ImageDefinition.typeCount; t++) { + for (var t = ImageDefinition.TypeStart; t < ImageDefinition.TypeStart + ImageDefinition.TypeCount; t++) { var type = new TypeInfo(t, this); // Don't add empty module definitions diff --git a/Il2CppInspector.Common/Reflection/CustomAttributeData.cs b/Il2CppInspector.Common/Reflection/CustomAttributeData.cs index 511544b..1220455 100644 --- a/Il2CppInspector.Common/Reflection/CustomAttributeData.cs +++ b/Il2CppInspector.Common/Reflection/CustomAttributeData.cs @@ -95,7 +95,7 @@ namespace Il2CppInspector.Reflection if (pkg.Version < MetadataVersions.V290) { var range = pkg.AttributeTypeRanges[customAttributeIndex]; - for (var i = range.start; i < range.start + range.count; i++) + for (var i = range.Start; i < range.Start + range.Count; i++) { var typeIndex = pkg.AttributeTypeIndices[i]; @@ -118,8 +118,8 @@ namespace Il2CppInspector.Reflection var range = pkg.Metadata.AttributeDataRanges[customAttributeIndex]; var next = pkg.Metadata.AttributeDataRanges[customAttributeIndex + 1]; - var startOffset = pkg.Metadata.Header.attributeDataOffset + range.startOffset; - var endOffset = pkg.Metadata.Header.attributeDataOffset + next.startOffset; + var startOffset = (uint)pkg.Metadata.Header.AttributeDataOffset + range.StartOffset; + var endOffset = (uint)pkg.Metadata.Header.AttributeDataOffset + next.StartOffset; var reader = new CustomAttributeDataReader(pkg, asm, pkg.Metadata, startOffset, endOffset); if (reader.Count == 0) @@ -143,13 +143,17 @@ namespace Il2CppInspector.Reflection public static IList GetCustomAttributes(Assembly asm, int token, int customAttributeIndex) => getCustomAttributes(asm, asm.Model.GetCustomAttributeIndex(asm, token, customAttributeIndex)).ToList(); - public static IList GetCustomAttributes(Assembly asm) => GetCustomAttributes(asm, asm.MetadataToken, asm.AssemblyDefinition.customAttributeIndex); - public static IList GetCustomAttributes(EventInfo evt) => GetCustomAttributes(evt.Assembly, evt.MetadataToken, evt.Definition.customAttributeIndex); - public static IList GetCustomAttributes(FieldInfo field) => GetCustomAttributes(field.Assembly, field.MetadataToken, field.Definition.customAttributeIndex); - public static IList GetCustomAttributes(MethodBase method) => GetCustomAttributes(method.Assembly, method.MetadataToken, method.Definition.customAttributeIndex); - public static IList GetCustomAttributes(ParameterInfo param) => GetCustomAttributes(param.DeclaringMethod.Assembly, param.MetadataToken, param.Definition.customAttributeIndex); + public static IList GetCustomAttributes(Assembly asm) => GetCustomAttributes(asm, asm.MetadataToken, asm.AssemblyDefinition.CustomAttributeIndex); + public static IList GetCustomAttributes(EventInfo evt) => GetCustomAttributes(evt.Assembly, evt.MetadataToken, evt.Definition.CustomAttributeIndex); + public static IList GetCustomAttributes(FieldInfo field) => GetCustomAttributes(field.Assembly, field.MetadataToken, field.Definition.CustomAttributeIndex); + public static IList GetCustomAttributes(MethodBase method) => GetCustomAttributes(method.Assembly, method.MetadataToken, method.Definition.CustomAttributeIndex); + public static IList GetCustomAttributes(ParameterInfo param) => GetCustomAttributes(param.DeclaringMethod.Assembly, param.MetadataToken, param.Definition.CustomAttributeIndex); public static IList GetCustomAttributes(PropertyInfo prop) - => prop.Definition != null ? GetCustomAttributes(prop.Assembly, prop.MetadataToken, prop.Definition.customAttributeIndex) : new List(); - public static IList GetCustomAttributes(TypeInfo type) => type.Definition != null? GetCustomAttributes(type.Assembly, type.MetadataToken, type.Definition.customAttributeIndex) : new List(); + => prop.Definition.IsValid + ? GetCustomAttributes(prop.Assembly, prop.MetadataToken, prop.Definition.CustomAttributeIndex) + : new List(); + public static IList GetCustomAttributes(TypeInfo type) => type.Definition.IsValid + ? GetCustomAttributes(type.Assembly, type.MetadataToken, type.Definition.CustomAttributeIndex) + : new List(); } } diff --git a/Il2CppInspector.Common/Reflection/EventInfo.cs b/Il2CppInspector.Common/Reflection/EventInfo.cs index 9f5a998..2495495 100644 --- a/Il2CppInspector.Common/Reflection/EventInfo.cs +++ b/Il2CppInspector.Common/Reflection/EventInfo.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Il2CppInspector.Next.Metadata; namespace Il2CppInspector.Reflection { @@ -41,25 +42,25 @@ namespace Il2CppInspector.Reflection public EventInfo(Il2CppInspector pkg, int eventIndex, TypeInfo declaringType) : base(declaringType) { Definition = pkg.Events[eventIndex]; - MetadataToken = (int) Definition.token; + MetadataToken = (int) Definition.Token; Index = eventIndex; - Name = pkg.Strings[Definition.nameIndex]; + Name = pkg.Strings[Definition.NameIndex]; rootDefinition = this; - eventTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.typeIndex); - var eventType = pkg.TypeReferences[Definition.typeIndex]; + eventTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.TypeIndex); + var eventType = pkg.TypeReferences[Definition.TypeIndex]; // Copy attributes - Attributes = (EventAttributes) eventType.attrs; + Attributes = (EventAttributes) eventType.Attrs; // NOTE: This relies on methods being added to TypeInfo.DeclaredMethods in the same order they are defined in the Il2Cpp metadata // add, remove and raise are method indices from the first method of the declaring type - if (Definition.add >= 0) - AddMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.add); - if (Definition.remove >= 0) - RemoveMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.remove); - if (Definition.raise >= 0) - RaiseMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.raise); + if (Definition.Add >= 0) + AddMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.MethodIndex + Definition.Add); + if (Definition.Remove >= 0) + RemoveMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.MethodIndex + Definition.Remove); + if (Definition.Raise >= 0) + RaiseMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.MethodIndex + Definition.Raise); } public EventInfo(EventInfo eventDef, TypeInfo declaringType) : base(declaringType) { diff --git a/Il2CppInspector.Common/Reflection/FieldInfo.cs b/Il2CppInspector.Common/Reflection/FieldInfo.cs index 0b76299..f207693 100644 --- a/Il2CppInspector.Common/Reflection/FieldInfo.cs +++ b/Il2CppInspector.Common/Reflection/FieldInfo.cs @@ -10,6 +10,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Text; +using Il2CppInspector.Next.Metadata; namespace Il2CppInspector.Reflection { public class FieldInfo : MemberInfo // L-TODO: Add support for [ThreadLocal] fields @@ -96,9 +97,9 @@ namespace Il2CppInspector.Reflection { public FieldInfo(Il2CppInspector pkg, int fieldIndex, TypeInfo declaringType) : base(declaringType) { Definition = pkg.Fields[fieldIndex]; - MetadataToken = (int) Definition.token; + MetadataToken = (int) Definition.Token; Index = fieldIndex; - Name = pkg.Strings[Definition.nameIndex]; + Name = pkg.Strings[Definition.NameIndex]; rawOffset = pkg.FieldOffsets[fieldIndex]; if (0 > rawOffset) @@ -109,11 +110,11 @@ namespace Il2CppInspector.Reflection { rootDefinition = this; - fieldTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.typeIndex); - var fieldType = pkg.TypeReferences[Definition.typeIndex]; + fieldTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.TypeIndex); + var fieldType = pkg.TypeReferences[Definition.TypeIndex]; // Copy attributes - Attributes = (FieldAttributes) fieldType.attrs; + Attributes = (FieldAttributes) fieldType.Attrs; // Default initialization value if present if (pkg.FieldDefaultValue.TryGetValue(fieldIndex, out (ulong address, object variant) value)) { @@ -123,7 +124,7 @@ namespace Il2CppInspector.Reflection { } public FieldInfo(FieldInfo fieldDef, TypeInfo declaringType) : base(declaringType) { - if (fieldDef.Definition == null) + if (!fieldDef.Definition.IsValid) throw new ArgumentException("Argument must be a bare field definition"); rootDefinition = fieldDef; diff --git a/Il2CppInspector.Common/Reflection/MethodBase.cs b/Il2CppInspector.Common/Reflection/MethodBase.cs index 44b9ab7..79e8222 100644 --- a/Il2CppInspector.Common/Reflection/MethodBase.cs +++ b/Il2CppInspector.Common/Reflection/MethodBase.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; +using Il2CppInspector.Next.Metadata; namespace Il2CppInspector.Reflection { @@ -117,9 +118,9 @@ namespace Il2CppInspector.Reflection // Initialize a method from a method definition (MethodDef) protected MethodBase(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(declaringType) { Definition = pkg.Methods[methodIndex]; - MetadataToken = (int) Definition.token; + MetadataToken = (int) Definition.Token; Index = methodIndex; - Name = pkg.Strings[Definition.nameIndex]; + Name = pkg.Strings[Definition.NameIndex]; // Find method pointer VirtualAddress = pkg.GetMethodPointer(Assembly.ModuleDefinition, Definition); @@ -130,28 +131,28 @@ namespace Il2CppInspector.Reflection rootDefinition = this; // Generic method definition? - if (Definition.genericContainerIndex >= 0) { + if (Definition.GenericContainerIndex >= 0) { IsGenericMethod = true; // Store the generic type parameters for later instantiation - var container = pkg.GenericContainers[Definition.genericContainerIndex]; - genericArguments = Enumerable.Range((int)container.genericParameterStart, container.type_argc) + var container = pkg.GenericContainers[Definition.GenericContainerIndex]; + genericArguments = Enumerable.Range(container.GenericParameterStart, container.TypeArgc) .Select(index => Assembly.Model.GetGenericParameterType(index)).ToArray(); genericMethodInstances = new Dictionary(new TypeInfo.TypeArgumentsComparer()); genericMethodInstances[genericArguments] = this; } // Copy attributes - Attributes = (MethodAttributes) Definition.flags; - MethodImplementationFlags = (MethodImplAttributes) Definition.iflags; + Attributes = (MethodAttributes) Definition.Flags; + MethodImplementationFlags = (MethodImplAttributes) Definition.ImplFlags; // Add arguments - for (var p = Definition.parameterStart; p < Definition.parameterStart + Definition.parameterCount; p++) + for (var p = Definition.ParameterStart; p < Definition.ParameterStart + Definition.ParameterCount; p++) DeclaredParameters.Add(new ParameterInfo(pkg, p, this)); } protected MethodBase(MethodBase methodDef, TypeInfo declaringType) : base(declaringType) { - if (methodDef.Definition == null) + if (!methodDef.Definition.IsValid) throw new ArgumentException("Argument must be a bare method definition"); rootDefinition = methodDef; diff --git a/Il2CppInspector.Common/Reflection/ParameterInfo.cs b/Il2CppInspector.Common/Reflection/ParameterInfo.cs index cf6d0a6..f31fe5d 100644 --- a/Il2CppInspector.Common/Reflection/ParameterInfo.cs +++ b/Il2CppInspector.Common/Reflection/ParameterInfo.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Il2CppInspector.Next.Metadata; namespace Il2CppInspector.Reflection { @@ -64,28 +65,28 @@ namespace Il2CppInspector.Reflection if (paramIndex == -1) { Position = -1; - paramTypeReference = TypeRef.FromReferenceIndex(declaringMethod.Assembly.Model, declaringMethod.Definition.returnType); - MetadataToken = declaringMethod.Definition.returnParameterToken; + paramTypeReference = TypeRef.FromReferenceIndex(declaringMethod.Assembly.Model, declaringMethod.Definition.ReturnType); + MetadataToken = (int)declaringMethod.Definition.ReturnParameterToken; Attributes |= ParameterAttributes.Retval; return; } Definition = pkg.Params[Index]; - MetadataToken = (int) Definition.token; - Name = pkg.Strings[Definition.nameIndex]; + MetadataToken = (int) Definition.Token; + Name = pkg.Strings[Definition.NameIndex]; rootDefinition = this; // Handle unnamed/obfuscated parameter names if (string.IsNullOrEmpty(Name)) Name = string.Format($"param_{Index:x8}"); - Position = paramIndex - declaringMethod.Definition.parameterStart; - paramTypeReference = TypeRef.FromReferenceIndex(declaringMethod.Assembly.Model, Definition.typeIndex); + Position = paramIndex - declaringMethod.Definition.ParameterStart; + paramTypeReference = TypeRef.FromReferenceIndex(declaringMethod.Assembly.Model, Definition.TypeIndex); - var paramType = pkg.TypeReferences[Definition.typeIndex]; + var paramType = pkg.TypeReferences[Definition.TypeIndex]; // Copy attributes - Attributes = (ParameterAttributes) paramType.attrs; + Attributes = (ParameterAttributes) paramType.Attrs; // Default initialization value if present if (pkg.ParameterDefaultValue.TryGetValue(paramIndex, out (ulong address, object variant) value)) { diff --git a/Il2CppInspector.Common/Reflection/PropertyInfo.cs b/Il2CppInspector.Common/Reflection/PropertyInfo.cs index 440a562..d44e627 100644 --- a/Il2CppInspector.Common/Reflection/PropertyInfo.cs +++ b/Il2CppInspector.Common/Reflection/PropertyInfo.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Il2CppInspector.Next.Metadata; namespace Il2CppInspector.Reflection { public class PropertyInfo : MemberInfo @@ -52,25 +53,24 @@ namespace Il2CppInspector.Reflection { base(declaringType) { Index = propIndex; Definition = pkg.Properties[propIndex]; - MetadataToken = (int) Definition.token; - Name = pkg.Strings[Definition.nameIndex]; + MetadataToken = (int) Definition.Token; + Name = pkg.Strings[Definition.NameIndex]; rootDefinition = this; // Copy attributes - Attributes = (PropertyAttributes) Definition.attrs; + Attributes = (PropertyAttributes) Definition.Attrs; // prop.get and prop.set are method indices from the first method of the declaring type - if (Definition.get >= 0) - GetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.get); - if (Definition.set >= 0) - SetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.set); + if (Definition.Get >= 0) + GetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.MethodIndex + Definition.Get); + if (Definition.Set >= 0) + SetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.MethodIndex + Definition.Set); } // Create a property based on a get and set method public PropertyInfo(MethodInfo getter, MethodInfo setter, TypeInfo declaringType) : base(declaringType) { Index = -1; - Definition = null; rootDefinition = this; Name = (getter ?? setter).Name.Replace(".get_", ".").Replace(".set_", "."); diff --git a/Il2CppInspector.Common/Reflection/TypeInfo.cs b/Il2CppInspector.Common/Reflection/TypeInfo.cs index 42088a2..305ba43 100644 --- a/Il2CppInspector.Common/Reflection/TypeInfo.cs +++ b/Il2CppInspector.Common/Reflection/TypeInfo.cs @@ -13,6 +13,8 @@ using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using Il2CppInspector.Next.BinaryMetadata; +using Il2CppInspector.Next.Metadata; namespace Il2CppInspector.Reflection { @@ -53,9 +55,9 @@ namespace Il2CppInspector.Reflection return null; if (IsArray) return Assembly.Model.TypesByFullName["System.Array"]; - if (Definition != null) { - if (Definition.parentIndex >= 0) - return Assembly.Model.TypesByReferenceIndex[Definition.parentIndex]; + if (Definition.IsValid) { + if (Definition.ParentIndex >= 0) + return Assembly.Model.TypesByReferenceIndex[Definition.ParentIndex]; } if (genericTypeDefinition != null) { return genericTypeDefinition.BaseType.SubstituteGenericArguments(genericArguments); @@ -73,15 +75,15 @@ namespace Il2CppInspector.Reflection public override TypeInfo DeclaringType { get { - if (Definition != null) { + if (Definition.IsValid) { /* Type definition */ - if (Definition.declaringTypeIndex == -1) + if (Definition.DeclaringTypeIndex == -1) return null; - var type = Assembly.Model.TypesByReferenceIndex[Definition.declaringTypeIndex]; + var type = Assembly.Model.TypesByReferenceIndex[Definition.DeclaringTypeIndex]; if (type == null) { /* This might happen while initially setting up the types */ - var typeRef = Assembly.Model.Package.TypeReferences[Definition.declaringTypeIndex]; - type = Assembly.Model.TypesByDefinitionIndex[(int)typeRef.datapoint]; + var typeRef = Assembly.Model.Package.TypeReferences[Definition.DeclaringTypeIndex]; + type = Assembly.Model.TypesByDefinitionIndex[typeRef.Data.KlassIndex]; } return type; } @@ -253,7 +255,7 @@ namespace Il2CppInspector.Reflection public PropertyInfo GetProperty(string name) => DeclaredProperties.FirstOrDefault(p => p.Name == name); public MethodBase[] GetVTable() { - if (Definition != null) { + if (!Definition.IsValid) { MetadataUsage[] vt = Assembly.Model.Package.GetVTable(Definition); MethodBase[] res = new MethodBase[vt.Length]; for (int i = 0; i < vt.Length; i++) { @@ -667,7 +669,7 @@ namespace Il2CppInspector.Reflection private readonly TypeRef[] implementedInterfaceReferences; public IEnumerable ImplementedInterfaces { get { - if (Definition != null) + if (Definition.IsValid) return implementedInterfaceReferences.Select(x => x.Value); if (genericTypeDefinition != null) return genericTypeDefinition.ImplementedInterfaces.Select(t => t.SubstituteGenericArguments(genericArguments)); @@ -687,7 +689,7 @@ namespace Il2CppInspector.Reflection public bool IsEnum { get; } public bool IsGenericParameter { get; } public bool IsGenericType { get; } - public bool IsGenericTypeDefinition => (Definition != null) && genericArguments.Any(); + public bool IsGenericTypeDefinition => (Definition.IsValid) && genericArguments.Any(); public bool IsImport => (Attributes & TypeAttributes.Import) == TypeAttributes.Import; public bool IsInterface => (Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface; public bool IsNested => (MemberType & MemberTypes.NestedType) == MemberTypes.NestedType; @@ -746,13 +748,13 @@ namespace Il2CppInspector.Reflection Definition = pkg.TypeDefinitions[typeIndex]; Sizes = pkg.TypeDefinitionSizes[typeIndex]; - MetadataToken = (int) Definition.token; + MetadataToken = (int) Definition.Token; Index = typeIndex; - Namespace = Regex.Replace(pkg.Strings[Definition.namespaceIndex], @"[^A-Za-z0-9_\-\.<>{}]", ""); - Name = pkg.Strings[Definition.nameIndex]; + Namespace = Regex.Replace(pkg.Strings[Definition.NamespaceIndex], @"[^A-Za-z0-9_\-\.<>{}]", ""); + Name = pkg.Strings[Definition.NameIndex]; // Nested type? - if (Definition.declaringTypeIndex >= 0) { + if (Definition.DeclaringTypeIndex >= 0) { MemberType |= MemberTypes.NestedType; } @@ -760,14 +762,14 @@ namespace Il2CppInspector.Reflection Assembly.Model.TypesByDefinitionIndex[Index] = this; // Generic type definition? - if (Definition.genericContainerIndex >= 0) { + if (Definition.GenericContainerIndex >= 0) { IsGenericType = true; IsGenericParameter = false; // Store the generic type parameters for later instantiation - var container = pkg.GenericContainers[Definition.genericContainerIndex]; + var container = pkg.GenericContainers[Definition.GenericContainerIndex]; - genericArguments = Enumerable.Range((int)container.genericParameterStart, container.type_argc) + genericArguments = Enumerable.Range((int)container.GenericParameterStart, container.TypeArgc) .Select(index => Assembly.Model.GetGenericParameterType(index)).ToArray(); genericTypeInstances = new Dictionary(new TypeArgumentsComparer()); genericTypeInstances[genericArguments] = this; @@ -777,12 +779,12 @@ namespace Il2CppInspector.Reflection Assembly.Model.TypesByFullName[FullName] = this; // Copy attributes - Attributes = (TypeAttributes) Definition.flags; + Attributes = (TypeAttributes) Definition.Flags; // Enumerations - bit 1 of bitfield indicates this (also the baseTypeReference will be System.Enum) - if (((Definition.bitfield >> 1) & 1) == 1) { + if (Definition.Bitfield.EnumType) { IsEnum = true; - enumUnderlyingTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.elementTypeIndex); + enumUnderlyingTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.ElementTypeIndex); } // Pass-by-reference type @@ -792,24 +794,24 @@ namespace Il2CppInspector.Reflection IsByRef = false; // Add all implemented interfaces - implementedInterfaceReferences = new TypeRef[Definition.interfaces_count]; - for (var i = 0; i < Definition.interfaces_count; i++) - implementedInterfaceReferences[i] = TypeRef.FromReferenceIndex(Assembly.Model, pkg.InterfaceUsageIndices[Definition.interfacesStart + i]); + implementedInterfaceReferences = new TypeRef[Definition.InterfacesCount]; + for (var i = 0; i < Definition.InterfacesCount; i++) + implementedInterfaceReferences[i] = TypeRef.FromReferenceIndex(Assembly.Model, pkg.InterfaceUsageIndices[Definition.InterfacesIndex + i]); // Add all nested types - declaredNestedTypes = new TypeRef[Definition.nested_type_count]; - for (var n = 0; n < Definition.nested_type_count; n++) - declaredNestedTypes[n] = TypeRef.FromDefinitionIndex(Assembly.Model, pkg.NestedTypeIndices[Definition.nestedTypesStart + n]); + declaredNestedTypes = new TypeRef[Definition.NestedTypeCount]; + for (var n = 0; n < Definition.NestedTypeCount; n++) + declaredNestedTypes[n] = TypeRef.FromDefinitionIndex(Assembly.Model, pkg.NestedTypeIndices[Definition.NestedTypeIndex + n]); // Add all fields declaredFields = new List(); - for (var f = Definition.fieldStart; f < Definition.fieldStart + Definition.field_count; f++) + for (var f = Definition.FieldIndex; f < Definition.FieldIndex + Definition.FieldCount; f++) declaredFields.Add(new FieldInfo(pkg, f, this)); // Add all methods declaredConstructors = new List(); declaredMethods = new List(); - for (var m = Definition.methodStart; m < Definition.methodStart + Definition.method_count; m++) { + for (var m = Definition.MethodIndex; m < Definition.MethodIndex + Definition.MethodCount; m++) { var method = new MethodInfo(pkg, m, this); if (method.Name == ConstructorInfo.ConstructorName || method.Name == ConstructorInfo.TypeConstructorName) declaredConstructors.Add(new ConstructorInfo(pkg, m, this)); @@ -819,7 +821,7 @@ namespace Il2CppInspector.Reflection // Add all properties declaredProperties = new List(); - for (var p = Definition.propertyStart; p < Definition.propertyStart + Definition.property_count; p++) + for (var p = Definition.PropertyIndex; p < Definition.PropertyIndex + Definition.PropertyCount; p++) declaredProperties.Add(new PropertyInfo(pkg, p, this)); // There are rare cases when explicitly implemented interface properties @@ -856,7 +858,7 @@ namespace Il2CppInspector.Reflection // Add all events declaredEvents = new List(); - for (var e = Definition.eventStart; e < Definition.eventStart + Definition.event_count; e++) + for (var e = Definition.EventIndex; e < Definition.EventIndex + Definition.EventCount; e++) declaredEvents.Add(new EventInfo(pkg, e, this)); // TODO: Events have the same edge case issue as properties above, eg. PoGo 0.35.0 @@ -937,21 +939,21 @@ namespace Il2CppInspector.Reflection Namespace = declaringType.Namespace; // Special constraints - GenericParameterAttributes = (GenericParameterAttributes)param.flags; + GenericParameterAttributes = (GenericParameterAttributes)param.Flags; // Type constraints - genericParameterConstraints = new TypeRef[param.constraintsCount]; - for (int c = 0; c < param.constraintsCount; c++) - genericParameterConstraints[c] = TypeRef.FromReferenceIndex(Assembly.Model, Assembly.Model.Package.GenericConstraintIndices[param.constraintsStart + c]); + genericParameterConstraints = new TypeRef[param.ConstraintsCount]; + for (int c = 0; c < param.ConstraintsCount; c++) + genericParameterConstraints[c] = TypeRef.FromReferenceIndex(Assembly.Model, Assembly.Model.Package.GenericConstraintIndices[param.ConstraintsStart + c]); // Base type of object (set by default) // TODO: ImplementedInterfaces should be set to interface types constraints // Name of parameter - Name = Assembly.Model.Package.Strings[param.nameIndex]; + Name = Assembly.Model.Package.Strings[param.NameIndex]; // Position - GenericParameterPosition = param.num; + GenericParameterPosition = param.Num; IsGenericParameter = true; IsGenericType = false; diff --git a/Il2CppInspector.Common/Reflection/TypeModel.cs b/Il2CppInspector.Common/Reflection/TypeModel.cs index cf0b6ee..e052d32 100644 --- a/Il2CppInspector.Common/Reflection/TypeModel.cs +++ b/Il2CppInspector.Common/Reflection/TypeModel.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using Il2CppInspector.Next.BinaryMetadata; namespace Il2CppInspector.Reflection { @@ -112,13 +113,13 @@ namespace Il2CppInspector.Reflection // Create types and methods from MethodSpec (which incorporates TypeSpec in IL2CPP) foreach (var spec in Package.MethodSpecs) { - var methodDefinition = MethodsByDefinitionIndex[spec.methodDefinitionIndex]; + var methodDefinition = MethodsByDefinitionIndex[spec.MethodDefinitionIndex]; var declaringType = methodDefinition.DeclaringType; // Concrete instance of a generic class // If the class index is not specified, we will later create a generic method in a non-generic class - if (spec.classIndexIndex != -1) { - var genericInstance = Package.GenericInstances[spec.classIndexIndex]; + if (spec.ClassIndexIndex != -1) { + var genericInstance = Package.GenericInstances[spec.ClassIndexIndex]; var genericArguments = ResolveGenericArguments(genericInstance); declaringType = declaringType.MakeGenericType(genericArguments); } @@ -129,8 +130,8 @@ namespace Il2CppInspector.Reflection else method = declaringType.GetMethodByDefinition((MethodInfo)methodDefinition); - if (spec.methodIndexIndex != -1) { - var genericInstance = Package.GenericInstances[spec.methodIndexIndex]; + if (spec.MethodIndexIndex != -1) { + var genericInstance = Package.GenericInstances[spec.MethodIndexIndex]; var genericArguments = ResolveGenericArguments(genericInstance); method = method.MakeGenericMethod(genericArguments); } @@ -190,7 +191,7 @@ namespace Il2CppInspector.Reflection public TypeInfo[] ResolveGenericArguments(Il2CppGenericInst inst) { // Get list of pointers to type parameters (both unresolved and concrete) - var genericTypeArguments = Package.BinaryImage.ReadMappedArray(inst.type_argv, (int)inst.type_argc); + var genericTypeArguments = Package.BinaryImage.ReadMappedArray(inst.TypeArgv, (int)inst.TypeArgc); return genericTypeArguments.Select(a => GetTypeFromVirtualAddress(a)).ToArray(); } @@ -201,17 +202,17 @@ namespace Il2CppInspector.Reflection var image = Package.BinaryImage; TypeInfo underlyingType; - switch (typeRef.type) { + switch (typeRef.Type) { // Classes defined in the metadata (reference to a TypeDef) case Il2CppTypeEnum.IL2CPP_TYPE_CLASS: case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE: - underlyingType = TypesByDefinitionIndex[typeRef.datapoint]; // klassIndex + underlyingType = TypesByDefinitionIndex[typeRef.Data.KlassIndex]; // klassIndex break; // Constructed types case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST: // TODO: Replace with array load from Il2CppMetadataRegistration.genericClasses - var generic = image.ReadMappedObject(typeRef.datapoint); // Il2CppGenericClass * + var generic = image.ReadMappedObject(typeRef.Data.GenericClass); // Il2CppGenericClass * // Get generic type definition TypeInfo genericTypeDef; @@ -219,49 +220,49 @@ namespace Il2CppInspector.Reflection // It appears that TypeRef can be -1 if the generic depth recursion limit // (--maximum-recursive-generic-depth=) is reached in Il2Cpp. In this case, // no generic instance type is generated, so we just produce a null TypeInfo here. - if ((generic.typeDefinitionIndex & 0xffff_ffff) == 0x0000_0000_ffff_ffff) + if ((generic.TypeDefinitionIndex & 0xffff_ffff) == 0x0000_0000_ffff_ffff) return null; - genericTypeDef = TypesByDefinitionIndex[generic.typeDefinitionIndex]; + genericTypeDef = TypesByDefinitionIndex[generic.TypeDefinitionIndex]; } else { - genericTypeDef = GetTypeFromVirtualAddress(generic.type); + genericTypeDef = GetTypeFromVirtualAddress(generic.Type); } // Get the instantiation // TODO: Replace with array load from Il2CppMetadataRegistration.genericInsts - var genericInstance = image.ReadMappedObject(generic.context.class_inst); + var genericInstance = image.ReadMappedObject(generic.Context.ClassInst); var genericArguments = ResolveGenericArguments(genericInstance); underlyingType = genericTypeDef.MakeGenericType(genericArguments); break; case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: - var descriptor = image.ReadMappedObject(typeRef.datapoint); - var elementType = GetTypeFromVirtualAddress(descriptor.etype); - underlyingType = elementType.MakeArrayType(descriptor.rank); + var descriptor = image.ReadMappedObject(typeRef.Data.ArrayType); + var elementType = GetTypeFromVirtualAddress(descriptor.ElementType); + underlyingType = elementType.MakeArrayType(descriptor.Rank); break; case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: - elementType = GetTypeFromVirtualAddress(typeRef.datapoint); + elementType = GetTypeFromVirtualAddress(typeRef.Data.Type); underlyingType = elementType.MakeArrayType(1); break; case Il2CppTypeEnum.IL2CPP_TYPE_PTR: - elementType = GetTypeFromVirtualAddress(typeRef.datapoint); + elementType = GetTypeFromVirtualAddress(typeRef.Data.Type); underlyingType = elementType.MakePointerType(); break; // Generic type and generic method parameters case Il2CppTypeEnum.IL2CPP_TYPE_VAR: case Il2CppTypeEnum.IL2CPP_TYPE_MVAR: - underlyingType = GetGenericParameterType((int)typeRef.datapoint); + underlyingType = GetGenericParameterType(typeRef.Data.GenericParameterIndex); break; // Primitive types default: - underlyingType = GetTypeDefinitionFromTypeEnum(typeRef.type); + underlyingType = GetTypeDefinitionFromTypeEnum(typeRef.Type); break; } // Create a reference type if necessary - return typeRef.byref ? underlyingType.MakeByRefType() : underlyingType; + return typeRef.ByRef ? underlyingType.MakeByRefType() : underlyingType; } // Basic primitive types are specified via a flag value @@ -302,14 +303,14 @@ namespace Il2CppInspector.Reflection return GenericParameterTypes[index]; var paramType = Package.GenericParameters[index]; // genericParameterIndex - var container = Package.GenericContainers[paramType.ownerIndex]; + var container = Package.GenericContainers[paramType.OwnerIndex]; TypeInfo result; - if (container.is_method == 1) { - var owner = MethodsByDefinitionIndex[container.ownerIndex]; + if (container.IsMethod == 1) { + var owner = MethodsByDefinitionIndex[container.OwnerIndex]; result = new TypeInfo(owner, paramType); } else { - var owner = TypesByDefinitionIndex[container.ownerIndex]; + var owner = TypesByDefinitionIndex[container.OwnerIndex]; result = new TypeInfo(owner, paramType); } GenericParameterTypes[index] = result; @@ -324,7 +325,7 @@ namespace Il2CppInspector.Reflection // From v24.1 onwards, token was added to Il2CppCustomAttributeTypeRange and each Il2CppImageDefinition noted the CustomAttributeTypeRanges for the image // v29 uses this same system but with CustomAttributeDataRanges instead - if (!Package.AttributeIndicesByToken.TryGetValue(asm.ImageDefinition.customAttributeStart, out var indices) + if (!Package.AttributeIndicesByToken.TryGetValue(asm.ImageDefinition.CustomAttributeStart, out var indices) || !indices.TryGetValue((uint)token, out var index)) return -1; @@ -345,7 +346,7 @@ namespace Il2CppInspector.Reflection case MetadataUsageType.FieldInfo: var fieldRef = Package.FieldRefs[usage.SourceIndex]; var type = GetMetadataUsageType(usage); - var field = type.DeclaredFields.First(f => f.Index == type.Definition.fieldStart + fieldRef.fieldIndex); + var field = type.DeclaredFields.First(f => f.Index == type.Definition.FieldIndex + fieldRef.FieldIndex); return $"{type.Name}.{field.Name}"; case MetadataUsageType.StringLiteral: @@ -359,7 +360,7 @@ namespace Il2CppInspector.Reflection case MetadataUsageType.FieldRva: fieldRef = Package.FieldRefs[usage.SourceIndex]; type = GetMetadataUsageType(usage); - field = type.DeclaredFields.First(f => f.Index == type.Definition.fieldStart + fieldRef.fieldIndex); + field = type.DeclaredFields.First(f => f.Index == type.Definition.FieldIndex + fieldRef.FieldIndex); return $"{type.Name}.{field.Name}_Default"; // TODO: Find out if this is really needed for anything } throw new NotImplementedException("Unknown metadata usage type: " + usage.Type); @@ -369,7 +370,7 @@ namespace Il2CppInspector.Reflection public TypeInfo GetMetadataUsageType(MetadataUsage usage) => usage.Type switch { MetadataUsageType.Type or MetadataUsageType.TypeInfo => TypesByReferenceIndex[usage.SourceIndex], MetadataUsageType.MethodDef or MetadataUsageType.MethodRef => GetMetadataUsageMethod(usage).DeclaringType, - MetadataUsageType.FieldInfo or MetadataUsageType.FieldRva => TypesByReferenceIndex[Package.FieldRefs[usage.SourceIndex].typeIndex], + MetadataUsageType.FieldInfo or MetadataUsageType.FieldRva => TypesByReferenceIndex[Package.FieldRefs[usage.SourceIndex].TypeIndex], _ => throw new InvalidOperationException("Incorrect metadata usage type to retrieve referenced type") }; diff --git a/Il2CppInspector.Common/Utils/BlobReader.cs b/Il2CppInspector.Common/Utils/BlobReader.cs index f2c367e..c031950 100644 --- a/Il2CppInspector.Common/Utils/BlobReader.cs +++ b/Il2CppInspector.Common/Utils/BlobReader.cs @@ -4,6 +4,8 @@ using System; using System.Diagnostics; using System.IO; using Il2CppInspector.Next; +using Il2CppInspector.Next.BinaryMetadata; +using Il2CppInspector.Next.Metadata; namespace Il2CppInspector.Utils; @@ -154,18 +156,18 @@ public static class BlobReader public static Il2CppTypeEnum ReadEncodedTypeEnum(Il2CppInspector inspector, BinaryObjectStream blob, out Il2CppTypeDefinition enumType) { - enumType = null; + enumType = default; var typeEnum = (Il2CppTypeEnum)blob.ReadByte(); if (typeEnum == Il2CppTypeEnum.IL2CPP_TYPE_ENUM) { var typeIndex = blob.ReadCompressedInt32(); - var typeHandle = (uint)inspector.TypeReferences[typeIndex].datapoint; + var typeHandle = (uint)inspector.TypeReferences[typeIndex].Data.KlassIndex; enumType = inspector.TypeDefinitions[typeHandle]; - var elementTypeHandle = inspector.TypeReferences[enumType.elementTypeIndex].datapoint; + var elementTypeHandle = inspector.TypeReferences[enumType.ElementTypeIndex].Data.KlassIndex; var elementType = inspector.TypeDefinitions[elementTypeHandle]; - typeEnum = inspector.TypeReferences[elementType.byvalTypeIndex].type; + typeEnum = inspector.TypeReferences[elementType.ByValTypeIndex].Type; } // This technically also handles SZARRAY (System.Array) and all others by just returning their system type diff --git a/VersionedSerialization/VersionedSerialization.csproj b/VersionedSerialization/VersionedSerialization.csproj index b602acf..bb44983 100644 --- a/VersionedSerialization/VersionedSerialization.csproj +++ b/VersionedSerialization/VersionedSerialization.csproj @@ -7,4 +7,12 @@ preview + + True + + + + True + +