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
This commit is contained in:
@@ -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<Il2CppType>(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<Il2CppType>(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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user