Home / Alt manpages / llvm-strip-20(1)

  • llvm-strip-20(1)
  • User command
  • linux

Safely Remove Debug Symbols with llvm-strip-20

By the end of this guide you will have a smaller ELF executable with its debugging sections removed, while keeping the original available for recovery. The examples use llvm-strip-20 from Ubuntu's LLVM 20 package, reported locally as version 20.1.8. Allow about ten minutes if the binary is already built, plus time to test it in your own deployment.

Before you start

You need the llvm-20 package, an object file or executable that you are allowed to modify, and enough free space for a copy. You do not need elevated privileges when working in a directory you own. Use sudo only when the input is in a protected location, and prefer copying it to a staging directory first.

Stripping is a destructive file transformation. It can remove information needed by a debugger, profiler or crash-symbolication workflow. Do not run it in place until you have confirmed that the original is backed up and that the stripped file still passes the checks your service needs.

1. Check the installed tool and input

Confirm which executable will run, then inspect the input before changing it. A file marked as an ELF executable is a suitable starting point for the commands below.

$ command -v llvm-strip-20
/usr/bin/llvm-strip-20
$ llvm-strip-20 --version
llvm-strip, compatible with GNU strip
Ubuntu LLVM version 20.1.8
  Optimized build.
$ file /path/to/my-program
/path/to/my-program: ELF 64-bit LSB pie executable, ...

If file reports a different format, check its format-specific support before choosing ELF options. The manual says some ELF options can error or be ignored for other object formats.

2. Make a recoverable copy

Keep the unstripped file in a separate path. This copy is your undo operation: llvm-strip-20 does not provide a reverse command.

$ cp --preserve=all /path/to/my-program /path/to/my-program.unstripped
$ cmp --silent /path/to/my-program /path/to/my-program.unstripped && echo "backup matches"
backup matches

For a release build, store the unstripped file and its build metadata somewhere access-controlled rather than leaving it beside a public download. Debug information can reveal source paths, symbol names and implementation details.

Checkpoint: choose the operation

Use the least aggressive option that meets your distribution requirement. With no other stripping or remove option, this LLVM version enables --strip-all, so an unqualified command is not a safe way to mean "remove only debug information".

  • --strip-debug, also -g, removes debug sections and is the usual choice when you still want ordinary symbols available.
  • --strip-all, also -s, removes all symbols and selected non-allocatable sections from an ELF output. Use it only after testing tools that inspect symbols.
  • --strip-unneeded removes local or undefined symbols that relocations do not require, as well as debug sections.
  • --only-keep-debug creates a debug file containing sections useful for debugging. It is for retaining a symbol file, not for producing a runnable replacement.

3. Write a debug-stripped output file

Use -o to leave the input untouched. It accepts one input file, so this form is also a useful dry boundary around a release step.

$ llvm-strip-20 --strip-debug \
    -o /path/to/my-program.stripped \
    /path/to/my-program
$ file /path/to/my-program.stripped
/path/to/my-program.stripped: ELF 64-bit LSB pie executable, ...
$ readelf -S /path/to/my-program.stripped | grep -E '\.debug_|\.symtab|\.strtab'
  [..] .symtab           SYMTAB          ...
  [..] .strtab           STRTAB          ...

The absence of .debug_* sections confirms that the debug data was removed. Seeing .symtab and .strtab here is expected after --strip-debug; this option is not the same as removing all symbols.

4. Verify behaviour before replacing anything

Run the resulting file and compare its important behaviour with the original. A successful exit from llvm-strip-20 means the transformation completed, not that your application is correct.

$ /path/to/my-program.stripped
$ printf 'program status: %s\n' "$?"
program status: 0
$ sha256sum /path/to/my-program /path/to/my-program.stripped
...  /path/to/my-program
...  /path/to/my-program.stripped

Do not compare hashes as if they should match: stripping changes the bytes. Compare exit status, functional output, required exported symbols and, where relevant, startup and dynamic-linker behaviour. A stripped program can still run while a later diagnostic tool fails because symbol data is gone.

5. Replace the original only after the check

Once the staged file has passed your tests, replace the deployment copy as one deliberate change. This example changes state and may disrupt a service, so stop or drain that service according to its normal deployment procedure first.

$ mv /path/to/my-program.stripped /path/to/my-program
$ /path/to/my-program
$ printf 'deployed stripped binary: %s\n' "$?"
deployed stripped binary: 0
$ printf 'deployed stripped binary: %s\n' "$?"
deployed stripped binary: 0

To undo the replacement, stop the affected process if necessary, then restore the saved copy:

$ cp --preserve=all /path/to/my-program.unstripped /path/to/my-program
$ /path/to/my-program
$ printf 'restored status: %s\n' "$?"
restored status: 0

Common traps

Running llvm-strip-20 /path/to/my-program modifies that file in place and, because no other remove operation was specified, enables --strip-all. Quote paths containing spaces, and do not pass several inputs with -o: the manual rejects multiple inputs with that option.

For archives, the requested operation is applied to each member. Archive headers are deterministic by default, with zero UID, GID and timestamp fields; -U opts into real values. This affects reproducibility, so do not add -U merely to make an archive look more familiar.

Section removal can break consumers. --remove-section accepts repeated section names, while --allow-broken-links permits invalid section references to be left with zeroed sh_link fields. Treat that option as a last resort, not as a repair.

Done means

  • llvm-strip-20 --version reports the expected installed LLVM release.
  • The original binary is preserved outside the deployment path.
  • The selected output has the intended debug and symbol sections.
  • The stripped file runs and passes the application's functional checks.
  • You know how to restore the unstripped copy if diagnostics or runtime behaviour regress.