llvm-dwarfutil-20 produces a separate ELF file with processed DWARF debug information and verifies that output for you. It can also split the debug data into a companion .debug file. The examples use the installed Ubuntu package llvm-20, version 20.1.8, and the executable llvm-dwarfutil-20.
Allow about 15 minutes, plus the time needed to copy a large binary. You need an ELF executable or object file and enough free space for every output. The normal commands do not need elevated privileges when you can read the input and write the destination directory. This tool currently supports ELF, not arbitrary binary formats.
Confirm which executable will run and record its version before you rely on any option behaviour:
$ command -v llvm-dwarfutil-20
/usr/bin/llvm-dwarfutil-20
$ llvm-dwarfutil-20 --version
Ubuntu LLVM version 20.1.8
Optimized build.
Checkpoint: If the command is missing, install the distribution's LLVM 20 package through your normal package-management process. Do not substitute an unversioned LLVM binary in an automated job until you have checked its help output, because this tool is still in active development.
Choose an input and a new output path. Never use the same path for both arguments. Keep the original until you have inspected and tested the result:
$ INPUT='/path/to/program'
$ OUTPUT='/path/to/work/program.processed'
$ test -r "$INPUT" && test ! -e "$OUTPUT"
$ file "$INPUT"
/path/to/program: ELF 64-bit LSB pie executable, x86-64, ...
The final test prevents an accidental overwrite in this example. llvm-dwarfutil-20 writes the named output, so an existing destination is a destructive boundary worth checking explicitly. If you must replace an existing file, make a backup first and keep it until the processed binary has passed your checks. Recovery is then just removing the new file and restoring the backup with your normal file-management procedure.
Do not use sudo merely because the program handles debug data. Use it only when filesystem permissions genuinely require it, and prefer a writable staging directory for the output.
Run the input and output as separate positional arguments:
$ llvm-dwarfutil-20 "$INPUT" "$OUTPUT"
$ test -s "$OUTPUT" && file "$OUTPUT"
/path/to/work/program.processed: ELF 64-bit LSB pie executable, x86-64, ...
With no extra options, the tool makes a semantic copy while its default processing is active. Garbage collection removes debug information associated with discarded sections, and ODR deduplication removes repeated type definitions where the language supports that concept. These defaults can reduce debug data, so never treat the result as a byte-for-byte copy: in a check against /bin/true on this machine, the command returned success and produced an ELF output, but cmp reported differences.
Checkpoint: A zero exit status means the operation completed. It does not prove the application behaves correctly, or that every desired debug entry survived. Exercise the resulting executable in a test environment before replacing a production artefact.
Add --verify when you want the DWARF verifier run against the output:
$ VERIFIED='/path/to/work/program.verified'
$ llvm-dwarfutil-20 --verify "$INPUT" "$VERIFIED"
$ test -s "$VERIFIED" && echo 'verified output was written'
verified output was written
The verifier is a diagnostic gate, not a replacement for testing the program. Keep the output separate from the original so a failed run leaves the source artefact available. If the command exits non-zero, preserve its diagnostic, stop the deployment, and inspect the input format and permissions before trying another option.
Use --separate-debug-file when the deployed file should not carry its complete debug tables:
$ STRIPPED='/path/to/work/program.stripped'
$ llvm-dwarfutil-20 --separate-debug-file "$INPUT" "$STRIPPED"
$ file "$STRIPPED" "$STRIPPED.debug"
/path/to/work/program.stripped: ELF 64-bit LSB pie executable, x86-64, ...
/path/to/work/program.stripped.debug: ELF 64-bit LSB no file type, x86-64, ...
This creates two outputs: the runnable file and a sibling debug file with .debug appended to the output path. The operation is equivalent in intent to keeping debug data, stripping it from the deployed file, and adding a GNU debug link. Ship the companion file to the location your debugger or symbol server expects; do not delete it simply because the stripped executable still runs.
Warning: There is no undo operation inside llvm-dwarfutil-20. To recover, remove or quarantine the generated pair and restore the original from the untouched input or a verified backup. Treat both output paths as a unit when cleaning up.
A single hyphen means standard input or standard output. Useful for a pipeline, but it removes the easy-to-inspect named input and output files:
$ llvm-dwarfutil-20 - - < "$INPUT" > "$OUTPUT"
$ test -s "$OUTPUT" && file "$OUTPUT"
/path/to/work/program.processed: ELF 64-bit LSB pie executable, x86-64, ...
Keep diagnostics separate from the binary stream. Do not redirect standard error into standard output, because that would corrupt the ELF result. The command still returns a non-zero status for an error, so use shell error handling in scripts:
if ! llvm-dwarfutil-20 "$INPUT" "$OUTPUT"; then
printf '%s\n' 'DWARF processing failed; original retained' >&2
exit 1
fi
--no-garbage-collection and --no-odr-deduplication disable the corresponding defaults. Use them when a debugger or downstream tool needs the unpruned or non-deduplicated information, and compare the resulting size and behaviour with a test build. --tombstone=universal is the default marker policy; the other supported values are bfd, maxpc and exec. Do not change that policy just to silence an unexplained diagnostic without understanding the address-range convention in the input.
-j or --num-threads limits simultaneous processing threads. --verbose enables logging but disables multi-thread mode, so do not use it to benchmark parallel performance. On a busy host, set a deliberate thread limit rather than letting the default claim every available core.
llvm-dwarfutil-20 --version reports the expected installed version.--verify was used when a DWARF verification gate was required..debug companion were retained and placed where debugging tools can find them.