From 1a3028087dbd1537e6b80f99eeaec0068b12446a Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Wed, 23 Oct 2019 23:51:16 +0200 Subject: [PATCH] Tidy up FileFormatReader stream access methods --- Il2CppInspector/FileFormatReader.cs | 46 ++++++++++++++---------- Il2CppInspector/Il2CppBinary.cs | 8 ++--- Il2CppInspector/Il2CppBinaryX86.cs | 4 +-- Il2CppInspector/Il2CppInspector.cs | 2 +- Il2CppInspector/Reflection/MethodInfo.cs | 2 +- Il2CppInspector/Reflection/TypeInfo.cs | 5 ++- 6 files changed, 37 insertions(+), 30 deletions(-) diff --git a/Il2CppInspector/FileFormatReader.cs b/Il2CppInspector/FileFormatReader.cs index e2e181e..cd1e87a 100644 --- a/Il2CppInspector/FileFormatReader.cs +++ b/Il2CppInspector/FileFormatReader.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.IO.IsolatedStorage; using System.Linq; using System.Reflection; using NoisyCowStudios.Bin2Object; @@ -17,6 +16,8 @@ namespace Il2CppInspector public interface IFileFormatReader { BinaryObjectReader Stream { get; } + double Version { get; set; } + long Length { get; } uint NumImages { get; } IEnumerable Images { get; } IFileFormatReader this[uint index] { get; } @@ -29,13 +30,21 @@ namespace Il2CppInspector uint[] GetFunctionTable(); U ReadMappedObject(ulong uiAddr) where U : new(); U[] ReadMappedArray(ulong uiAddr, int count) where U : new(); + long[] ReadMappedWordArray(ulong uiAddr, int count); uint MapVATR(ulong uiAddr); byte[] ReadBytes(int count); ulong ReadUInt64(); + ulong ReadUInt64(long uiAddr); uint ReadUInt32(); + uint ReadUInt32(long uiAddr); ushort ReadUInt16(); + ushort ReadUInt16(long uiAddr); byte ReadByte(); + byte ReadByte(long uiAddr); + long ReadWord(); + long ReadWord(long uiAddr); + U ReadObject() where U : new(); string ReadMappedNullTerminatedString(ulong uiAddr); List ReadMappedObjectPointerArray(ulong uiAddr, int count) where U : new(); } @@ -65,6 +74,8 @@ namespace Il2CppInspector public BinaryObjectReader Stream => this; + public long Length => BaseStream.Length; + public uint NumImages { get; protected set; } = 1; public ulong GlobalOffset { get; protected set; } @@ -83,8 +94,8 @@ namespace Il2CppInspector } public static T Load(string filename) { - using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) - return Load(stream); + using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read); + return Load(stream); } public static T Load(Stream stream) { @@ -102,13 +113,7 @@ namespace Il2CppInspector protected virtual bool Init() => throw new NotImplementedException(); // Choose a sub-binary within the image for multi-architecture binaries - public virtual IFileFormatReader this[uint index] { - get { - if (index == 0) - return this; - throw new IndexOutOfRangeException("Binary image index out of bounds"); - } - } + public virtual IFileFormatReader this[uint index] => (index == 0)? this : throw new IndexOutOfRangeException("Binary image index out of bounds"); // Find search locations in the symbol table for Il2Cpp data public virtual Dictionary GetSymbolTable() => null; @@ -120,18 +125,21 @@ namespace Il2CppInspector // No mapping by default public virtual uint MapVATR(ulong uiAddr) => (uint) uiAddr; + // Read a file format dependent word (32 or 64 bits) + // The primitive mappings in Bin2Object will automatically read a uint if the file is 32-bit + public long ReadWord() => ReadObject(); + public long ReadWord(long uiAddr) => ReadObject(uiAddr); + // Retrieve object(s) from specified RVA(s) - public U ReadMappedObject(ulong uiAddr) where U : new() { - return ReadObject(MapVATR(uiAddr)); - } + public U ReadMappedObject(ulong uiAddr) where U : new() => ReadObject(MapVATR(uiAddr)); - public U[] ReadMappedArray(ulong uiAddr, int count) where U : new() { - return ReadArray(MapVATR(uiAddr), count); - } + public U[] ReadMappedArray(ulong uiAddr, int count) where U : new() => ReadArray(MapVATR(uiAddr), count); - public string ReadMappedNullTerminatedString(ulong uiAddr) { - return ReadNullTerminatedString(MapVATR(uiAddr)); - } + // Read a file format dependent array of words (32 or 64 bits) + // The primitive mappings in Bin2Object will automatically read a uint if the file is 32-bit + public long[] ReadMappedWordArray(ulong uiAddr, int count) => ReadArray(MapVATR(uiAddr), count); + + public string ReadMappedNullTerminatedString(ulong uiAddr) => ReadNullTerminatedString(MapVATR(uiAddr)); // Reads a list of pointers, then reads each object pointed to public List ReadMappedObjectPointerArray(ulong uiAddr, int count) where U : new() { diff --git a/Il2CppInspector/Il2CppBinary.cs b/Il2CppInspector/Il2CppBinary.cs index 1a8c9d2..7057cbb 100644 --- a/Il2CppInspector/Il2CppBinary.cs +++ b/Il2CppInspector/Il2CppBinary.cs @@ -64,7 +64,7 @@ namespace Il2CppInspector // Check all search locations public bool Initialize(double version, uint imageIndex = 0) { var subImage = Image[imageIndex]; - subImage.Stream.Version = version; + subImage.Version = version; // Try searching the symbol table var symbols = subImage.GetSymbolTable(); @@ -128,11 +128,11 @@ namespace Il2CppInspector MetadataRegistration = image.ReadMappedObject(metadataRegistration); // The global method pointer list was deprecated in v24.2 in favour of Il2CppCodeGenModule - if (Image.Stream.Version <= 24.1) + if (Image.Version <= 24.1) GlobalMethodPointers = image.ReadMappedArray(CodeRegistration.pmethodPointers, (int) CodeRegistration.methodPointersCount); // After v24 method pointers and RGCTX data were stored in Il2CppCodeGenModules - if (Image.Stream.Version >= 24.2) { + if (Image.Version >= 24.2) { Modules = new Dictionary(); // Array of pointers to Il2CppCodeGenModule @@ -145,7 +145,7 @@ namespace Il2CppInspector } // Field offset data. Metadata <=21.x uses a value-type array; >=21.x uses a pointer array - FieldOffsetData = image.ReadMappedArray(MetadataRegistration.pfieldOffsets, (int) MetadataRegistration.fieldOffsetsCount); + FieldOffsetData = image.ReadMappedWordArray(MetadataRegistration.pfieldOffsets, (int) MetadataRegistration.fieldOffsetsCount); // Type definitions (pointer array) Types = image.ReadMappedObjectPointerArray(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount); diff --git a/Il2CppInspector/Il2CppBinaryX86.cs b/Il2CppInspector/Il2CppBinaryX86.cs index 75d3a65..cd88891 100644 --- a/Il2CppInspector/Il2CppBinaryX86.cs +++ b/Il2CppInspector/Il2CppBinaryX86.cs @@ -1,5 +1,5 @@ /* - Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com All rights reserved. */ @@ -50,7 +50,7 @@ namespace Il2CppInspector image.Position += 8; funcPtr = image.MapVATR(image.ReadUInt32() + image.GlobalOffset); - if (funcPtr > image.Stream.BaseStream.Length) + if (funcPtr > image.Length) return (0, 0); // Extract Metadata pointer diff --git a/Il2CppInspector/Il2CppInspector.cs b/Il2CppInspector/Il2CppInspector.cs index c32fb70..d5ba4b2 100644 --- a/Il2CppInspector/Il2CppInspector.cs +++ b/Il2CppInspector/Il2CppInspector.cs @@ -137,7 +137,7 @@ namespace Il2CppInspector BinaryImage.Position = BinaryImage.MapVATR((ulong) pFieldOffsets); for (var f = 0; f < def.field_count; f++) - offsets.Add(def.fieldStart + f, BinaryImage.Stream.ReadObject()); + offsets.Add(def.fieldStart + f, BinaryImage.ReadWord()); } } diff --git a/Il2CppInspector/Reflection/MethodInfo.cs b/Il2CppInspector/Reflection/MethodInfo.cs index 9d49358..0986100 100644 --- a/Il2CppInspector/Reflection/MethodInfo.cs +++ b/Il2CppInspector/Reflection/MethodInfo.cs @@ -52,7 +52,7 @@ namespace Il2CppInspector.Reflection // This probably means it has been optimized away by the compiler, or is an unused generic method try { pkg.BinaryImage.Position = pkg.BinaryImage.MapVATR(Assembly.Module.methodPointers + (ulong) ((method - 1) * (pkg.BinaryImage.Bits / 8))); - VirtualAddress = pkg.BinaryImage.Stream.ReadObject(); + VirtualAddress = (ulong) pkg.BinaryImage.ReadWord(); } catch (Exception) { } } } diff --git a/Il2CppInspector/Reflection/TypeInfo.cs b/Il2CppInspector/Reflection/TypeInfo.cs index ffa7275..c4eefe8 100644 --- a/Il2CppInspector/Reflection/TypeInfo.cs +++ b/Il2CppInspector/Reflection/TypeInfo.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Runtime.InteropServices; namespace Il2CppInspector.Reflection { public class TypeInfo : MemberInfo @@ -224,11 +223,11 @@ namespace Il2CppInspector.Reflection { var genericInstance = image.ReadMappedObject(generic.context.class_inst); // Get list of pointers to type parameters (both unresolved and concrete) - var genericTypeParameters = image.ReadMappedArray(genericInstance.type_argv, (int)genericInstance.type_argc); + var genericTypeParameters = image.ReadMappedWordArray(genericInstance.type_argv, (int)genericInstance.type_argc); GenericTypeParameters = new List(); foreach (var pArg in genericTypeParameters) { - var argType = image.ReadMappedObject(pArg); + var argType = image.ReadMappedObject((ulong) pArg); // TODO: Detect whether unresolved or concrete (add concrete to GenericTypeArguments instead) // TODO: GenericParameterPosition etc. in types we generate here GenericTypeParameters.Add(model.GetType(argType)); // TODO: Fix MemberType here