Common Misconceptions in iOS15 Dynamic Linking and Mach‑O Fixup Chains
This article clarifies three frequent misunderstandings about iOS15+ dynamic linking—namely the encoding of b/bl instructions, the need for rebase/bind in __TEXT segments, and the mismatch between Mach‑O segment VM size and file size—by explaining the underlying ARM64 architecture, PIC concepts, and providing concrete dyld tool examples.
Background – The performance‑oriented iOS15 dynamic linking fixup chain analysis sparked interest in the Mach‑O compilation and linking process, prompting a review of three typical beginner misconceptions.
Misconception 1: b/bl instructions contain absolute addresses
In Xcode’s disassembly view, the bl 0x10239e3a4 line appears to show an absolute address, but the ARM64 specification defines the low 26 bits of the instruction as a signed offset (imm26) relative to the program counter. The high 6 bits are reserved. By reading the raw bytes ( 0x9b010094 → little‑endian 0x9400019b ) and extracting imm26 = 0x19b , the absolute target address is computed as 0x10239dd38 + 0x19b * 4 = 0x10239e3a4 , matching Xcode’s output. The reachable range of b/bl is ±128 MiB.
(lldb) memory read 0x10239dd38
0x10239dd38: 9b 01 00 94 fd 7b 42 a9 ff c3 00 91 c0 03 5f d6 .....{B......._.
0x10239dd48: ff 43 00 d1 e0 07 00 f9 e1 03 00 f9 e8 07 40 f9 .C............@.Conclusion – b/bl store a PC‑relative offset, not an absolute address.
Insight – Disassembly tools may present optimized views; understanding the underlying encoding prevents being misled.
Misconception 2: b/bl addresses in the __TEXT segment require rebase/bind
The belief stems from assuming that all addresses need runtime fix‑ups. However, the __TEXT segment is marked r‑x (read‑execute, not writable), so it cannot be modified at runtime. Only symbols residing in __DATA or __DATA_CONST need rebase or bind, following the PIC model used by Mach‑O.
External symbols are stored in __got (non‑lazy) or __la_symbos_ptr (lazy) sections, and the dyld tool dyld_info -fixups can list them. Example usage:
./dyld_info -fixups ./machoName > fixups.txt
Filtering for rebase or bind:
./dyld_info -fixups ./machoName | grep 'rebase' > rebase.txt ./dyld_info -fixups ./machoName | grep 'bind' > bind.txt
Conclusion – Only __DATA and __DATA_CONST segments contain addresses that require runtime fix‑ups.
Insight – The root cause is a misunderstanding of Mach‑O symbol resolution and the role of PIC, which also appears in Linux PLT/GOT mechanisms.
Misconception 3: Mach‑O segment VM size always equals file size
Observing that __TEXT and __DATA_CONST segments have matching sizes leads to the false generalisation that all segments behave similarly. In reality, file offsets are packed without alignment gaps, while VM addresses must be 4 KB aligned, causing possible size differences.
Illustrative code from the “deep‑understanding Mach‑O” blog shows how to compute the base of the __LINKEDIT segment and locate symbol tables:
// Find __LINKEDIT base address
uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff;
// Locate symbol table
nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff);
// Locate string table
char *strtab = (char *)(linkedit_base + symtab_cmd->stroff);
// Indirect symbol table
uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff);From these equations, the relationship between VM address and file offset can be expressed as:
symtab.vmaddr - __LINKEDIT.vmaddr = symtab.fileoff - __LINKEDIT.fileoff
Including ASLR (slide) yields:
symtab_base = linkedit_base + symtab.fileoff
Conclusion – VM size may be larger due to 4 KB alignment, while file size has no such requirement.
Insight – Relying solely on empirical observations without understanding the underlying alignment rules can lead to incorrect assumptions.
References
[1] "iOS15 Dynamic Linking Fixup Chain Detailed Explanation"
[2] ARM64 BL instruction encoding
[3] "iOS Programmer's Self‑Cultivation – Mach‑O Dynamic Linking (Part 4)"
[4] "Deep Understanding of Mach‑O Structure and Runtime System"
[5] StackOverflow answer on Mach‑O rebasing
[6] dyld4 source code (dyld_info.cpp)
[7] Zhihu discussion on Linux PLT/GOT
ByteDance Terminal Technology
Official account of ByteDance Terminal Technology, sharing technical insights and team updates.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.