From d59f67216a53ae085fef1a8992cf8c4c450b78fc Mon Sep 17 00:00:00 2001 From: LukeFZ <17146677+LukeFZ@users.noreply.github.com> Date: Sun, 13 Oct 2024 21:54:59 +0200 Subject: [PATCH] support auto-recovering type indices from type handles fixes loading of memory-dumped v29+ libraries since those replacee their class indices on load with a pointer to the corresponding type --- Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs | 47 +++++++++++++++++-- .../Next/BinaryMetadata/Il2CppTypeEnum.cs | 31 ++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs b/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs index ab7c7aa..64b087f 100644 --- a/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs +++ b/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs @@ -6,15 +6,12 @@ */ using Il2CppInspector.Next; -using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.IO; -using System.Linq; using System.Reflection; using System.Text.RegularExpressions; using Il2CppInspector.Next.BinaryMetadata; +using Il2CppInspector.Next.Metadata; using VersionedSerialization; namespace Il2CppInspector @@ -370,6 +367,48 @@ namespace Il2CppInspector TypeReferences = Image.ReadMappedVersionedObjectPointerArray(MetadataRegistration.Types, (int)MetadataRegistration.TypesCount); + if (TypeReferences.Any(x => + x.Type.IsTypeDefinitionEnum() + && (uint)x.Data.KlassIndex >= (uint)Metadata.Types.Length)) + { + // This is a memory-dumped binary. + // We need to fix the remapped type indices from their pointer form back to the indices. + var baseDefinitionPtr = ulong.MaxValue; + var baseGenericPtr = ulong.MaxValue; + + foreach (var entry in TypeReferences) + { + if (entry.Type.IsTypeDefinitionEnum()) + { + baseDefinitionPtr = Math.Min(baseDefinitionPtr, entry.Data.Type.PointerValue); + } + else if (entry.Type.IsGenericParameterEnum()) + { + baseGenericPtr = Math.Min(baseGenericPtr, entry.Data.GenericParameterHandle.PointerValue); + } + + } + + var definitionSize = (ulong)Il2CppTypeDefinition.Size(Image.Version); + var genericParameterSize = (ulong)Il2CppGenericParameter.Size(Image.Version); + + var builder = ImmutableArray.CreateBuilder(TypeReferences.Length); + for (var i = 0; i < TypeReferences.Length; i++) + { + var type = TypeReferences[i]; + if (type.Type.IsTypeDefinitionEnum()) + { + type.Data.Value = (type.Data.Type.PointerValue - baseDefinitionPtr) / definitionSize; + } + else if (type.Type.IsGenericParameterEnum()) + { + type.Data.Value = (type.Data.Type.PointerValue - baseGenericPtr) / genericParameterSize; + } + builder.Add(type); + } + TypeReferences = builder.MoveToImmutable(); + } + // Custom attribute constructors (function pointers) // This is managed in Il2CppInspector for metadata >= 27 if (Image.Version < MetadataVersions.V270) { diff --git a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeEnum.cs b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeEnum.cs index 0c44142..7466ad9 100644 --- a/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeEnum.cs +++ b/Il2CppInspector.Common/Next/BinaryMetadata/Il2CppTypeEnum.cs @@ -42,4 +42,35 @@ public enum Il2CppTypeEnum : byte IL2CPP_TYPE_ENUM = 0x55, IL2CPP_TYPE_IL2CPP_TYPE_INDEX = 0xff +} + +public static class Il2CppTypeEnumExtensions +{ + public static bool IsTypeDefinitionEnum(this Il2CppTypeEnum value) + => value + is Il2CppTypeEnum.IL2CPP_TYPE_VOID + or Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN + or Il2CppTypeEnum.IL2CPP_TYPE_CHAR + or Il2CppTypeEnum.IL2CPP_TYPE_I1 + or Il2CppTypeEnum.IL2CPP_TYPE_U1 + or Il2CppTypeEnum.IL2CPP_TYPE_I2 + or Il2CppTypeEnum.IL2CPP_TYPE_U2 + or Il2CppTypeEnum.IL2CPP_TYPE_I4 + or Il2CppTypeEnum.IL2CPP_TYPE_U4 + or Il2CppTypeEnum.IL2CPP_TYPE_I8 + or Il2CppTypeEnum.IL2CPP_TYPE_U8 + or Il2CppTypeEnum.IL2CPP_TYPE_R4 + or Il2CppTypeEnum.IL2CPP_TYPE_R8 + or Il2CppTypeEnum.IL2CPP_TYPE_STRING + or Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE + or Il2CppTypeEnum.IL2CPP_TYPE_CLASS + or Il2CppTypeEnum.IL2CPP_TYPE_I + or Il2CppTypeEnum.IL2CPP_TYPE_U + or Il2CppTypeEnum.IL2CPP_TYPE_OBJECT + or Il2CppTypeEnum.IL2CPP_TYPE_TYPEDBYREF; + + public static bool IsGenericParameterEnum(this Il2CppTypeEnum value) + => value + is Il2CppTypeEnum.IL2CPP_TYPE_VAR + or Il2CppTypeEnum.IL2CPP_TYPE_MVAR; } \ No newline at end of file