How DWARF, Mach-O, and dSYM Actually Turn a Crash Address Into a Line Number
Without a working mental model of these three pieces, crash reports stay opaque hex dumps. Knowing that UUID matching is the only reliable way to pair a binary with its dSYM — and that `.debug_line`, not `.debug_info`, supplies the executing line number — prevents hours of misattributed blame when optimization inlines or reorders code.
DWARF is a standardized data format that maps compiled machine addresses back to functions, variables, source files, and line numbers through a set of interlocking sections — the core being `.debug_info` for program entities and `.debug_line` for address-to-source-line mappings. Mach-O is Apple’s binary container that organizes machine code, load commands, segments, and an optional `__DWARF` segment, while also carrying the UUID that ties a running image to its debug data. A dSYM is a directory bundle containing a companion Mach-O of type `MH_DSYM` whose sole job is to hold the final linked DWARF for a specific build, matched by UUID.
During a Release build, the compiler emits DWARF fragments into `.o` object files, the linker produces the final address layout in the executable, and `dsymutil` collects and links those fragments into a dSYM keyed to the final addresses. At crash time, the runtime address is corrected for ASLR slide using the image’s load address and Mach-O link base, then the matching dSYM’s DWARF sections resolve it to a function name, file, and line number.
The common confusion between `.debug_info` declaration lines and `.debug_line` execution lines is a practical footgun: a crash at address `0x1c` maps to the executing line 3, not the declaration line 1, and tools that surface the wrong one send developers to the wrong code.
dSYM is often discussed as if it were a file format, but it is a directory bundle containing a Mach-O — a design that lets the same Mach-O parsing infrastructure handle both executables and their debug data.
ASLR slide calculation is straightforward arithmetic, yet many symbolication failures trace to mismatched load addresses or missing link-base metadata, not to missing DWARF.