add new struct definitions

This commit is contained in:
LukeFZ
2024-08-13 18:34:22 +02:00
parent 23e873280d
commit 2d3b186b4d
78 changed files with 1852 additions and 1047 deletions

View File

@@ -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)];

View File

@@ -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<Il2CppCodeRegistration>(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<Il2CppCodeRegistration>(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<ulong>(CodeRegistration.pmethodPointers, (int) CodeRegistration.methodPointersCount);
GlobalMethodPointers = Image.ReadMappedArray<ulong>(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<Il2CppCodeRegistration>(codeRegistration);
}
// Array of pointers to Il2CppCodeGenModule
var codeGenModulePointers = Image.ReadMappedArray<ulong>(CodeRegistration.pcodeGenModules, (int) CodeRegistration.codeGenModulesCount);
var modules = Image.ReadMappedObjectPointerArray<Il2CppCodeGenModule>(CodeRegistration.pcodeGenModules, (int) CodeRegistration.codeGenModulesCount);
var codeGenModulePointers = Image.ReadMappedArray<ulong>(CodeRegistration.CodeGenModules, (int) CodeRegistration.CodeGenModulesCount);
var modules = Image.ReadMappedObjectPointerArray<Il2CppCodeGenModule>(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<ulong>(module.methodPointers, (int) module.methodPointerCount));
ModuleMethodPointers.Add(module, Image.ReadMappedArray<ulong>(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<int>(module.invokerIndices, (int) module.methodPointerCount));
MethodInvokerIndices.Add(module, Image.ReadMappedArray<int>(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<uint>(MetadataRegistration.pfieldOffsets, (int)MetadataRegistration.fieldOffsetsCount);
FieldOffsets = Image.ReadMappedArray<uint>(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<ulong>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount);
var typeRefPointers = Image.ReadMappedArray<ulong>(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<Il2CppTypeV272>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount)
.Cast<Il2CppType>()
.ToList()
: Image.ReadMappedObjectPointerArray<Il2CppType>(MetadataRegistration.ptypes, (int)MetadataRegistration.typesCount);
TypeReferences = Image.ReadMappedObjectPointerArray<Il2CppType>(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<ulong>(CodeRegistration.customAttributeGenerators, (int) CodeRegistration.customAttributeCount);
CustomAttributeGenerators = Image.ReadMappedArray<ulong>(CodeRegistration.CustomAttributeGenerators, (int) CodeRegistration.CustomAttributeCount);
}
// Method.Invoke function pointers
MethodInvokePointers = Image.ReadMappedArray<ulong>(CodeRegistration.invokerPointers, (int) CodeRegistration.invokerPointersCount);
MethodInvokePointers = Image.ReadMappedArray<ulong>(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<uint>(MetadataRegistration.methodReferences, (int)MetadataRegistration.methodReferencesCount);
VTableMethodReferences = Image.ReadMappedArray<uint>(MetadataRegistration.MethodReferences, (int)MetadataRegistration.MethodReferencesCount);
}
// Generic type and method specs (open and closed constructed types)
MethodSpecs = Image.ReadMappedArray<Il2CppMethodSpec>(MetadataRegistration.methodSpecs, (int) MetadataRegistration.methodSpecsCount);
MethodSpecs = Image.ReadMappedArray<Il2CppMethodSpec>(MetadataRegistration.MethodSpecs, (int) MetadataRegistration.MethodSpecsCount);
// Concrete generic class and method signatures
GenericInstances = Image.ReadMappedObjectPointerArray<Il2CppGenericInst>(MetadataRegistration.genericInsts, (int) MetadataRegistration.genericInstsCount);
GenericInstances = Image.ReadMappedObjectPointerArray<Il2CppGenericInst>(MetadataRegistration.GenericInsts, (int) MetadataRegistration.GenericInstsCount);
// Concrete generic method pointers
var genericMethodPointers = Image.ReadMappedArray<ulong>(CodeRegistration.genericMethodPointers, (int) CodeRegistration.genericMethodPointersCount);
var genericMethodTable = Image.ReadMappedArray<Il2CppGenericMethodFunctionsDefinitions>(MetadataRegistration.genericMethodTable, (int) MetadataRegistration.genericMethodTableCount);
var genericMethodPointers = Image.ReadMappedArray<ulong>(CodeRegistration.GenericMethodPointers, (int) CodeRegistration.GenericMethodPointersCount);
var genericMethodTable = Image.ReadMappedArray<Il2CppGenericMethodFunctionsDefinitions>(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<Il2CppTypeDefinitionSizes>(
MetadataRegistration.typeDefinitionsSizes, (int) MetadataRegistration.typeDefinitionsSizesCount);
MetadataRegistration.TypeDefinitionsSizes, (int) MetadataRegistration.TypeDefinitionsSizesCount);
// Plugin hook to pre-process binary
isModified |= PluginHooks.PostProcessBinary(this).IsStreamModified;

View File

@@ -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: <type> token */
IL2CPP_TYPE_BYREF = 0x10, /* arg: <type> token */
IL2CPP_TYPE_VALUETYPE = 0x11, /* arg: <type> token */
IL2CPP_TYPE_CLASS = 0x12, /* arg: <type> 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, /* <type> <type-arg-count> <type-1> \x{2026} <type-n> */
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 (<v27; v27: at startup)
Il2CppMetadataTypeHandle typeHandle; // for VALUETYPE and CLASS (added in v27: at runtime)
const Il2CppType* type; // for PTR and SZARRAY
Il2CppArrayType* array; // for ARRAY
GenericParameterIndex genericParameterIndex; // for VAR and MVAR (<v27; v27: at startup)
Il2CppMetadataGenericParameterHandle genericParameterHandle; // for VAR and MVAR (added in v27: at runtime)
Il2CppGenericClass* generic_class; // for GENERICINST
}
*/
}
// Unity 2021.1 (v27.2): num_mods becomes 1 bit shorter, shifting byref and pinned left 1 bit, valuetype bit added
public class Il2CppTypeV272 : Il2CppType
{
public override uint num_mods => (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;
}
}

View File

@@ -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<uint, MetadataUsage>();
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<ulong>(Binary.MetadataRegistration.metadataUsages, (int) count);
var addresses = Binary.Image.ReadMappedArray<ulong>(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<uint, int>();
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;

View File

@@ -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<Il2CppCodeRegistration>(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<Il2CppCodeRegistration>(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<Il2CppMetadataRegistration>(va);
if (mr.metadataUsagesCount == (ulong) metadata.MetadataUsageLists.Length)
if (mr.MetadataUsagesCount == (ulong) metadata.MetadataUsageLists.Length)
metadataRegistration = va;
}

View File

@@ -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<Il2CppGlobalMetadataHeader>(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<Il2CppImageDefinition>(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition)));
Images = ReadArray<Il2CppImageDefinition>(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<Il2CppImageDefinition>(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition)));
Images = ReadArray<Il2CppImageDefinition>(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<Il2CppTypeDefinition>(Header.typeDefinitionsOffset, Header.typeDefinitionsCount / Sizeof(typeof(Il2CppTypeDefinition)));
Methods = ReadArray<Il2CppMethodDefinition>(Header.methodsOffset, Header.methodsCount / Sizeof(typeof(Il2CppMethodDefinition)));
Params = ReadArray<Il2CppParameterDefinition>(Header.parametersOffset, Header.parametersCount / Sizeof(typeof(Il2CppParameterDefinition)));
Fields = ReadArray<Il2CppFieldDefinition>(Header.fieldsOffset, Header.fieldsCount / Sizeof(typeof(Il2CppFieldDefinition)));
FieldDefaultValues = ReadArray<Il2CppFieldDefaultValue>(Header.fieldDefaultValuesOffset, Header.fieldDefaultValuesCount / Sizeof(typeof(Il2CppFieldDefaultValue)));
Properties = ReadArray<Il2CppPropertyDefinition>(Header.propertiesOffset, Header.propertiesCount / Sizeof(typeof(Il2CppPropertyDefinition)));
Events = ReadArray<Il2CppEventDefinition>(Header.eventsOffset, Header.eventsCount / Sizeof(typeof(Il2CppEventDefinition)));
InterfaceUsageIndices = ReadArray<int>(Header.interfacesOffset, Header.interfacesCount / sizeof(int));
NestedTypeIndices = ReadArray<int>(Header.nestedTypesOffset, Header.nestedTypesCount / sizeof(int));
GenericContainers = ReadArray<Il2CppGenericContainer>(Header.genericContainersOffset, Header.genericContainersCount / Sizeof(typeof(Il2CppGenericContainer)));
GenericParameters = ReadArray<Il2CppGenericParameter>(Header.genericParametersOffset, Header.genericParametersCount / Sizeof(typeof(Il2CppGenericParameter)));
GenericConstraintIndices = ReadArray<int>(Header.genericParameterConstraintsOffset, Header.genericParameterConstraintsCount / sizeof(int));
InterfaceOffsets = ReadArray<Il2CppInterfaceOffsetPair>(Header.interfaceOffsetsOffset, Header.interfaceOffsetsCount / Sizeof(typeof(Il2CppInterfaceOffsetPair)));
VTableMethodIndices = ReadArray<uint>(Header.vtableMethodsOffset, Header.vtableMethodsCount / sizeof(uint));
Types = ReadArray<Il2CppTypeDefinition>(Header.TypeDefinitionsOffset, Header.TypeDefinitionsSize / Sizeof(typeof(Il2CppTypeDefinition)));
Methods = ReadArray<Il2CppMethodDefinition>(Header.MethodsOffset, Header.MethodsSize / Sizeof(typeof(Il2CppMethodDefinition)));
Params = ReadArray<Il2CppParameterDefinition>(Header.ParametersOffset, Header.ParametersSize / Sizeof(typeof(Il2CppParameterDefinition)));
Fields = ReadArray<Il2CppFieldDefinition>(Header.FieldsOffset, Header.FieldsSize / Sizeof(typeof(Il2CppFieldDefinition)));
FieldDefaultValues = ReadArray<Il2CppFieldDefaultValue>(Header.FieldDefaultValuesOffset, Header.FieldDefaultValuesSize / Sizeof(typeof(Il2CppFieldDefaultValue)));
Properties = ReadArray<Il2CppPropertyDefinition>(Header.PropertiesOffset, Header.PropertiesSize / Sizeof(typeof(Il2CppPropertyDefinition)));
Events = ReadArray<Il2CppEventDefinition>(Header.EventsOffset, Header.EventsSize / Sizeof(typeof(Il2CppEventDefinition)));
InterfaceUsageIndices = ReadArray<int>(Header.InterfacesOffset, Header.InterfacesSize / sizeof(int));
NestedTypeIndices = ReadArray<int>(Header.NestedTypesOffset, Header.NestedTypesSize / sizeof(int));
GenericContainers = ReadArray<Il2CppGenericContainer>(Header.GenericContainersOffset, Header.GenericContainersSize / Sizeof(typeof(Il2CppGenericContainer)));
GenericParameters = ReadArray<Il2CppGenericParameter>(Header.GenericParametersOffset, Header.GenericParametersSize / Sizeof(typeof(Il2CppGenericParameter)));
GenericConstraintIndices = ReadArray<int>(Header.GenericParameterConstraintsOffset, Header.GenericParameterConstraintsSize / sizeof(int));
InterfaceOffsets = ReadArray<Il2CppInterfaceOffsetPair>(Header.InterfaceOffsetsOffset, Header.InterfaceOffsetsSize / Sizeof(typeof(Il2CppInterfaceOffsetPair)));
VTableMethodIndices = ReadArray<uint>(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<Il2CppAssemblyDefinition>(Header.assembliesOffset, Images.Length);
Assemblies = ReadArray<Il2CppAssemblyDefinition>(Header.AssembliesOffset, Images.Length);
if (changedAssemblyDefStruct)
Version = MetadataVersions.V241;
ParameterDefaultValues = ReadArray<Il2CppParameterDefaultValue>(Header.parameterDefaultValuesOffset, Header.parameterDefaultValuesCount / Sizeof(typeof(Il2CppParameterDefaultValue)));
ParameterDefaultValues = ReadArray<Il2CppParameterDefaultValue>(Header.ParameterDefaultValuesOffset, Header.ParameterDefaultValuesSize / Sizeof(typeof(Il2CppParameterDefaultValue)));
}
if (Version >= MetadataVersions.V190 && Version < MetadataVersions.V270) {
MetadataUsageLists = ReadArray<Il2CppMetadataUsageList>(Header.metadataUsageListsOffset, Header.metadataUsageListsCount / Sizeof(typeof(Il2CppMetadataUsageList)));
MetadataUsagePairs = ReadArray<Il2CppMetadataUsagePair>(Header.metadataUsagePairsOffset, Header.metadataUsagePairsCount / Sizeof(typeof(Il2CppMetadataUsagePair)));
MetadataUsageLists = ReadArray<Il2CppMetadataUsageList>(Header.MetadataUsageListsOffset, Header.MetadataUsageListsCount / Sizeof(typeof(Il2CppMetadataUsageList)));
MetadataUsagePairs = ReadArray<Il2CppMetadataUsagePair>(Header.MetadataUsagePairsOffset, Header.MetadataUsagePairsCount / Sizeof(typeof(Il2CppMetadataUsagePair)));
}
if (Version >= MetadataVersions.V190) {
FieldRefs = ReadArray<Il2CppFieldRef>(Header.fieldRefsOffset, Header.fieldRefsCount / Sizeof(typeof(Il2CppFieldRef)));
FieldRefs = ReadArray<Il2CppFieldRef>(Header.FieldRefsOffset, Header.FieldRefsSize / Sizeof(typeof(Il2CppFieldRef)));
}
if (Version >= MetadataVersions.V210 && Version < MetadataVersions.V290) {
AttributeTypeIndices = ReadArray<int>(Header.attributeTypesOffset, Header.attributeTypesCount / sizeof(int));
AttributeTypeRanges = ReadArray<Il2CppCustomAttributeTypeRange>(Header.attributesInfoOffset, Header.attributesInfoCount / Sizeof(typeof(Il2CppCustomAttributeTypeRange)));
AttributeTypeIndices = ReadArray<int>(Header.AttributesTypesOffset, Header.AttributesTypesCount / sizeof(int));
AttributeTypeRanges = ReadArray<Il2CppCustomAttributeTypeRange>(Header.AttributesInfoOffset, Header.AttributesInfoCount / Sizeof(typeof(Il2CppCustomAttributeTypeRange)));
}
if (Version >= MetadataVersions.V290)
{
AttributeDataRanges = ReadArray<Il2CppCustomAttributeDataRange>(Header.attributeDataRangeOffset,
Header.attributeDataRangeSize / Sizeof(typeof(Il2CppCustomAttributeDataRange)));
AttributeDataRanges = ReadArray<Il2CppCustomAttributeDataRange>(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<Il2CppMethodDefinition>(Header.methodsOffset,
Header.methodsCount / Sizeof(typeof(Il2CppMethodDefinition)));
Methods = ReadArray<Il2CppMethodDefinition>(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<Il2CppStringLiteral>(Header.stringLiteralOffset, Header.stringLiteralCount / Sizeof(typeof(Il2CppStringLiteral)));
var stringLiteralList = ReadArray<Il2CppStringLiteral>(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

View File

@@ -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;
}
}

View File

@@ -2,6 +2,8 @@
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>preview</LangVersion>
<AssemblyName>Il2CppInspector.Common</AssemblyName>
<Authors>Katy Coe</Authors>
<Version>2023.1</Version>
@@ -47,7 +49,7 @@
<ItemGroup>
<ProjectReference Include="..\Bin2Object\Bin2Object\Bin2Object.csproj" PrivateAssets="all" />
<ProjectReference Include="..\VersionedSerialization.Generator\VersionedSerialization.Generator.csproj" ReferenceOutputAssembly="false" OutputType="Analyzer" />
<ProjectReference Include="..\VersionedSerialization.Generator\VersionedSerialization.Generator.csproj" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
<ProjectReference Include="..\VersionedSerialization\VersionedSerialization.csproj" />
</ItemGroup>

View File

@@ -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]);

View File

@@ -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))
: "";

View File

@@ -0,0 +1,18 @@
using VersionedSerialization.Attributes;
namespace Il2CppInspector.Next.BinaryMetadata;
[VersionedStruct]
public partial struct Il2CppArrayType
{
public Pointer<Il2CppType> 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*
}

View File

@@ -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<Il2CppMethodPointer> MethodPointers;
[Aligned(0)]
[VersionCondition(EqualTo = "24.5")]
[VersionCondition(GreaterThan = "27.1")]
public uint AdjustorThunksCount;
[VersionCondition(EqualTo = "24.5")]
[VersionCondition(GreaterThan = "27.1")]
public Pointer<Il2CppTokenAdjustorThunkPair> AdjustorThunks;
[CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")]
public ulong InvokerIndices; // int*
[Aligned(0)]
public uint ReversePInvokeWrapperCount;
public Pointer<Il2CppTokenIndexMethodTuple> ReversePInvokeWrapperIndices;
[Aligned(0)]
public uint RgctxRangesCount;
public Pointer<Il2CppTokenRangePair> RgctxRanges;
[Aligned(0)]
public uint RgctxsCount;
public Pointer<Il2CppRgctxDefinition> Rgctxs;
[CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")]
public ulong DebuggerMetadata; // Pointer<Il2CppDebuggerMetadataRegistration> DebuggerMetadata;
[VersionCondition(GreaterThan = "27.0", LessThan = "27.2")]
public Pointer<Il2CppMethodPointer> 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<Il2CppMetadataRegistration>
[VersionCondition(GreaterThan = "27.0")]
[CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")]
public ulong CodeRegistration; // Pointer<Il2CppCodeRegistration>
}

View File

@@ -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<Il2CppMethodPointer> MethodPointers;
[Aligned(0)]
public uint ReversePInvokeWrapperCount;
public Pointer<Il2CppMethodPointer> ReversePInvokeWrappers;
[VersionCondition(LessThan = "22.0"), Aligned(0)]
public uint DelegateWrappersFromManagedToNativeCount;
[VersionCondition(LessThan = "22.0")]
public Pointer<Il2CppMethodPointer> DelegateWrappersFromManagedToNative;
[VersionCondition(LessThan = "22.0"), Aligned(0)]
public uint MarshalingFunctionsCount;
[VersionCondition(LessThan = "22.0")]
public Pointer<Il2CppMethodPointer> MarshalingFunctions;
[VersionCondition(GreaterThan = "21.0", LessThan = "22.0"), Aligned(0)]
public uint CcwMarshalingFunctionsCount;
[VersionCondition(GreaterThan = "21.0", LessThan = "22.0")]
public Pointer<Il2CppMethodPointer> CcwMarshalingFunctions;
[Aligned(0)]
public uint GenericMethodPointersCount;
public Pointer<Il2CppMethodPointer> GenericMethodPointers;
[VersionCondition(EqualTo = "24.5")]
[VersionCondition(GreaterThan = "27.1")]
public Pointer<Il2CppMethodPointer> GenericAdjustorThunks;
[Aligned(0)]
public uint InvokerPointersCount;
public Pointer<InvokerMethod> InvokerPointers;
[VersionCondition(LessThan = "24.5"), Aligned(0)]
public int CustomAttributeCount;
[VersionCondition(LessThan = "24.5")]
public Pointer<Il2CppMethodPointer> CustomAttributeGenerators;
[VersionCondition(GreaterThan = "21.0", LessThan = "22.0"), Aligned(0)]
public int GuidCount;
[VersionCondition(GreaterThan = "21.0", LessThan = "22.0")]
public Pointer<Il2CppGuid> 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<Il2CppMethodPointer> UnresolvedVirtualCallPointers;
[VersionCondition(EqualTo = "29.1"), VersionCondition(EqualTo = "31.1")]
[VersionCondition(EqualTo = "29.2"), VersionCondition(EqualTo = "31.2")]
public Pointer<Il2CppMethodPointer> UnresolvedInstanceCallWrappers;
[VersionCondition(EqualTo = "29.1"), VersionCondition(EqualTo = "31.1")]
[VersionCondition(EqualTo = "29.2"), VersionCondition(EqualTo = "31.2")]
public Pointer<Il2CppMethodPointer> UnresolvedStaticCallPointers;
[VersionCondition(GreaterThan = "23.0"), Aligned(0)]
public uint InteropDataCount;
[VersionCondition(GreaterThan = "23.0")]
public Pointer<Il2CppInteropData> InteropData;
[VersionCondition(GreaterThan = "24.3"), Aligned(0)]
public uint WindowsRuntimeFactoryCount;
[VersionCondition(GreaterThan = "24.3")]
public Pointer<Il2CppWindowsRuntimeFactoryTableEntry> WindowsRuntimeFactoryTable;
[VersionCondition(GreaterThan = "24.2"), Aligned(0)]
public uint CodeGenModulesCount;
[VersionCondition(GreaterThan = "24.2")]
public Pointer<Pointer<Il2CppCodeGenModule>> CodeGenModules;
}

View File

@@ -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<Il2CppType> Type;
public Il2CppGenericContext Context;
[CustomSerialization("reader.ReadNUInt();", "is32Bit ? 4 : 8")]
public ulong CachedClass; // Il2CppClass*, optional
}

View File

@@ -0,0 +1,10 @@
using VersionedSerialization.Attributes;
namespace Il2CppInspector.Next.BinaryMetadata;
[VersionedStruct]
public partial struct Il2CppGenericContext
{
public Pointer<Il2CppGenericInst> ClassInst;
public Pointer<Il2CppGenericInst> MethodInst;
}

View File

@@ -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<Pointer<Il2CppType>> TypeArgv;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,22 @@
using VersionedSerialization;
namespace Il2CppInspector.Next.BinaryMetadata;
public struct Il2CppGuid : IReadable
{
public Guid Value;
public void Read<TReader>(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;
}

View File

@@ -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<Il2CppGuid> Guid;
public Pointer<Il2CppType> Type;
}

View File

@@ -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<Pointer<Il2CppGenericClass>> GenericClasses;
[Aligned(0)]
public int GenericInstsCount;
public Pointer<Pointer<Il2CppGenericInst>> GenericInsts;
[Aligned(0)]
public int GenericMethodTableCount;
public Pointer<Il2CppGenericMethodFunctionsDefinitions> GenericMethodTable;
[Aligned(0)]
public int TypesCount;
public Pointer<Pointer<Il2CppType>> Types;
[Aligned(0)]
public int MethodSpecsCount;
public Pointer<Il2CppMethodSpec> 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<Pointer<Il2CppTypeDefinitionSizes>> TypeDefinitionsSizes;
[Aligned(0)]
[VersionCondition(GreaterThan = "19.0")]
public ulong MetadataUsagesCount;
[VersionCondition(GreaterThan = "19.0")]
public Pointer<Pointer<Il2CppMetadataUsage>> MetadataUsages;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -0,0 +1,10 @@
using VersionedSerialization.Attributes;
namespace Il2CppInspector.Next.BinaryMetadata;
[VersionedStruct]
public partial struct Il2CppRange
{
public int Start;
public int Length;
}

View File

@@ -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;
}

View File

@@ -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,
}

