Introduction
Mach-O, short for Mach object, is the format of programs, libraries and object files on Apple’s macOS, iOS, iPadOS, watchOS and tvOS. It came from the Mach kernel through NeXTSTEP, which became Mac OS X.
Mach-O programs have no extension: the program inside an app bundle, such as
Safari.app/Contents/MacOS/Safari, is a Mach-O file. The extensions that do
appear are .dylib for dynamic libraries, .bundle for plug-ins
and .o for object files. A universal binary wraps several Mach-O files, one
per processor, such as one for Intel and one for Apple silicon, in a single file.
Structure
A Mach-O file starts with a header: a magic number that gives the word size and byte
order (0xFEEDFACE for 32-bit, 0xFEEDFACF for 64-bit), the
processor type, the file type (1 object, 2 executable, 6 dynamic library, 8 bundle and
others), and the number and total size of the load commands that follow. The header is
28 bytes for 32-bit files and 32 bytes for 64-bit ones.
Load commands describe everything else: the segments to map into memory and the sections inside them, the symbol table, the libraries to link, the entry point, the code signature and more. Each command starts with its type and size, so a reader can skip the ones it does not know.
A universal binary starts instead with the big-endian magic CA FE BA BE,
a count of architectures, and one 20-byte entry per architecture giving the processor
type and the offset and size of that architecture’s Mach-O file inside it.
0header: magic, CPU type, file type, load command count and size, flags28 or 32 bytes28 or 32load commands, each a type and size, then its fieldssizeofcmds bytes…segment data:__TEXTcode,__DATA,__LINKEDITsymbols and signaturesvaries