A crash log from App Store Connect or an App Review rejection that cites a crash is useless while it is a wall of hex addresses. Symbolication turns those addresses into function names and line numbers so you can see where the app actually failed. The whole task comes down to matching the right dSYM file to the build that crashed. Here is how to do it in Xcode and from the command line.
Short answer
Symbolication maps the memory addresses in a crash report to readable symbols using the dSYM file that matches the crashed build by its UUID. Per Apple's documentation, Xcode's Organizer symbolicates automatically when it has the matching dSYM, and you can download dSYMs for a build from App Store Connect. To do it by hand, confirm the UUID with dwarfdump, then resolve addresses with atos or run symbolicatecrash against the whole report. The log stays unreadable only when the dSYM is missing or its UUID does not match the build.
What you should know
- The dSYM is the key: it maps addresses to function names, file names, and line numbers for one specific build.
- UUIDs must match: a dSYM only symbolicates the build it was generated for, identified by a build UUID.
- Xcode Organizer is automatic: it symbolicates crashes when the matching dSYM is on your machine or downloaded.
- App Store Connect holds dSYMs: you can download the debug symbols for a build to symbolicate its crashes.
- Bitcode is deprecated: since Xcode 14 you use the dSYM from your own build rather than one Apple recompiled.
What does symbolication actually do?
It replaces raw memory addresses with the names of the functions that ran. A crash report records the call stack as a list of addresses inside the binary, which mean nothing on their own. The dSYM file generated when you built the app holds the debug information that maps each address back to a function, a source file, and a line number. Symbolication is the step that applies that map. Because each build links to its dSYM through a unique build UUID, the dSYM from one build cannot symbolicate a crash from another, which is the single most common reason the process fails. That UUID is not your version or build number; it is a hash baked into the compiled binary, so two builds that share a version string still have different UUIDs and need different dSYMs.
How do you symbolicate in Xcode Organizer?
Open the Organizer and let Xcode do it. In Xcode, choose Window, then Organizer, then the Crashes tab, and select the app and build. Xcode symbolicates the report automatically when it can find the matching dSYM, either from the archive on your machine or from symbols you downloaded. If the build was uploaded from this machine, the archive in Xcode usually already has the dSYM. If it was not, download the debug symbols for that build from App Store Connect first, then reopen the crash so Xcode can apply them.
How do you symbolicate a crash log manually?
Match the UUID, then resolve the addresses. First confirm the dSYM matches the crash report's binary image UUID:
dwarfdump --uuid MyApp.app.dSYM
With a matching dSYM, resolve a single address with atos, using the load address from the crash report:
atos -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp -arch arm64 -l 0x100000000 0x0000000100a1b2c3
Or symbolicate the whole report at once with symbolicatecrash:
export DEVELOPER_DIR="$(xcode-select -p)"
./symbolicatecrash MyApp.crash MyApp.app.dSYM > MyApp-symbolicated.crash
The table summarizes the tools.
| Tool | What it does |
|---|---|
| Xcode Organizer | Symbolicates crashes automatically when the matching dSYM is present |
| dwarfdump --uuid | Prints a dSYM's UUID so you can match it to the crash report |
| atos | Converts a single address to a symbol using the dSYM |
| symbolicatecrash | Symbolicates an entire .crash file against the dSYM |
Why is my crash log still not symbolicated?
Almost always a dSYM problem. The dSYM is missing, or its UUID does not match the build that crashed, so Xcode has nothing to apply. This happens when you build on a different machine, when a clean build replaced the archive, or when a release build stripped symbols without saving the dSYM. Frames from Apple's own frameworks need Apple's symbols, which Xcode adds when the device or symbols are available, so a partially symbolicated log with your code readable and system frames in hex is normal. If even your own frames stay in hex, the dSYM in use is the wrong one, so run dwarfdump on each candidate dSYM until one UUID matches the report. The fix is always to find the dSYM whose UUID matches, which is why archiving every release build and keeping its dSYM is worth the discipline.
What about React Native, Expo, or Flutter crashes?
Native frames symbolicate the same way, but JavaScript and Dart need their own maps. A crash in native code, including the React Native or Flutter engine, resolves with the dSYM as above. An error thrown in your JavaScript needs the source map for that bundle, which a service like Sentry uses to symbolicate JS stack traces, and Hermes bundles need their matching source map uploaded for the same build. A Flutter crash in Dart needs the Dart symbols saved at build time. The principle holds across all of them: the symbol artifact has to match the exact build, so upload or archive it as part of every release rather than after a crash appears.
What to take away
- Symbolication maps a crash report's addresses to function names using the dSYM that matches the build by UUID.
- Let Xcode Organizer do it automatically, and download the dSYM for a build from App Store Connect when it is not on your machine.
- To work by hand, match the UUID with dwarfdump, then resolve addresses with atos or symbolicatecrash.
- Symbolicating a crash is a debugging task, separate from a security review of the build; for the security side, a pre-submission scan such as PTKD.com (https://ptkd.com) reads the compiled IPA against OWASP MASVS, so archive your dSYMs for crashes and scan the binary for the issues a crash log will never show.