View File

@@ -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<Il2CppRgctxDefinitionData> Definition => Data;
public readonly Pointer<Il2CppRgctxConstrainedData> Constrained => Data;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,12 @@
using VersionedSerialization.Attributes;
namespace Il2CppInspector.Next.BinaryMetadata;
[VersionedStruct]
public partial struct Il2CppTokenAdjustorThunkPair
{
[Aligned(0)]
public uint Token;
public Il2CppMethodPointer AdjustorThunk;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,10 @@
using VersionedSerialization.Attributes;
namespace Il2CppInspector.Next.BinaryMetadata;
[VersionedStruct]
public partial struct Il2CppTokenRangePair
{
public uint Token;
public Il2CppRange Range;
}

View File

@@ -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<Il2CppTypeDefinition>;
using Il2CppMetadataGenericParameterHandle = Pointer<Il2CppGenericParameter>;
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<Il2CppType> Type => Value;
public readonly Pointer<Il2CppArrayType> ArrayType => Value;
public readonly GenericParameterIndex GenericParameterIndex => (int)Value;
public readonly Il2CppMetadataGenericParameterHandle GenericParameterHandle => Value;
public readonly Pointer<Il2CppGenericClass> GenericClass => Value;
public void Read<TReader>(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<TReader>(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct
{
Data.Read(ref reader, version);
Value = reader.Read<uint>();
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
};
}

View File

@@ -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;
}

View File

@@ -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
}

