Understanding ld64 Static Linking in iOS: Architecture, Symbol Processing, and Optimization
This article provides an in‑depth technical overview of the ld64 static linker used in iOS builds, explaining its architecture, how it parses .o, .a and .dylib files, manages symbols, atoms and fixups, resolves undefined references, performs dead‑code stripping, and generates the final executable.
The ld64 static linker is the core component that transforms object files (.o), static libraries (.a) and dynamic libraries (.dylib) into an executable for iOS projects. It begins by processing command‑line options, converting all input specifications into absolute file paths, and storing the options in an internal Options object.
During the parsing phase, ld64 reads Mach‑O headers and load commands such as LC_SEGMENT_64 , LC_SYMTAB and LC_DYSYMTAB to extract sections, symbols and relocation entries. For .o files it builds an atom graph where each atom represents a symbol or code fragment, and creates FixupInAtom objects from relocation entries. For .a archives it initially loads only the symbol table, lazily pulling in member object files when an undefined symbol matches an entry. Dynamic libraries and .tbd stubs are parsed to obtain exported symbols and dependency information.
The resolver aggregates atoms into a global SymbolTable , handling strong/weak and visibility rules, merging duplicate atoms, and converting undefined symbols into proxy atoms or loading the necessary archive members. It then performs dead‑code stripping by marking root atoms (entry point, forced symbols, and those marked dont‑dead‑strip ) and traversing the atom graph via fixups to keep only live atoms.
After dead‑strip, ld64 runs a series of passes (e.g., ObjC handling, stub generation, deduplication) to apply further optimizations. Finally, it builds the output sections, writes atom contents, applies fixups, synthesizes the final symbol table, and emits the executable along with optional link maps and debug information.
Additional features such as auto‑linking, the -ObjC flag for loading Objective‑C classes and categories, and various debugging options ( -print_statistics , -why_load , -why_live , -map ) are also explained, illustrating how ld64 can be tuned for iOS development.
ByteDance Dali Intelligent Technology Team
Technical practice sharing from the ByteDance Dali Intelligent Technology Team
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.