Every Mach-O file starts with a header of 28 bytes (32-bit) or 32 bytes (64-bit). The header gives the word size and byte order, the processor, what kind of file it is, and the size of the load commands that follow it.
Fields
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | magic | The magic number: word size and byte order. |
| 4 | 4 | cputype | The processor family: see CPU types. |
| 8 | 4 | cpusubtype | The processor within the family, and feature flags in the top byte. |
| 12 | 4 | filetype | The kind of file. |
| 16 | 4 | ncmds | How many load commands follow. |
| 20 | 4 | sizeofcmds | Their total size in bytes. |
| 24 | 4 | flags | Flags. |
| 28 | 4 | reserved | 64-bit files only. Reserved. |
All fields are in the byte order the magic number shows. The numbers in the examples on this site are little-endian, as on current Macs.
00000000 CF FA ED FE 0C 00 00 01 02 00 00 80 02 00 00 00
00000010 10 00 00 00 38 03 00 00 85 00 20 00 00 00 00 00
/usr/bin/true: MH_MAGIC_64 read little-endian, CPU type 0x0100000C (ARM64), subtype 0x80000002 (arm64e, with the ABI flag set), file type 2 (executable), 16 load commands in 824 bytes, flags 0x00200085: NOUNDEFS, DYLDLINK, TWOLEVEL and PIE.Magic number
| Bytes on disk | Value (big-endian) | Constant | Meaning |
|---|---|---|---|
FE ED FA CE | 0xFEEDFACE | MH_MAGIC | 32-bit, big-endian |
CE FA ED FE | 0xCEFAEDFE | MH_CIGAM | 32-bit, little-endian |
FE ED FA CF | 0xFEEDFACF | MH_MAGIC_64 | 64-bit, big-endian |
CF FA ED FE | 0xCFFAEDFE | MH_CIGAM_64 | 64-bit, little-endian (current Macs) |
A file that starts CA FE BA BE is a universal binary, which holds one of these for each architecture.
CPU types
The types and subtypes are in <mach/machine.h>. Bit 24 of the type marks a 64-bit ABI, bit 25 the 32-bit pointers of arm64_32. The ones you are likely to meet:
| cputype | Name | Common subtypes (low 24 bits) |
|---|---|---|
0x00000007 | x86 (i386) | 3 all, 4 486, 5 Pentium |
0x01000007 | x86-64 | 3 all, 4 Arch1, 8 Haswell (x86_64h) |
0x0000000C | ARM | 6 v6, 9 v7, 11 v7s, 12 v7k |
0x0100000C | ARM64 | 0 all, 1 v8, 2 arm64e (pointer authentication), 3 X1, 12 arm64e X1 |
0x0200000C | ARM64_32 | 0 all, 1 v8 |
0x00000012 | PowerPC | 0 all, 100 G5 (970) |
0x01000012 | PowerPC 64 | 0 all, 100 G5 (970) |
The top byte of the subtype holds flags. For x86-64, 0x80000000 asks for 64-bit system libraries. For arm64e, it marks the version of the pointer authentication ABI (bits 24 to 27 give the number).
Values 1 (VAX), 6 (MC680x0), 10 (MC98000), 11 (HP-PA), 13 (MC88000), 14 (SPARC) and 15 (i860) are also defined, but do not appear in modern files.
File types
| Value | Constant | Meaning |
|---|---|---|
| 1 | MH_OBJECT | Relocatable object file (.o). All sections are in one unnamed segment. |
| 2 | MH_EXECUTE | Executable program. |
| 3 | MH_FVMLIB | Fixed virtual memory shared library (obsolete). |
| 4 | MH_CORE | Core dump. |
| 5 | MH_PRELOAD | Executable that is not loaded under the kernel (ROMs, kernels). |
| 6 | MH_DYLIB | Dynamic library (.dylib). |
| 7 | MH_DYLINKER | The dynamic linker itself (dyld). |
| 8 | MH_BUNDLE | A plug-in loaded at run time (.bundle). |
| 9 | MH_DYLIB_STUB | Library stub for static linking only, with no section contents. |
| 10 | MH_DSYM | Companion file with debug sections only. |
| 11 | MH_KEXT_BUNDLE | Kernel extension. |
| 12 | MH_FILESET | A file set: several Mach-O files that share one __LINKEDIT, as in kernel caches. |
| 13 | MH_GPU_EXECUTE | GPU program. |
| 14 | MH_GPU_DYLIB | GPU support functions. |
Flags
| Bit | Constant | Meaning |
|---|---|---|
0x1 | MH_NOUNDEFS | No undefined references. |
0x2 | MH_INCRLINK | The output of an incremental link. |
0x4 | MH_DYLDLINK | Input for the dynamic linker. |
0x8 | MH_BINDATLOAD | Undefined references are bound when loaded. |
0x10 | MH_PREBOUND | Dynamic references are prebound. |
0x20 | MH_SPLIT_SEGS | Read-only and writable segments are split. |
0x40 | MH_LAZY_INIT | Obsolete. |
0x80 | MH_TWOLEVEL | Uses two-level namespace bindings. |
0x100 | MH_FORCE_FLAT | Forces flat namespace bindings. |
0x200 | MH_NOMULTIDEFS | This umbrella guarantees no multiple definitions. |
0x400 | MH_NOFIXPREBINDING | Do not notify the prebinding agent. |
0x800 | MH_PREBINDABLE | Not prebound, but can have prebinding redone. |
0x1000 | MH_ALLMODSBOUND | Binds to all two-level modules of its libraries. |
0x2000 | MH_SUBSECTIONS_VIA_SYMBOLS | Sections can be divided by symbol for dead stripping. |
0x4000 | MH_CANONICAL | Canonicalised via the unprebind operation. |
0x8000 | MH_WEAK_DEFINES | Contains external weak symbols. |
0x10000 | MH_BINDS_TO_WEAK | Uses weak symbols. |
0x20000 | MH_ALLOW_STACK_EXECUTION | Allows execution on the stack. |
0x40000 | MH_ROOT_SAFE | Safe for processes with uid 0. |
0x80000 | MH_SETUID_SAFE | Safe when issetugid() is true. |
0x100000 | MH_NO_REEXPORTED_DYLIBS | This library re-exports nothing. |
0x200000 | MH_PIE | Load the main executable at a random address. |
0x400000 | MH_DEAD_STRIPPABLE_DYLIB | Do not link this library unless one of its symbols is used. |
0x800000 | MH_HAS_TLV_DESCRIPTORS | Has thread-local variables. |
0x1000000 | MH_NO_HEAP_EXECUTION | Runs with a non-executable heap. |
0x2000000 | MH_APP_EXTENSION_SAFE | Linked for use in an application extension. |
0x4000000 | MH_NLIST_OUTOFSYNC_WITH_DYLDINFO | External symbols in the symbol table do not include all those in the dyld info. |
0x8000000 | MH_SIM_SUPPORT | Allows both macOS and simulator version load commands. |
0x10000000 | MH_IMPLICIT_PAGEZERO | The executable has no __PAGEZERO; the kernel loads it high. |
0x80000000 | MH_DYLIB_IN_CACHE | This library is part of the dyld shared cache. |