Why can a dSYM exist yet give no file and line numbers, and how do you check it?
Predict first
A program is built with swiftc -g in one step, then dsymutil is run. What does dsymutil report?
// === main.swift ===
struct Account {
var balance = 0
mutating func deposit(_ x: Int) { balance += x }
}
var a = Account(); a.deposit(2); print(a.balance)
- a warning that it is unable to open the object file
- nothing, it works
- a compile error
Mental model. A photocopy of a document whose original was shredded before you copied it: you have the folder, not the pages.
A dSYM is built by dsymutil from the debug map in the linked binary, which points at the original object files. If those objects are gone, the dSYM has nothing to copy. In the check, building in one step (swiftc -g main.swift -o one) deletes the temporary object, and dsymutil warns “unable to open object file”: the bundle exists, but lines are missing. Compiling to an object (-c), linking it, then running dsymutil produces a dSYM that resolves main.swift:3. Xcode keeps the intermediates so it works there; the failure appears in custom scripts and some CI setups, or when intermediates are cleaned before the archive step.
Verify instead of assuming: run dsymutil and read its warnings, compare dwarfdump --uuid of the binary and dSYM, and symbolicate a known address with atos (a successful line lookup is the real test). Add that smoke test to the release job. Also remember Debug builds are not meant to be symbolicated from dSYMs, and bitcode-era advice about downloading dSYMs no longer applies.
The temporary object file no longer exists when dsymutil reads the debug map.
Common traps
- Counting a dSYM file in the archive as success. Check size, warnings and a real lookup.
- Cleaning intermediates before dsymutil. The debug map needs them.
They might follow up with
- Where do the paths come from? The N_OSO entries in the debug map.
- CI check? UUID match plus one atos lookup.
Related questions
- 23.5.1 How do you read a crash report, what do the exception types and Swift runtime messages mean, and how does…
- 23.10.2 How do you symbolicate one crash address by hand: load address, ASLR slide, atos, stripped binaries and dSYMs?
- 23.5.2 How do you build a production diagnostics pipeline: collection, symbolication, grouping, prioritisation…
← How do you symbolicate one crash address by hand: load address, ASLR… How do Logger interpolation formats, privacy options and compile-time… →