View File

@@ -0,0 +1,10 @@
using VersionedSerialization.Attributes;
namespace Il2CppInspector.Next.BinaryMetadata;
[VersionedStruct]
public partial struct Il2CppWindowsRuntimeFactoryTableEntry
{
public Pointer<Il2CppType> Type;
public Il2CppMethodPointer CreateFactoryFunction;
}

View File

@@ -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;
}

View File

@@ -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<PublicKeyToken>();", "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<PublicKeyToken>();", "8")]
public PublicKeyToken PublicKeyToken;
}

View File

@@ -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; }
}

View File

@@ -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; }
}

View File

@@ -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;
}

View File

@@ -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; }
}

View File

@@ -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;
}

View File

@@ -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; }
}

View File

@@ -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; }
}

View File

@@ -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; }
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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; }
}

View File

@@ -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; }
}

View File

@@ -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}";
}
}

View File

@@ -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; }
}

View File

@@ -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; }
}

View File

@@ -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,
}

View File

@@ -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;
}

View File

@@ -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; }
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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; }
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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; }
}

View File

@@ -0,0 +1,14 @@
namespace Il2CppInspector.Next.Metadata;
public enum PackingSize
{
Zero,
One,
Two,
Four,
Eight,
Sixteen,
ThirtyTwo,
SixtyFour,
OneHundredTwentyEight
}

