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 Il2CppInspector.Next;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Il2CppInspector.Next.BinaryMetadata;
|
using Il2CppInspector.Next.BinaryMetadata;
|
||||||
|
using Il2CppInspector.Next.Metadata;
|
||||||
using VersionedSerialization;
|
using VersionedSerialization;
|
||||||
|
|
||||||
namespace Il2CppInspector
|
namespace Il2CppInspector
|
||||||
@@ -370,6 +367,48 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
TypeReferences = Image.ReadMappedVersionedObjectPointerArray<Il2CppType>(MetadataRegistration.Types, (int)MetadataRegistration.TypesCount);
|
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)
|
// Custom attribute constructors (function pointers)
|
||||||
// This is managed in Il2CppInspector for metadata >= 27
|
// This is managed in Il2CppInspector for metadata >= 27
|
||||||
if (Image.Version < MetadataVersions.V270) {
|
if (Image.Version < MetadataVersions.V270) {
|
||||||
|
|||||||
@@ -43,3 +43,34 @@ public enum Il2CppTypeEnum : byte
|
|||||||
IL2CPP_TYPE_ENUM = 0x55,
|
IL2CPP_TYPE_ENUM = 0x55,
|
||||||
IL2CPP_TYPE_IL2CPP_TYPE_INDEX = 0xff
|
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