MachO: Read __mod_init_func instead of LC_FUNCTION_STARTS

This commit is contained in:
Katy Coe
2019-10-27 22:00:48 +01:00
parent 1616699977
commit b863cf74b8

View File

@@ -6,14 +6,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using NoisyCowStudios.Bin2Object; using NoisyCowStudios.Bin2Object;
namespace Il2CppInspector namespace Il2CppInspector
{ {
internal class MachOReader32 : MachOReader<uint, MachOReader32> internal class MachOReader32 : MachOReader<uint, MachOReader32, Convert32>
{ {
public MachOReader32(Stream stream) : base(stream) { } public MachOReader32(Stream stream) : base(stream) { }
@@ -30,7 +29,7 @@ namespace Il2CppInspector
} }
} }
internal class MachOReader64 : MachOReader<ulong, MachOReader64> internal class MachOReader64 : MachOReader<ulong, MachOReader64, Convert64>
{ {
public MachOReader64(Stream stream) : base(stream) { } public MachOReader64(Stream stream) : base(stream) { }
@@ -48,11 +47,16 @@ namespace Il2CppInspector
// We need this convoluted generic TReader declaration so that "static T FileFormatReader.Load(Stream)" // We need this convoluted generic TReader declaration so that "static T FileFormatReader.Load(Stream)"
// is inherited to MachOReader32/64 with a correct definition of T // is inherited to MachOReader32/64 with a correct definition of T
internal abstract class MachOReader<TWord, TReader> : FileFormatReader<TReader> where TWord : struct where TReader : FileFormatReader<TReader> internal abstract class MachOReader<TWord, TReader, TConvert> : FileFormatReader<TReader>
where TWord : struct
where TReader : FileFormatReader<TReader>
where TConvert : IWordConverter<TWord>, new()
{ {
private readonly TConvert conv = new TConvert();
private MachOHeader<TWord> header; private MachOHeader<TWord> header;
protected readonly List<MachOSection<TWord>> sections = new List<MachOSection<TWord>>(); protected readonly List<MachOSection<TWord>> sections = new List<MachOSection<TWord>>();
private MachOLinkEditDataCommand funcTab; private MachOSection<TWord> funcTab;
private MachOSymtabCommand symTab; private MachOSymtabCommand symTab;
protected MachOReader(Stream stream) : base(stream) { } protected MachOReader(Stream stream) : base(stream) { }
@@ -105,13 +109,13 @@ namespace Il2CppInspector
if (section.Name == "__text") { if (section.Name == "__text") {
GlobalOffset = (ulong) Convert.ChangeType(section.Address, typeof(ulong)) - section.ImageOffset; GlobalOffset = (ulong) Convert.ChangeType(section.Address, typeof(ulong)) - section.ImageOffset;
} }
}
}
break;
// Location of function table // Initialization (pre-main) functions
case MachO.LC_FUNCTION_STARTS: if (section.Name == "__mod_init_func") {
funcTab = ReadObject<MachOLinkEditDataCommand>(); funcTab = section;
}
}
}
break; break;
// Location of static symbol table // Location of static symbol table
@@ -128,7 +132,7 @@ namespace Il2CppInspector
Position = startPos + loadCommand.Size; Position = startPos + loadCommand.Size;
} }
// Must find LC_FUNCTION_STARTS load command // Must find __mod_init_func
if (funcTab == null) if (funcTab == null)
return false; return false;
@@ -145,31 +149,7 @@ namespace Il2CppInspector
return true; return true;
} }
public override uint[] GetFunctionTable() { public override uint[] GetFunctionTable() => ReadArray<TWord>(funcTab.ImageOffset, conv.Int(funcTab.Size) / (Bits / 8)).Select(x => MapVATR(conv.ULong(x)) & 0xffff_fffe).ToArray();
Position = funcTab.Offset;
var functionPointers = new List<uint>();
// Decompress ELB128 list of function offsets
// https://en.wikipedia.org/wiki/LEB128
uint previous = 0;
while (Position < funcTab.Offset + funcTab.Size) {
uint result = 0;
int shift = 0;
byte b;
do {
b = ReadByte();
result |= (uint)((b & 0x7f) << shift);
shift += 7;
} while ((b & 0x80) != 0);
if (result > 0) {
if (previous == 0)
result &= 0xffffffc;
previous += result;
functionPointers.Add(previous);
}
}
return functionPointers.ToArray();
}
public override Dictionary<string, ulong> GetSymbolTable() { public override Dictionary<string, ulong> GetSymbolTable() {
var symbols = new Dictionary<string, ulong>(); var symbols = new Dictionary<string, ulong>();