MachO: Add ability to fetch exports with GetExports()
This commit is contained in:
@@ -25,6 +25,8 @@ namespace Il2CppInspector
|
||||
LC_DYSYMTAB = 0xb,
|
||||
LC_SEGMENT_64 = 0x19,
|
||||
LC_ENCRYPTION_INFO = 0x21,
|
||||
LC_DYLD_INFO = 0x22,
|
||||
LC_DYLD_INFO_ONLY = 0x80000022,
|
||||
LC_FUNCTION_STARTS = 0x26,
|
||||
LC_ENCRYPTION_INFO_64 = 0x2C,
|
||||
|
||||
@@ -90,6 +92,20 @@ namespace Il2CppInspector
|
||||
public uint Size;
|
||||
}
|
||||
|
||||
internal class MachODyldInfoCommand
|
||||
{
|
||||
public uint RebaseOffset;
|
||||
public uint RebaseSize;
|
||||
public uint BindOffset;
|
||||
public uint BindSize;
|
||||
public uint WeakBindOffset;
|
||||
public uint WeakBindSize;
|
||||
public uint LazyBindOffset;
|
||||
public uint LazyBindSize;
|
||||
public uint ExportOffset;
|
||||
public uint ExportSize;
|
||||
}
|
||||
|
||||
internal class MachOSymtabCommand
|
||||
{
|
||||
public uint SymOffset;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
@@ -60,6 +60,8 @@ namespace Il2CppInspector
|
||||
private MachOSection<TWord> funcTab;
|
||||
private MachOSymtabCommand symTab;
|
||||
|
||||
private List<Export> exports = new List<Export>();
|
||||
|
||||
protected MachOReader(Stream stream) : base(stream) { }
|
||||
|
||||
public override string Format => "Mach-O " + (Bits == 32 ? "32-bit" : "64-bit");
|
||||
@@ -103,6 +105,8 @@ namespace Il2CppInspector
|
||||
// Segments
|
||||
case MachO cmd when cmd == lc_Segment:
|
||||
var segment = ReadObject<MachOSegmentCommand<TWord>>();
|
||||
|
||||
// Code and data
|
||||
if (segment.Name == "__TEXT" || segment.Name == "__DATA") {
|
||||
for (int s = 0; s < segment.NumSections; s++) {
|
||||
var section = ReadObject<MachOSection<TWord>>();
|
||||
@@ -128,6 +132,14 @@ namespace Il2CppInspector
|
||||
// TODO: Implement Mach-O dynamic symbol table
|
||||
break;
|
||||
|
||||
// Compressed dyld information
|
||||
case MachO.LC_DYLD_INFO:
|
||||
case MachO.LC_DYLD_INFO_ONLY:
|
||||
var dyld = ReadObject<MachODyldInfoCommand>();
|
||||
|
||||
loadExportTrie(dyld.ExportOffset);
|
||||
break;
|
||||
|
||||
// Encryption check
|
||||
// If cryptid == 1, this binary is encrypted with FairPlay DRM
|
||||
case MachO.LC_ENCRYPTION_INFO:
|
||||
@@ -159,6 +171,51 @@ namespace Il2CppInspector
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle export trie
|
||||
private void loadExportTrie(uint trieOffset, uint nodeOffset = 0, string partialSymbol = "") {
|
||||
Position = trieOffset + nodeOffset;
|
||||
|
||||
var size = ULEB128.Decode(this);
|
||||
|
||||
// Terminal information
|
||||
if (size != 0) {
|
||||
var flags = ReadByte();
|
||||
var symbolKind = flags & 0x03;
|
||||
var symbolType = (flags >> 2) & 0x03;
|
||||
|
||||
// 0 = regular, 1 = weak, 2 = re-export, 3 = stub
|
||||
switch (symbolType) {
|
||||
case 0:
|
||||
var address = ULEB128.Decode(this);
|
||||
exports.Add(new Export {Name = partialSymbol, VirtualAddress = GlobalOffset + address});
|
||||
break;
|
||||
case 1:
|
||||
var weakAddress = ULEB128.Decode(this);
|
||||
exports.Add(new Export {Name = partialSymbol, VirtualAddress = GlobalOffset + weakAddress});
|
||||
break;
|
||||
case 2:
|
||||
var ordinal = ULEB128.Decode(this);
|
||||
var name = ReadNullTerminatedString();
|
||||
break;
|
||||
case 3:
|
||||
var stubOffset = ULEB128.Decode(this);
|
||||
var resolverOffset = ULEB128.Decode(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var branchCount = ReadByte();
|
||||
|
||||
for (int branch = 0; branch < branchCount; branch++) {
|
||||
var prefix = ReadNullTerminatedString();
|
||||
var childNodeOffset = (uint) ULEB128.Decode(this);
|
||||
|
||||
var currentPosition = Position;
|
||||
loadExportTrie(trieOffset, childNodeOffset, partialSymbol + prefix);
|
||||
Position = currentPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public override uint[] GetFunctionTable() => ReadArray<TWord>(funcTab.ImageOffset, conv.Int(funcTab.Size) / (Bits / 8)).Select(x => MapVATR(conv.ULong(x)) & 0xffff_fffe).ToArray();
|
||||
|
||||
public override Dictionary<string, ulong> GetSymbolTable() {
|
||||
@@ -180,7 +237,10 @@ namespace Il2CppInspector
|
||||
if (value != 0)
|
||||
symbols.TryAdd(name, value);
|
||||
}
|
||||
|
||||
return symbols;
|
||||
}
|
||||
|
||||
public override IEnumerable<Export> GetExports() => exports;
|
||||
}
|
||||
}
|
||||
|
||||
23
Il2CppInspector.Common/ULEB128.cs
Normal file
23
Il2CppInspector.Common/ULEB128.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
internal class ULEB128
|
||||
{
|
||||
public static ulong Decode(IFileFormatReader next) {
|
||||
ulong uleb = 0;
|
||||
byte b = 0x80;
|
||||
for (var shift = 0; b >> 7 == 1; shift += 7) {
|
||||
b = next.ReadByte();
|
||||
uleb |= (ulong) (b & 0x7f) << shift;
|
||||
}
|
||||
return uleb;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user