Recognize v24 metadata from later Unity 2018 versions ("24.1")

This commit is contained in:
Katy Coe
2019-10-20 18:59:59 +02:00
parent 41d6b45f3b
commit 227eb83b63
7 changed files with 44 additions and 32 deletions

View File

@@ -18,7 +18,7 @@ namespace Il2CppInspector
public Il2CppCodeRegistration CodeRegistration { get; protected set; } public Il2CppCodeRegistration CodeRegistration { get; protected set; }
public Il2CppMetadataRegistration MetadataRegistration { get; protected set; } public Il2CppMetadataRegistration MetadataRegistration { get; protected set; }
// Only for <=v24.0 // Only for <=v24.1
public uint[] GlobalMethodPointers { get; set; } public uint[] GlobalMethodPointers { get; set; }
// NOTE: In versions <21 and earlier releases of v21, this array has the format: // NOTE: In versions <21 and earlier releases of v21, this array has the format:
@@ -30,7 +30,7 @@ namespace Il2CppInspector
// Every defined type // Every defined type
public List<Il2CppType> Types { get; private set; } public List<Il2CppType> Types { get; private set; }
// From later versions of v24 onwards, this structure is stored for each module (image) // From v24.2 onwards, this structure is stored for each module (image)
// One assembly may contain multiple modules // One assembly may contain multiple modules
public Dictionary<string, Il2CppCodeGenModule> Modules { get; private set; } public Dictionary<string, Il2CppCodeGenModule> Modules { get; private set; }
@@ -71,12 +71,12 @@ namespace Il2CppInspector
CodeRegistration = image.ReadMappedObject<Il2CppCodeRegistration>(codeRegistration); CodeRegistration = image.ReadMappedObject<Il2CppCodeRegistration>(codeRegistration);
MetadataRegistration = image.ReadMappedObject<Il2CppMetadataRegistration>(metadataRegistration); MetadataRegistration = image.ReadMappedObject<Il2CppMetadataRegistration>(metadataRegistration);
// The global method pointer list was deprecated in later versions of v24 in favour of Il2CppCodeGenModule // The global method pointer list was deprecated in v24.2 in favour of Il2CppCodeGenModule
if (Image.Stream.Version <= 24.0) if (Image.Stream.Version <= 24.1)
GlobalMethodPointers = image.ReadMappedArray<uint>(CodeRegistration.pmethodPointers, (int) CodeRegistration.methodPointersCount); GlobalMethodPointers = image.ReadMappedArray<uint>(CodeRegistration.pmethodPointers, (int) CodeRegistration.methodPointersCount);
// After v24 method pointers and RGCTX data were stored in Il2CppCodeGenModules // After v24 method pointers and RGCTX data were stored in Il2CppCodeGenModules
if (Image.Stream.Version >= 24.1) { if (Image.Stream.Version >= 24.2) {
Modules = new Dictionary<string, Il2CppCodeGenModule>(); Modules = new Dictionary<string, Il2CppCodeGenModule>();
// Array of pointers to Il2CppCodeGenModule // Array of pointers to Il2CppCodeGenModule

View File

@@ -12,10 +12,10 @@ namespace Il2CppInspector
// From class-internals.h / il2cpp-class-internals.h // From class-internals.h / il2cpp-class-internals.h
public class Il2CppCodeRegistration public class Il2CppCodeRegistration
{ {
// Moved to Il2CppCodeGenModule in later versions of v24 // Moved to Il2CppCodeGenModule in v24.2
[Version(Max = 24.0)] [Version(Max = 24.1)]
public uint methodPointersCount; public uint methodPointersCount;
[Version(Max = 24.0)] [Version(Max = 24.1)]
public uint pmethodPointers; public uint pmethodPointers;
public uint reversePInvokeWrapperCount; // (was renamed from delegateWrappersFromNativeToManagedCount in v22) public uint reversePInvokeWrapperCount; // (was renamed from delegateWrappersFromNativeToManagedCount in v22)
@@ -60,14 +60,14 @@ namespace Il2CppInspector
[Version(Min = 23)] [Version(Min = 23)]
public uint interopData; public uint interopData;
// Added in later versions of metadata v24 // Added in metadata v24.2 to replace methodPointers and methodPointersCount
[Version(Min = 24.1)] [Version(Min = 24.2)]
public uint codeGenModulesCount; public uint codeGenModulesCount;
[Version(Min = 24.1)] [Version(Min = 24.2)]
public uint pcodeGenModules; public uint pcodeGenModules;
} }
// Introduced in metadata v24.1 (replaces method pointers in Il2CppCodeRegistration) // Introduced in metadata v24.2 (replaces method pointers in Il2CppCodeRegistration)
public class Il2CppCodeGenModule public class Il2CppCodeGenModule
{ {
public uint moduleName; public uint moduleName;

View File

@@ -34,7 +34,7 @@ namespace Il2CppInspector
public List<int> FieldOffsets { get; } public List<int> FieldOffsets { get; }
public List<Il2CppType> TypeUsages => Binary.Types; public List<Il2CppType> TypeUsages => Binary.Types;
public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules; public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules;
public uint[] GlobalMethodPointers => Binary.GlobalMethodPointers; // <=v24.0 only public uint[] GlobalMethodPointers => Binary.GlobalMethodPointers; // <=v24.1 only
// TODO: Finish all file access in the constructor and eliminate the need for this // TODO: Finish all file access in the constructor and eliminate the need for this
public IFileFormatReader BinaryImage => Binary.Image; public IFileFormatReader BinaryImage => Binary.Image;

View File

@@ -8,6 +8,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using NoisyCowStudios.Bin2Object; using NoisyCowStudios.Bin2Object;
@@ -52,14 +53,15 @@ namespace Il2CppInspector
// with each block always coming directly after the previous block, 4-byte aligned. We can use this to check the integrity of the data and // with each block always coming directly after the previous block, 4-byte aligned. We can use this to check the integrity of the data and
// detect sub-versions. // detect sub-versions.
// For metadata v24, the header can either be either 0x108 (24.0) or 0x110 (24.1) bytes long. Since 'stringLiteralOffset' is the first thing // For metadata v24, the header can either be either 0x110 (24.0, 24.1) or 0x108 (24.2) bytes long. Since 'stringLiteralOffset' is the first thing
// in the header after the sanity and version fields, and since it will always point directly to the first byte after the end of the header, // in the header after the sanity and version fields, and since it will always point directly to the first byte after the end of the header,
// we can use this value to determine the actual header length and therefore the IL2CPP metadata sub-version used. // 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.
var realHeaderLength = Header.stringLiteralOffset; var realHeaderLength = Header.stringLiteralOffset;
if (realHeaderLength != Sizeof(typeof(Il2CppGlobalMetadataHeader))) { if (realHeaderLength != Sizeof(typeof(Il2CppGlobalMetadataHeader))) {
if (Version == 24.0) { if (Version == 24.0) {
Version = 24.1; Version = 24.2;
Header = ReadObject<Il2CppGlobalMetadataHeader>(0); Header = ReadObject<Il2CppGlobalMetadataHeader>(0);
} }
} }
@@ -72,9 +74,18 @@ namespace Il2CppInspector
Images = ReadArray<Il2CppImageDefinition>(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition))); Images = ReadArray<Il2CppImageDefinition>(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition)));
// As an additional sanity check, all images in the metadata should have Mono.Cecil.MetadataToken == 1 // As an additional sanity check, all images in the metadata should have Mono.Cecil.MetadataToken == 1
foreach (var i in Images) // In metadata v24.1, two extra fields were added which will cause the below test to fail.
if (i.token != 1) // In that case, we can then adjust the version number and reload
throw new Exception("ERROR: Could not verify the integrity of the metadata file image list"); if (Images.Any(x => x.token != 1))
if (Version == 24.0) {
Version = 24.1;
// 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)));
}
if (Images.Any(x => x.token != 1))
throw new Exception("ERROR: Could not verify the integrity of the metadata file image list");
Types = ReadArray<Il2CppTypeDefinition>(Header.typeDefinitionsOffset, Header.typeDefinitionsCount / Sizeof(typeof(Il2CppTypeDefinition))); Types = ReadArray<Il2CppTypeDefinition>(Header.typeDefinitionsOffset, Header.typeDefinitionsCount / Sizeof(typeof(Il2CppTypeDefinition)));
Methods = ReadArray<Il2CppMethodDefinition>(Header.methodsOffset, Header.methodsCount / Sizeof(typeof(Il2CppMethodDefinition))); Methods = ReadArray<Il2CppMethodDefinition>(Header.methodsOffset, Header.methodsCount / Sizeof(typeof(Il2CppMethodDefinition)));

