Tidy up FileFormatReader stream access methods

This commit is contained in:
Katy Coe
2019-10-23 23:51:16 +02:00
parent 19127a6649
commit 1a3028087d
6 changed files with 37 additions and 30 deletions

View File

@@ -7,7 +7,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.IsolatedStorage;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using NoisyCowStudios.Bin2Object; using NoisyCowStudios.Bin2Object;
@@ -17,6 +16,8 @@ namespace Il2CppInspector
public interface IFileFormatReader public interface IFileFormatReader
{ {
BinaryObjectReader Stream { get; } BinaryObjectReader Stream { get; }
double Version { get; set; }
long Length { get; }
uint NumImages { get; } uint NumImages { get; }
IEnumerable<IFileFormatReader> Images { get; } IEnumerable<IFileFormatReader> Images { get; }
IFileFormatReader this[uint index] { get; } IFileFormatReader this[uint index] { get; }
@@ -29,13 +30,21 @@ namespace Il2CppInspector
uint[] GetFunctionTable(); uint[] GetFunctionTable();
U ReadMappedObject<U>(ulong uiAddr) where U : new(); U ReadMappedObject<U>(ulong uiAddr) where U : new();
U[] ReadMappedArray<U>(ulong uiAddr, int count) where U : new(); U[] ReadMappedArray<U>(ulong uiAddr, int count) where U : new();
long[] ReadMappedWordArray(ulong uiAddr, int count);
uint MapVATR(ulong uiAddr); uint MapVATR(ulong uiAddr);
byte[] ReadBytes(int count); byte[] ReadBytes(int count);
ulong ReadUInt64(); ulong ReadUInt64();
ulong ReadUInt64(long uiAddr);
uint ReadUInt32(); uint ReadUInt32();
uint ReadUInt32(long uiAddr);
ushort ReadUInt16(); ushort ReadUInt16();
ushort ReadUInt16(long uiAddr);
byte ReadByte(); byte ReadByte();
byte ReadByte(long uiAddr);
long ReadWord();
long ReadWord(long uiAddr);
U ReadObject<U>() where U : new();
string ReadMappedNullTerminatedString(ulong uiAddr); string ReadMappedNullTerminatedString(ulong uiAddr);
List<U> ReadMappedObjectPointerArray<U>(ulong uiAddr, int count) where U : new(); List<U> ReadMappedObjectPointerArray<U>(ulong uiAddr, int count) where U : new();
} }
@@ -65,6 +74,8 @@ namespace Il2CppInspector
public BinaryObjectReader Stream => this; public BinaryObjectReader Stream => this;
public long Length => BaseStream.Length;
public uint NumImages { get; protected set; } = 1; public uint NumImages { get; protected set; } = 1;
public ulong GlobalOffset { get; protected set; } public ulong GlobalOffset { get; protected set; }
@@ -83,8 +94,8 @@ namespace Il2CppInspector
} }
public static T Load(string filename) { public static T Load(string filename) {
using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read);
return Load(stream); return Load(stream);
} }
public static T Load(Stream stream) { public static T Load(Stream stream) {
@@ -102,13 +113,7 @@ namespace Il2CppInspector
protected virtual bool Init() => throw new NotImplementedException(); protected virtual bool Init() => throw new NotImplementedException();
// Choose a sub-binary within the image for multi-architecture binaries // Choose a sub-binary within the image for multi-architecture binaries
public virtual IFileFormatReader this[uint index] { public virtual IFileFormatReader this[uint index] => (index == 0)? this : throw new IndexOutOfRangeException("Binary image index out of bounds");
get {
if (index == 0)
return this;
throw new IndexOutOfRangeException("Binary image index out of bounds");
}
}
// Find search locations in the symbol table for Il2Cpp data // Find search locations in the symbol table for Il2Cpp data
public virtual Dictionary<string, ulong> GetSymbolTable() => null; public virtual Dictionary<string, ulong> GetSymbolTable() => null;
@@ -120,18 +125,21 @@ namespace Il2CppInspector
// No mapping by default // No mapping by default
public virtual uint MapVATR(ulong uiAddr) => (uint) uiAddr; 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<long>();
public long ReadWord(long uiAddr) => ReadObject<long>(uiAddr);
// Retrieve object(s) from specified RVA(s) // Retrieve object(s) from specified RVA(s)
public U ReadMappedObject<U>(ulong uiAddr) where U : new() { public U ReadMappedObject<U>(ulong uiAddr) where U : new() => ReadObject<U>(MapVATR(uiAddr));
return ReadObject<U>(MapVATR(uiAddr));
}
public U[] ReadMappedArray<U>(ulong uiAddr, int count) where U : new() { public U[] ReadMappedArray<U>(ulong uiAddr, int count) where U : new() => ReadArray<U>(MapVATR(uiAddr), count);
return ReadArray<U>(MapVATR(uiAddr), count);
}
public string ReadMappedNullTerminatedString(ulong uiAddr) { // Read a file format dependent array of words (32 or 64 bits)
return ReadNullTerminatedString(MapVATR(uiAddr)); // The primitive mappings in Bin2Object will automatically read a uint if the file is 32-bit
} public long[] ReadMappedWordArray(ulong uiAddr, int count) => ReadArray<long>(MapVATR(uiAddr), count);
public string ReadMappedNullTerminatedString(ulong uiAddr) => ReadNullTerminatedString(MapVATR(uiAddr));
// Reads a list of pointers, then reads each object pointed to // Reads a list of pointers, then reads each object pointed to
public List<U> ReadMappedObjectPointerArray<U>(ulong uiAddr, int count) where U : new() { public List<U> ReadMappedObjectPointerArray<U>(ulong uiAddr, int count) where U : new() {

View File

@@ -64,7 +64,7 @@ namespace Il2CppInspector
// Check all search locations // Check all search locations
public bool Initialize(double version, uint imageIndex = 0) { public bool Initialize(double version, uint imageIndex = 0) {
var subImage = Image[imageIndex]; var subImage = Image[imageIndex];
subImage.Stream.Version = version; subImage.Version = version;
// Try searching the symbol table // Try searching the symbol table
var symbols = subImage.GetSymbolTable(); var symbols = subImage.GetSymbolTable();
@@ -128,11 +128,11 @@ namespace Il2CppInspector
MetadataRegistration = image.ReadMappedObject<Il2CppMetadataRegistration>(metadataRegistration); MetadataRegistration = image.ReadMappedObject<Il2CppMetadataRegistration>(metadataRegistration);
// The global method pointer list was deprecated in v24.2 in favour of Il2CppCodeGenModule // 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<ulong>(CodeRegistration.pmethodPointers, (int) CodeRegistration.methodPointersCount); GlobalMethodPointers = image.ReadMappedArray<ulong>(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.2) { if (Image.Version >= 24.2) {
Modules = new Dictionary<string, Il2CppCodeGenModule>(); Modules = new Dictionary<string, Il2CppCodeGenModule>();
// Array of pointers to Il2CppCodeGenModule // 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 // Field offset data. Metadata <=21.x uses a value-type array; >=21.x uses a pointer array
FieldOffsetData = image.ReadMappedArray<long>(MetadataRegistration.pfieldOffsets, (int) MetadataRegistration.fieldOffsetsCount); FieldOffsetData = image.ReadMappedWordArray(MetadataRegistration.pfieldOffsets, (int) MetadataRegistration.fieldOffsetsCount);
// Type definitions (pointer array) // Type definitions (pointer array)
Types = image.ReadMappedObjectPointerArray<Il2CppType>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount); Types = image.ReadMappedObjectPointerArray<Il2CppType>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount);

View File

@@ -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. All rights reserved.
*/ */
@@ -50,7 +50,7 @@ namespace Il2CppInspector
image.Position += 8; image.Position += 8;
funcPtr = image.MapVATR(image.ReadUInt32() + image.GlobalOffset); funcPtr = image.MapVATR(image.ReadUInt32() + image.GlobalOffset);
if (funcPtr > image.Stream.BaseStream.Length) if (funcPtr > image.Length)
return (0, 0); return (0, 0);
// Extract Metadata pointer // Extract Metadata pointer

View File

@@ -137,7 +137,7 @@ namespace Il2CppInspector
BinaryImage.Position = BinaryImage.MapVATR((ulong) pFieldOffsets); BinaryImage.Position = BinaryImage.MapVATR((ulong) pFieldOffsets);
for (var f = 0; f < def.field_count; f++) for (var f = 0; f < def.field_count; f++)
offsets.Add(def.fieldStart + f, BinaryImage.Stream.ReadObject<long>()); offsets.Add(def.fieldStart + f, BinaryImage.ReadWord());
} }
} }