View File

@@ -0,0 +1,60 @@
using System.Collections.Immutable;
using VersionedSerialization;
using VersionedSerialization.Attributes;
namespace Il2CppInspector.Next;
public struct Pointer<T>(ulong value = 0) : IReadable, IEquatable<Pointer<T>> 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<TReader>(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<T>(version);
}
public readonly ImmutableArray<T> ReadArray(ref SpanReader reader, long count, in StructVersion version)
{
reader.Offset = (int)PointerValue;
return reader.ReadObjectArray<T>(count, version);
}
public static implicit operator Pointer<T>(ulong value) => new(value);
public static implicit operator ulong(Pointer<T> ptr) => ptr.PointerValue;
#region Equality operators + ToString
public static bool operator ==(Pointer<T> left, Pointer<T> right)
=> left._value == right._value;
public static bool operator !=(Pointer<T> left, Pointer<T> right)
=> !(left == right);
public readonly override bool Equals(object? obj)
=> obj is Pointer<T> other && Equals(other);
public readonly bool Equals(Pointer<T> other)
=> this == other;
public readonly override int GetHashCode()
=> HashCode.Combine(_value);
public readonly override string ToString() => $"0x{_value:X} <{typeof(T).Name}>";
#endregion
}

View File

@@ -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))

View File