View File

@@ -12,7 +12,8 @@ namespace Il2CppInspector
// Unity 5.6.2p3 -> v23 // Unity 5.6.2p3 -> v23
// Unity 5.6.4f1 -> v23 // Unity 5.6.4f1 -> v23
// Unity 2017.2f3 -> v24 // Unity 2017.2f3 -> v24
// Unity 2019.2.8f1 -> v24.1 // Unity 2018.3.0f2 -> v24.1
// Unity 2019.2.8f1 -> v24.2
// From il2cpp-metadata.h // From il2cpp-metadata.h
#pragma warning disable CS0649 #pragma warning disable CS0649
@@ -62,9 +63,9 @@ namespace Il2CppInspector
public int typeDefinitionsOffset; // Il2CppTypeDefinition public int typeDefinitionsOffset; // Il2CppTypeDefinition
public int typeDefinitionsCount; public int typeDefinitionsCount;
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int rgctxEntriesOffset; // Il2CppRGCTXDefinition public int rgctxEntriesOffset; // Il2CppRGCTXDefinition
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int rgctxEntriesCount; public int rgctxEntriesCount;
public int imagesOffset; // Il2CppImageDefinition public int imagesOffset; // Il2CppImageDefinition
@@ -135,7 +136,7 @@ namespace Il2CppInspector
public int nameIndex; public int nameIndex;
public int namespaceIndex; public int namespaceIndex;
// Removed in later versions of metadata v24 // Removed in metadata v24.1
[Version(Max = 24.0)] [Version(Max = 24.0)]
public int customAttributeIndex; public int customAttributeIndex;
@@ -146,9 +147,9 @@ namespace Il2CppInspector
public int parentIndex; public int parentIndex;
public int elementTypeIndex; // we can probably remove this one. Only used for enums public int elementTypeIndex; // we can probably remove this one. Only used for enums
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int rgctxStartIndex; public int rgctxStartIndex;
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int rgctxCount; public int rgctxCount;
public int genericContainerIndex; public int genericContainerIndex;
@@ -207,15 +208,15 @@ namespace Il2CppInspector
public int genericContainerIndex; public int genericContainerIndex;
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int methodIndex; public int methodIndex;
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int invokerIndex; public int invokerIndex;
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int reversePInvokeWrapperIndex; // (was renamed from delegateWrapperIndex in v22) public int reversePInvokeWrapperIndex; // (was renamed from delegateWrapperIndex in v22)
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int rgctxStartIndex; public int rgctxStartIndex;
[Version(Max = 24.0)] [Version(Max = 24.1)]
public int rgctxCount; public int rgctxCount;
public uint token; public uint token;

View File

@@ -43,7 +43,7 @@ namespace Il2CppInspector.Reflection {
} }
// Find corresponding module (we'll need this for method pointers) // Find corresponding module (we'll need this for method pointers)
if (Model.Package.Version >= 24.1) if (Model.Package.Version >= 24.2)
Module = Model.Package.Modules[FullName]; Module = Model.Package.Modules[FullName];
// Generate types in DefinedTypes from typeStart to typeStart+typeCount-1 // Generate types in DefinedTypes from typeStart to typeStart+typeCount-1

View File

@@ -39,7 +39,7 @@ namespace Il2CppInspector.Reflection
if (Definition.methodIndex >= 0) { if (Definition.methodIndex >= 0) {
// Global method pointer array // Global method pointer array
if (pkg.Version < 24.1) { if (pkg.Version <= 24.1) {
VirtualAddress = pkg.GlobalMethodPointers[Definition.methodIndex]; VirtualAddress = pkg.GlobalMethodPointers[Definition.methodIndex];
} }