You will turn an executable's DWARF records into a dSYM companion with dsymutil, checking the debug map first. The installed command is LLVM 18.1.3 from package llvm-18. Allow about fifteen minutes if you already have a debug build, or longer if you need to arrange a matching build environment.
There is one boundary to establish before running anything: the installed Linux build does not accept an ordinary Linux ELF executable. On this machine, a small ELF test produced The file was not recognized as a valid object file. The workflow below therefore applies to an executable and object files produced for the dSYM workflow, typically on an Apple toolchain. Do not treat a Linux ELF failure as evidence that the DWARF is merely incomplete.
Start with read-only checks. They need no elevated privileges:
$ command -v dsymutil-18
/usr/bin/dsymutil-18
$ dsymutil-18 --version
Ubuntu LLVM version 18.1.3
Optimized build.
$ dpkg-query -W -f='${Package} ${Version}\n' llvm-18
llvm-18 1:18.1.3-1ubuntu1
The version matters because this guide describes the installed LLVM 18 command, not an unspecified copy found elsewhere in PATH. The manual gives the basic shape as dsymutil [options] executable. Its job is to link the DWARF found in the executable's object files, using the symbol information in the executable's symbol table.
Use the exact executable from the matching build. A dSYM is only useful when it corresponds to the binary that produced the crash or diagnostic. Keep the executable, its object files and any relevant symbol maps from the same build; do not substitute a similarly named release.
Ask dsymutil to print the debug map without linking:
$ dsymutil-18 --dump-debug-map /path/to/MyApp
--- !MachODebugMap
Triple: '...'
ObjectPath: /path/to/objects/example.o
...
The YAML is illustrative because paths, triples and the object list depend on your build. The useful checkpoint is that the command exits successfully and lists the object files containing debug information. The option explicitly says that no DWARF link takes place, so this is a safe way to catch a wrong executable or missing object before creating a bundle.
If the command says it cannot parse the debug map, stop there. Check that the input is the intended supported executable and that the build's object files are still available. On the installed Linux command, an ELF executable fails earlier with an invalid-object-file error; changing -o or adding sudo cannot repair that format mismatch.
Run the link with an explicit destination so the generated companion cannot be confused with an older result:
$ dsymutil-18 -o /tmp/MyApp.dSYM /path/to/MyApp
Without -o, dsymutil appends .dSYM to the executable name. With the command above, the expected result is a new dSYM bundle at /tmp/MyApp.dSYM. The command returns status 0 when linking succeeds and status 1 when it does not.
Checkpoint the result before moving it into an archive or crash-reporting system:
$ test -d /tmp/MyApp.dSYM && echo 'dSYM bundle exists'
dSYM bundle exists
$ find /tmp/MyApp.dSYM -maxdepth 3 -type f -print
/tmp/MyApp.dSYM/Contents/Info.plist
/tmp/MyApp.dSYM/Contents/Resources/DWARF/MyApp
The precise file list can vary with the input and toolchain. At minimum, confirm that the destination is a directory and that it contains the generated DWARF payload. Do not assume that a directory with the right suffix is valid merely because another command created it.
Add --verify while creating a separate output when you need the verifier to inspect the link:
$ dsymutil-18 --verify -o /tmp/MyApp.checked.dSYM /path/to/MyApp
$ printf 'exit status: %s\n' "$?"
exit status: 0
Verification runs the DWARF verifier on the linked information. A zero status means this invocation completed successfully. Keep the verifier's result tied to the exact executable and output you intend to publish. If it fails, retain the diagnostic and rebuild or correct the input rather than shipping an unverified bundle.
For a size or object-level investigation, use --statistics:
$ dsymutil-18 --statistics -o /tmp/MyApp.stats.dSYM /path/to/MyApp
Object file: ...
Debug info size: ...
Debug info contributed: ...
The installed manual describes a table sorted with the largest output contributors first. Exact columns and paths are build-dependent. This is a reporting option, not a repair operation.
Use --arch ARM64, repeating the option for each required architecture, when you want to link only named architectures. By default, dsymutil attempts all architectures and reports an error if an architecture cannot be linked. Use the architecture spelling expected by the executable's toolchain; do not copy a name from an unrelated binary.
For a flat output instead of a bundle, use --flat or -f. Unless you also provide -o, the manual says dsymutil appends .dwarf to the executable name. That is a different output shape, so make the choice deliberately when a consuming tool expects a flat file.
Use --update only for an existing dSYM that needs its accelerator tables rebuilt. It updates that file in place. Treat this as a state-changing operation: make a copy first, and keep the original until the updated bundle has passed your checks:
$ cp -a /path/to/MyApp.dSYM /tmp/MyApp.dSYM.before-update
$ dsymutil-18 --update /path/to/MyApp.dSYM
$ printf 'exit status: %s\n' "$?"
exit status: 0
To undo the example, remove the updated bundle and restore the copy only after checking the paths carefully:
$ rm -rf /path/to/MyApp.dSYM
$ mv /tmp/MyApp.dSYM.before-update /path/to/MyApp.dSYM
The removal is irreversible. Do not run it in a script without validating the destination and retaining a recoverable copy.
Use --verbose when the link fails and you need more detail. Use --no-output for a dry link in memory when you want to exercise processing without emitting a result file. It still needs a valid input and object set; it is not an ELF compatibility switch.
Use --oso-prepend-path when the debug map contains object paths that need a directory prepended. If paths were remapped during Clang compilation, --object-prefix-map old=new remaps object paths before processing. These options address path resolution, not missing debug information or an unsupported executable format.
Do not run dsymutil as root by default. Reading a build tree and writing a new output directory are normally ordinary user operations. Elevated privileges may hide ownership or path mistakes and can leave root-owned output behind. Use them only when the build files are intentionally inaccessible and your system policy permits it.
--dump-debug-map completed and its object list was plausible.--verify passed for the output that will be used.