Add Fat Mach-O (Universal Binary) support

Fix fieldOffsets bug in some metadata versions
Add support for generic multi-architecture binaries
Add Mach-O section RVA mapping
This commit is contained in:
Katy Coe
2017-10-23 12:35:59 +02:00
parent fef4d3d8f3
commit 16b56e271b
9 changed files with 218 additions and 82 deletions

View File

@@ -20,7 +20,7 @@ namespace Il2CppInspector
Metadata = metadata;
}
public static Il2CppProcessor LoadFromFile(string codeFile, string metadataFile) {
public static List<Il2CppProcessor> LoadFromFile(string codeFile, string metadataFile) {
// Load the metadata file
Metadata metadata;
try {
@@ -34,36 +34,41 @@ namespace Il2CppInspector
// Load the il2cpp code file (try ELF and PE)
var memoryStream = new MemoryStream(File.ReadAllBytes(codeFile));
IFileFormatReader stream =
((IFileFormatReader) ElfReader.Load(memoryStream) ??
PEReader.Load(memoryStream)) ??
MachOReader.Load(memoryStream);
(((IFileFormatReader) ElfReader.Load(memoryStream) ??
PEReader.Load(memoryStream)) ??
MachOReader.Load(memoryStream)) ??
UBReader.Load(memoryStream);
if (stream == null) {
Console.Error.WriteLine("Unsupported executable file format");
return null;
}
Il2CppReader il2cpp;
var processors = new List<Il2CppProcessor>();
foreach (var image in stream.Images) {
Il2CppReader il2cpp;
// We are currently supporting x86 and ARM architectures
switch (stream.Arch) {
case "x86":
il2cpp = new Il2CppReaderX86(stream);
break;
case "ARM":
il2cpp = new Il2CppReaderARM(stream);
break;
default:
Console.Error.WriteLine("Unsupported architecture");
return null;
// We are currently supporting x86 and ARM architectures
switch (image.Arch) {
case "x86":
il2cpp = new Il2CppReaderX86(image);
break;
case "ARM":
il2cpp = new Il2CppReaderARM(image);
break;
default:
Console.Error.WriteLine("Unsupported architecture");
return null;
}
// Find code and metadata regions
if (!il2cpp.Load(metadata.Version)) {
Console.Error.WriteLine("Could not process IL2CPP image");
}
else {
processors.Add(new Il2CppProcessor(il2cpp, metadata));
}
}
// Find code and metadata regions
if (!il2cpp.Load(metadata.Version)) {
Console.Error.WriteLine("Could not process IL2CPP image");
return null;
}
return new Il2CppProcessor(il2cpp, metadata);
return processors;
}
public string GetTypeName(Il2CppType pType) {
@@ -106,6 +111,31 @@ namespace Il2CppInspector
return ret;
}
public Il2CppType GetTypeFromTypeIndex(int idx) {
return Code.PtrMetadataRegistration.types[idx];
}
public int GetFieldOffsetFromIndex(int typeIndex, int fieldIndexInType) {
// Versions from 22 onwards use an array of pointers in fieldOffsets
bool fieldOffsetsArePointers = (Metadata.Version >= 22);
// Some variants of 21 also use an array of pointers
if (Metadata.Version == 21) {
var f = Code.PtrMetadataRegistration.fieldOffsets;
fieldOffsetsArePointers = (f[0] == 0 && f[1] == 0 && f[2] == 0 && f[3] == 0 && f[4] == 0 && f[5] > 0);
}
// All older versions use values directly in the array
if (!fieldOffsetsArePointers) {
var typeDef = Metadata.Types[typeIndex];
return Code.PtrMetadataRegistration.fieldOffsets[typeDef.fieldStart + fieldIndexInType];
}
var ptr = Code.PtrMetadataRegistration.fieldOffsets[typeIndex];
Code.Image.Stream.Position = Code.Image.MapVATR((uint)ptr) + 4 * fieldIndexInType;
return Code.Image.Stream.ReadInt32();
}
private readonly string[] szTypeString =
{
"END",