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

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

Read C++ Symbols Clearly with llvm-cxxfilt-20

You will turn LLVM and C++ mangled symbols into readable names, either as individual arguments or inside a larger text stream. You will also see how to remove parameter details, demangle type names, preserve separators, and check failures in a script. Allow about ten minutes. The examples use llvm-cxxfilt-20 from the Ubuntu llvm-20 package; the executable installed on this machine reports LLVM 20.1.8.

This is a read-only diagnostic tool. It does not edit object files, binaries or symbol tables, and it normally needs no elevated privileges.

1. Confirm the installed command

Check that the versioned executable is on your path and record the version before relying on its output in a script:

$ command -v llvm-cxxfilt-20
/usr/bin/llvm-cxxfilt-20
$ llvm-cxxfilt-20 --version
llvm-cxxfilt-20
Ubuntu LLVM version 20.1.8
  Optimized build.

Use the versioned name in examples when several LLVM releases are installed. An unversioned llvm-cxxfilt may select a different release, with different support or output details.

Checkpoint

command -v should find the executable and --version should show the release you intend to inspect.

2. Demangle names passed as arguments

Pass one or more mangled names after the command. LLVM prints one result per argument. A name that cannot be demangled is printed unchanged, which lets a mixed list continue without losing ordinary labels:

$ llvm-cxxfilt-20 _Z3foov _Z3bari not_mangled
foo()
bar(int)
not_mangled

The input names in this example use the GNU and Itanium-style encoding expected by the default auto format. The readable result is useful when an object-file tool, linker diagnostic or crash report gives you a symbol such as _Z3bari instead of its source-level spelling.

Do not treat the output as a compiler declaration in every case. It is a demangled description of the symbol, and a symbol can still be missing, duplicated or associated with a different binary build.

3. Demangle a symbol stream without losing separators

With no names on the command line, the program reads standard input. It splits each line around characters that cannot belong to an Itanium mangled name, demangles the candidate names, and copies those separators back to the output:

$ printf '%s\n' '| _Z3foov *** _Z3bari *** not_mangled |' | llvm-cxxfilt-20
| foo() *** bar(int) *** not_mangled |

This makes it suitable for a pipeline that keeps addresses, punctuation or log prefixes around symbols. The accepted name characters include letters, digits, full stops, dollar signs and underscores. Keep that boundary rule in mind when feeding it decorated output from another tool: punctuation is treated as a separator, not as part of the candidate name.

Checkpoint

Compare the separators in your input and output. If the surrounding text is unchanged and only mangled names have been replaced, the stream is ready for the next diagnostic step.

4. Choose how much detail to show

Function parameters and return types are included by default. Use --no-params, or its short form -p, when the function name matters more than its signature:

$ llvm-cxxfilt-20 --no-params _Z3bari
bar

Use --types or -t when the input may contain encoded type names as well as symbols. For example, the single-letter encoding i is the C++ int type:

$ printf '%s\n' i | llvm-cxxfilt-20 --types
int

Without --types, do not assume every type encoding will be interpreted as a type. Add the option at the point where the input format requires it, rather than enabling it globally without checking the results.

5. Handle underscores and quoted output deliberately

On this Linux host, the default is not to strip a leading underscore. --strip-underscore, or -_, removes one leading underscore before demangling. This is useful when a producer adds a platform-specific decoration, but it changes the input before the normal demangler sees it:

$ llvm-cxxfilt-20 --strip-underscore __Z3foov
foo()
$ llvm-cxxfilt-20 --no-strip-underscore __Z3foov
foo()

The second output is also foo() for this particular input because the remaining spelling still resolves after one underscore is retained. Do not infer the option's effect from a convenient example alone. Test it with the symbols emitted by your object format, and use --no-strip-underscore when retaining the leading character is part of the diagnosis. LLVM documents underscore stripping as enabled by default on Mach-O hosts, so portability matters if the same script runs on macOS.

--quote adds plain double quotes around a demangled name unless it is already quoted:

$ llvm-cxxfilt-20 --quote _Z3foov
"foo()"

Quoting can make a result easier to distinguish from adjacent log text. If another program expects the bare demangled name, leave this option off.

6. Use the format option and response files carefully

--format=auto is the documented default. The installed LLVM 20 help reports that the format selector is currently ignored because only gnu is supported, but the manpage identifies auto and gnu as the valid values. Keep an explicit format only when it documents an interface assumption:

$ llvm-cxxfilt-20 --format=gnu _Z3foov
foo()

This option does not make LLVM 20 understand an unrelated mangling scheme. If the symbols are from another ABI, confirm that the tool is appropriate before building a parser around its output.

For a long option list, @FILE tells the command to read command-line options from a response file. Treat that file as executable input to your workflow: review its contents, use a controlled path, and do not consume an untrusted file merely because it has a familiar name. The normal symbol arguments can still be supplied after the response-file argument.

7. Check failures in a script

The command returns status 0 unless it encounters a usage error. Capture the status immediately if a pipeline must distinguish a bad invocation from a successful pass-through:

if output=$(llvm-cxxfilt-20 --no-params "$symbol"); then
    printf '%s\n' "$output"
else
    status=$?
    printf 'llvm-cxxfilt-20 failed with status %s\n' "$status" &> /dev/stderr
    exit "$status"
fi

Do not use a non-demangled result as proof that the command failed. The documented behaviour is to print an unrecognised name unchanged. A usage error, such as an unknown option, is the condition that should trigger the non-zero status path.

Shell redirection can hide where output went. For a one-off inspection, leave standard output on the terminal. For a saved report, write to a new file and inspect it before replacing an existing report:

$ llvm-cxxfilt-20 < symbols.txt > symbols-readable.txt
$ test -s symbols-readable.txt && echo 'report written'
report written

If the new report is wrong, discard symbols-readable.txt and keep symbols.txt. The original input is never changed by this command. Do not use sudo unless a separate file-permission problem genuinely requires it.

Done means

  • llvm-cxxfilt-20 --version identifies the expected LLVM 20.1.8 executable.
  • Individual symbols and mixed stdin streams produce readable output while preserving useful separators.
  • --no-params, --types, quoting and underscore handling are selected for a stated diagnostic need.
  • Unrecognised names are treated as pass-through data, while usage errors are checked through the exit status.
  • Reports are written to new paths, and the original symbol input remains untouched.