Load commands are the map
After the Mach header comes a sequence of variable-sized load commands. Each begins with:
struct load_command {
uint32_t cmd;
uint32_t cmdsize;
};
The command identifier says what kind of record follows. cmdsize says how far to advance to the next command.
This makes a Mach-O command region a small tagged-record stream.
Important families include:
- segment mappings such as
LC_SEGMENT_64; - dependency and dylib identity records;
- symbol-table records such as
LC_SYMTAB; - dynamic-linker information;
- minimum OS / build-version metadata;
- entry-point information;
- code-signature location metadata;
- UUID and source/version records.
Parser discipline
For every command:
- verify at least the fixed header fits;
- verify
cmdsizeis large enough for the claimed command type; - verify
cmdsizedoes not run beyond the load-command region; - parse command-specific arrays or strings only inside that validated range;
- advance by exactly
cmdsize.
A malformed command size should produce an error, not an attempt to “keep parsing.”
Why load commands matter more than section-name memorization
Names such as __TEXT, __DATA, and __LINKEDIT are useful conventions. But the load commands are what explicitly describe mapping and metadata locations. If you want to understand what the loader will do, follow the commands.