diff --git a/patterns/macho.hexpat b/patterns/macho.hexpat index f6a5f96..dce0182 100644 --- a/patterns/macho.hexpat +++ b/patterns/macho.hexpat @@ -4,6 +4,7 @@ #pragma MIME application/x-mach-binary import type.size; +import std.string; enum Magic : u32 { _32BitMagic = 0xFEEDFACE, @@ -367,18 +368,44 @@ struct CommandSegment64 { u8 data[fileSize] @ fileOffset [[sealed]]; }; +struct lc_str { // NB: struct as opposed to it's union def in loader.h + u32 offset; + // It's important to note that the `ptr` field is not used in the Mach-O file itself. + // It is only relevant at runtime when the Mach-O file is loaded into memory. + // The Mach-O file uses the `offset` field to locate the string data within the file. +}; + +struct Dylib { + lc_str name; // always 24 + u32 timestamp; + u32 current_version; + u32 compatibility_version; +}; + +struct LoadDyLib { + Dylib dylib [[inline]]; +}; + struct LoadCommand { Command command; type::Size commandSize; - if (command == Command::UUID) - CommandUUID data; - else if (command == Command::Segment) - CommandSegment data; - else if (command == Command::Segment64) - CommandSegment64 data; - else - u8 data[commandSize - 8] [[sealed]]; + match (command) { + (Command::UUID): CommandUUID data; + (Command::Segment): CommandSegment data; + (Command::Segment64): CommandSegment64 data; + (Command::LoadDyLib | Command::IdDyLib | Command::LoadWeakDyLib): { + LoadDyLib dylib; + + // always 24 bytes in the struct + std::string::NullString dylib_name; + + // the 1 is the size of the string terminator + // not using align here since according to the spec this is computed + padding[commandSize - dylib.dylib.name.offset - 1 - std::string::length(dylib_name)]; + } + (_): u8 data[commandSize - 8] [[sealed]]; + } }; struct MachO {