跪拜 Guibai
← All articles
iOS · Assembly Language

How DWARF, Mach-O, and dSYM Actually Turn a Crash Address Into a Line Number

By _瑞 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

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.

Summary

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.

Takeaways
DWARF is a debug-data format, not a file; its `.debug_line` section maps machine addresses to executing source lines, while `.debug_info` records declarations, types, and scopes.
Mach-O is Apple’s binary container that holds machine code, load commands, segments, and an optional `__DWARF` segment, plus the UUID that identifies a build.
A dSYM is a directory bundle wrapping a `MH_DSYM` Mach-O that contains only the final linked DWARF for one specific build, matched by UUID.
`dsymutil` collects DWARF fragments from `.o` files and links them against the final executable’s address layout to produce the dSYM.
Symbolication corrects a runtime crash address by subtracting the ASLR slide (runtime load address minus Mach-O link base), then looks up the resulting link address in the dSYM’s DWARF.
UUID is the sole reliable match key; identical source code and filenames do not guarantee a dSYM corresponds to a binary.
Compiler optimizations can inline functions, reorder code, or eliminate variables, so even a correct dSYM may not recover every source-level detail.
Conclusions

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.

Concepts & terms
DWARF
A standardized debugging data format that encodes mappings from machine addresses to source-level constructs — functions, variables, types, files, and line numbers — across multiple sections such as `.debug_info` and `.debug_line`.
Mach-O
Apple/Darwin’s native binary container format. It organizes machine code, data, load commands, and optional debug sections, and carries a UUID that uniquely identifies a build.
dSYM
A directory bundle holding a companion Mach-O of type `MH_DSYM` that contains the final linked DWARF debugging information for a specific binary build, matched by UUID.
ASLR slide
The random offset between a Mach-O’s link-time base address and its runtime load address. Subtracting the slide from a crash address recovers the original link address needed for DWARF lookup.
.debug_line
A DWARF section that stores a line-number program — a compact instruction sequence that, when interpreted, yields the source file, line, and column for each machine address.
UUID (build UUID)
A unique identifier embedded in both a Mach-O binary and its corresponding dSYM. It is the only reliable key for matching a crash report’s image to its debug information.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