Formats: Add option for multiple load strategies per sub-image
This commit is contained in:
@@ -21,15 +21,16 @@ namespace Il2CppInspector
|
|||||||
long Length { get; }
|
long Length { get; }
|
||||||
uint NumImages { get; }
|
uint NumImages { get; }
|
||||||
string DefaultFilename { get; }
|
string DefaultFilename { get; }
|
||||||
bool IsModified { get; }
|
bool IsModified { get; }
|
||||||
IEnumerable<IFileFormatReader> Images { get; }
|
IEnumerable<IFileFormatReader> Images { get; } // Each child image of this object (eg. 32/64-bit versions in Fat MachO file)
|
||||||
IFileFormatReader this[uint index] { get; }
|
IFileFormatReader this[uint index] { get; } // With no additional override, one object = one file, this[0] == this
|
||||||
long Position { get; set; }
|
long Position { get; set; }
|
||||||
string Format { get; }
|
string Format { get; }
|
||||||
string Arch { get; }
|
string Arch { get; }
|
||||||
int Bits { get; }
|
int Bits { get; }
|
||||||
ulong GlobalOffset { get; } // The virtual address where the code section (.text) would be loaded in memory
|
ulong GlobalOffset { get; } // The virtual address where the code section (.text) would be loaded in memory
|
||||||
ulong ImageBase { get; } // The virtual address of where the image would be loaded in memory (same as GlobalOffset except for PE)
|
ulong ImageBase { get; } // The virtual address of where the image would be loaded in memory (same as GlobalOffset except for PE)
|
||||||
|
IEnumerable<IFileFormatReader> TryNextLoadStrategy(); // Some images can be loaded multiple ways, eg. default, packed
|
||||||
Dictionary<string, Symbol> GetSymbolTable();
|
Dictionary<string, Symbol> GetSymbolTable();
|
||||||
uint[] GetFunctionTable();
|
uint[] GetFunctionTable();
|
||||||
IEnumerable<Export> GetExports();
|
IEnumerable<Export> GetExports();
|
||||||
@@ -184,9 +185,12 @@ namespace Il2CppInspector
|
|||||||
// Confirm file is valid and set up RVA mappings
|
// Confirm file is valid and set up RVA mappings
|
||||||
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 an image within the file for multi-architecture binaries
|
||||||
public virtual IFileFormatReader this[uint index] => (index == 0)? 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");
|
||||||
|
|
||||||
|
// For images that can be loaded and then tested with Il2CppBinary in multiple ways, get the next possible version of the image
|
||||||
|
public virtual IEnumerable<IFileFormatReader> TryNextLoadStrategy() { yield return this; }
|
||||||
|
|
||||||
// Find search locations in the symbol table for Il2Cpp data
|
// Find search locations in the symbol table for Il2Cpp data
|
||||||
public virtual Dictionary<string, Symbol> GetSymbolTable() => new Dictionary<string, Symbol>();
|
public virtual Dictionary<string, Symbol> GetSymbolTable() => new Dictionary<string, Symbol>();
|
||||||
|
|
||||||
|
|||||||
@@ -95,12 +95,16 @@ namespace Il2CppInspector
|
|||||||
protected Il2CppBinary(IFileFormatReader stream, EventHandler<string> statusCallback = null) {
|
protected Il2CppBinary(IFileFormatReader stream, EventHandler<string> statusCallback = null) {
|
||||||
Image = stream;
|
Image = stream;
|
||||||
OnStatusUpdate = statusCallback;
|
OnStatusUpdate = statusCallback;
|
||||||
|
|
||||||
|
StatusUpdate($"Analyzing IL2CPP data for {Image.Format}/{Image.Arch} image");
|
||||||
DiscoverAPIExports();
|
DiscoverAPIExports();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Il2CppBinary(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration, EventHandler<string> statusCallback = null) {
|
protected Il2CppBinary(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration, EventHandler<string> statusCallback = null) {
|
||||||
Image = stream;
|
Image = stream;
|
||||||
OnStatusUpdate = statusCallback;
|
OnStatusUpdate = statusCallback;
|
||||||
|
|
||||||
|
StatusUpdate($"Analyzing IL2CPP data for {Image.Format}/{Image.Arch} image");
|
||||||
DiscoverAPIExports();
|
DiscoverAPIExports();
|
||||||
PrepareMetadata(codeRegistration, metadataRegistration);
|
PrepareMetadata(codeRegistration, metadataRegistration);
|
||||||
}
|
}
|
||||||
@@ -123,8 +127,12 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
// Load binary without a global-metadata.dat available
|
// Load binary without a global-metadata.dat available
|
||||||
public static Il2CppBinary Load(IFileFormatReader stream, double metadataVersion, EventHandler<string> statusCallback = null) {
|
public static Il2CppBinary Load(IFileFormatReader stream, double metadataVersion, EventHandler<string> statusCallback = null) {
|
||||||
var inst = LoadImpl(stream, statusCallback);
|
foreach (var loadedImage in stream.TryNextLoadStrategy()) {
|
||||||
return inst.FindRegistrationStructs(metadataVersion) ? inst : null;
|
var inst = LoadImpl(stream, statusCallback);
|
||||||
|
if (inst.FindRegistrationStructs(metadataVersion))
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load binary with a global-metadata.dat available
|
// Load binary with a global-metadata.dat available
|
||||||
@@ -133,8 +141,12 @@ namespace Il2CppInspector
|
|||||||
// Metadata will be used to try to find the required structures with data analysis
|
// Metadata will be used to try to find the required structures with data analysis
|
||||||
// If it is not specified, data analysis will not be performed
|
// If it is not specified, data analysis will not be performed
|
||||||
public static Il2CppBinary Load(IFileFormatReader stream, Metadata metadata, EventHandler<string> statusCallback = null) {
|
public static Il2CppBinary Load(IFileFormatReader stream, Metadata metadata, EventHandler<string> statusCallback = null) {
|
||||||
var inst = LoadImpl(stream, statusCallback);
|
foreach (var loadedImage in stream.TryNextLoadStrategy()) {
|
||||||
return inst.FindRegistrationStructs(metadata) ? inst : null;
|
var inst = LoadImpl(stream, statusCallback);
|
||||||
|
if (inst.FindRegistrationStructs(metadata))
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save binary to file, overwriting if necessary
|
// Save binary to file, overwriting if necessary
|
||||||
@@ -146,24 +158,24 @@ namespace Il2CppInspector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize binary without a global-metadata.dat available
|
// Initialize binary without a global-metadata.dat available
|
||||||
public bool FindRegistrationStructs(double metadataVersion, EventHandler<string> statusCallback = null) {
|
public bool FindRegistrationStructs(double metadataVersion) {
|
||||||
Image.Version = metadataVersion;
|
Image.Version = metadataVersion;
|
||||||
|
|
||||||
if (!((FindMetadataFromSymbols() ?? FindMetadataFromCode()) is var ptrs))
|
if (!((FindMetadataFromSymbols() ?? FindMetadataFromCode()) is (ulong code, ulong meta)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
PrepareMetadata(ptrs.Value.Item1, ptrs.Value.Item2);
|
PrepareMetadata(code, meta);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize binary with a global-metadata.dat available
|
// Initialize binary with a global-metadata.dat available
|
||||||
public bool FindRegistrationStructs(Metadata metadata, EventHandler<string> statusCallback = null) {
|
public bool FindRegistrationStructs(Metadata metadata) {
|
||||||
Image.Version = metadata.Version;
|
Image.Version = metadata.Version;
|
||||||
|
|
||||||
if (!((FindMetadataFromSymbols() ?? FindMetadataFromCode() ?? FindMetadataFromData(metadata)) is var ptrs))
|
if (!((FindMetadataFromSymbols() ?? FindMetadataFromCode() ?? FindMetadataFromData(metadata)) is (ulong code, ulong meta)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
PrepareMetadata(ptrs.Value.Item1, ptrs.Value.Item2, metadata);
|
PrepareMetadata(code, meta);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,8 +124,6 @@ namespace Il2CppInspectorGUI
|
|||||||
// Multi-image binaries may contain more than one Il2Cpp image
|
// Multi-image binaries may contain more than one Il2Cpp image
|
||||||
AppModels.Clear();
|
AppModels.Clear();
|
||||||
foreach (var image in stream.Images) {
|
foreach (var image in stream.Images) {
|
||||||
OnStatusUpdate?.Invoke(this, $"Analyzing IL2CPP data for {image.Format}/{image.Arch} image");
|
|
||||||
|
|
||||||
// Architecture-agnostic load attempt
|
// Architecture-agnostic load attempt
|
||||||
try {
|
try {
|
||||||
// If we can't load the IL2CPP data here, it's probably packed or obfuscated; ignore it
|
// If we can't load the IL2CPP data here, it's probably packed or obfuscated; ignore it
|
||||||
|
|||||||
Reference in New Issue
Block a user