A universal binary, also called a fat binary, holds several complete Mach-O files, one
for each processor, behind a short header. lipo creates and splits them.
Each member is a Mach-O file of its own, and the offsets inside it count from the start
of that member, not from the start of the fat file.
Layout
0fat_header: magic number and the number of architectures8 bytes8fat_arch entries, one per architecture20 bytes each (32 in the 64-bit form)…padding, zeros, up to each member’s alignmentvariesoffseta whole Mach-O file for each architecture, in the order of the entriessize bytes
Header
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | magic | 0xCAFEBABE (FAT_MAGIC), or 0xCAFEBABF (FAT_MAGIC_64) for the 64-bit form. |
| 4 | 4 | nfat_arch | The number of architecture entries that follow. |
fat_arch
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 | cputype | The processor family, as in the Mach header. |
| 4 | 4 | cpusubtype | The processor within the family. |
| 8 | 4 | offset | The file offset of this member. |
| 12 | 4 | size | The member’s size in bytes. |
| 16 | 4 | align | Its alignment in the file, as a power of 2. Padding before it reads as zeros. |
The 64-bit form, used when an offset or a size does not fit in 32 bits, has
offset and size as 8-byte values, then
align (4 bytes) and a reserved field (4 bytes): 32 bytes for
each entry.
00000000 CA FE BA BE 00 00 00 03 01 00 00 07 00 00 00 03
00000010 00 00 40 00 00 00 58 40 00 00 00 0E 01 00 00 0C
00000020 80 00 00 02 00 00 C0 00 00 00 88 40 00 00 00 0E
00000030 01 00 00 0C 80 00 00 0C 00 01 80 00 00 00 88 40
00000040 00 00 00 0E
/usr/bin/true, with three architectures: x86-64 at 0x4000 (0x5840 bytes), arm64e at 0xC000 and arm64e with subtype 12 at 0x18000, each aligned to 214 bytes (16 KB).Java class files
Java class files start with the same 0xCAFEBABE. In a class file, the
next four bytes are the minor and major version: 45 or higher as a 32-bit number. In a
universal binary they are the number of architectures, which is small. The explorer
treats a count of 1 to 32 as a universal binary.
In the explorer
Each architecture is opened as a file of its own, so its header, load commands, symbols and code can be browsed separately. Bytes between members are shown as padding.