View File

@@ -52,7 +52,7 @@ namespace Il2CppInspector.Reflection
// This probably means it has been optimized away by the compiler, or is an unused generic method // This probably means it has been optimized away by the compiler, or is an unused generic method
try { try {
pkg.BinaryImage.Position = pkg.BinaryImage.MapVATR(Assembly.Module.methodPointers + (ulong) ((method - 1) * (pkg.BinaryImage.Bits / 8))); pkg.BinaryImage.Position = pkg.BinaryImage.MapVATR(Assembly.Module.methodPointers + (ulong) ((method - 1) * (pkg.BinaryImage.Bits / 8)));
VirtualAddress = pkg.BinaryImage.Stream.ReadObject<ulong>(); VirtualAddress = (ulong) pkg.BinaryImage.ReadWord();
} catch (Exception) { } } catch (Exception) { }
} }
} }

View File

@@ -8,7 +8,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
namespace Il2CppInspector.Reflection { namespace Il2CppInspector.Reflection {
public class TypeInfo : MemberInfo public class TypeInfo : MemberInfo
@@ -224,11 +223,11 @@ namespace Il2CppInspector.Reflection {
var genericInstance = image.ReadMappedObject<Il2CppGenericInst>(generic.context.class_inst); var genericInstance = image.ReadMappedObject<Il2CppGenericInst>(generic.context.class_inst);
// Get list of pointers to type parameters (both unresolved and concrete) // Get list of pointers to type parameters (both unresolved and concrete)
var genericTypeParameters = image.ReadMappedArray<ulong>(genericInstance.type_argv, (int)genericInstance.type_argc); var genericTypeParameters = image.ReadMappedWordArray(genericInstance.type_argv, (int)genericInstance.type_argc);
GenericTypeParameters = new List<TypeInfo>(); GenericTypeParameters = new List<TypeInfo>();
foreach (var pArg in genericTypeParameters) { foreach (var pArg in genericTypeParameters) {
var argType = image.ReadMappedObject<Il2CppType>(pArg); var argType = image.ReadMappedObject<Il2CppType>((ulong) pArg);
// TODO: Detect whether unresolved or concrete (add concrete to GenericTypeArguments instead) // TODO: Detect whether unresolved or concrete (add concrete to GenericTypeArguments instead)
// TODO: GenericParameterPosition etc. in types we generate here // TODO: GenericParameterPosition etc. in types we generate here
GenericTypeParameters.Add(model.GetType(argType)); // TODO: Fix MemberType here GenericTypeParameters.Add(model.GetType(argType)); // TODO: Fix MemberType here