@@ -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");

View File

@@ -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");
}

View File

@@ -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

View File

@@ -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<CustomAttributeData> GetCustomAttributes(Assembly asm, int token, int customAttributeIndex) =>
getCustomAttributes(asm, asm.Model.GetCustomAttributeIndex(asm, token, customAttributeIndex)).ToList();
public static IList<CustomAttributeData> GetCustomAttributes(Assembly asm) => GetCustomAttributes(asm, asm.MetadataToken, asm.AssemblyDefinition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(EventInfo evt) => GetCustomAttributes(evt.Assembly, evt.MetadataToken, evt.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(FieldInfo field) => GetCustomAttributes(field.Assembly, field.MetadataToken, field.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(MethodBase method) => GetCustomAttributes(method.Assembly, method.MetadataToken, method.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo param) => GetCustomAttributes(param.DeclaringMethod.Assembly, param.MetadataToken, param.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(Assembly asm) => GetCustomAttributes(asm, asm.MetadataToken, asm.AssemblyDefinition.CustomAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(EventInfo evt) => GetCustomAttributes(evt.Assembly, evt.MetadataToken, evt.Definition.CustomAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(FieldInfo field) => GetCustomAttributes(field.Assembly, field.MetadataToken, field.Definition.CustomAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(MethodBase method) => GetCustomAttributes(method.Assembly, method.MetadataToken, method.Definition.CustomAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo param) => GetCustomAttributes(param.DeclaringMethod.Assembly, param.MetadataToken, param.Definition.CustomAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(PropertyInfo prop)
=> prop.Definition != null ? GetCustomAttributes(prop.Assembly, prop.MetadataToken, prop.Definition.customAttributeIndex) : new List<CustomAttributeData>();
public static IList<CustomAttributeData> GetCustomAttributes(TypeInfo type) => type.Definition != null? GetCustomAttributes(type.Assembly, type.MetadataToken, type.Definition.customAttributeIndex) : new List<CustomAttributeData>();
=> prop.Definition.IsValid
? GetCustomAttributes(prop.Assembly, prop.MetadataToken, prop.Definition.CustomAttributeIndex)
: new List<CustomAttributeData>();
public static IList<CustomAttributeData> GetCustomAttributes(TypeInfo type) => type.Definition.IsValid
? GetCustomAttributes(type.Assembly, type.MetadataToken, type.Definition.CustomAttributeIndex)
: new List<CustomAttributeData>();
}
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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<TypeInfo[], MethodBase>(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;

View File

@@ -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)) {

View File

@@ -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_", ".");

View File

@@ -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<TypeInfo> 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<TypeInfo[], TypeInfo>(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<FieldInfo>();
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<ConstructorInfo>();
declaredMethods = new List<MethodInfo>();
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<PropertyInfo>();
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<EventInfo>();
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;

View File

@@ -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<ulong>(inst.type_argv, (int)inst.type_argc);
var genericTypeArguments = Package.BinaryImage.ReadMappedArray<ulong>(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<Il2CppGenericClass>(typeRef.datapoint); // Il2CppGenericClass *
var generic = image.ReadMappedObject<Il2CppGenericClass>(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<Il2CppGenericInst>(generic.context.class_inst);
var genericInstance = image.ReadMappedObject<Il2CppGenericInst>(generic.Context.ClassInst);
var genericArguments = ResolveGenericArguments(genericInstance);
underlyingType = genericTypeDef.MakeGenericType(genericArguments);
break;
case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY:
var descriptor = image.ReadMappedObject<Il2CppArrayType>(typeRef.datapoint);
var elementType = GetTypeFromVirtualAddress(descriptor.etype);
underlyingType = elementType.MakeArrayType(descriptor.rank);
var descriptor = image.ReadMappedObject<Il2CppArrayType>(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")
};

View File

@@ -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

View File

@@ -7,4 +7,12 @@
<LangVersion>preview</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
</Project>