Home / Alt manpages / x86_64-w64-mingw32-c-filt(1)

  • x86_64-w64-mingw32-c-filt(1)
  • User command
  • linux

Demangle MinGW C++ Symbols with x86_64-w64-mingw32-c++filt

You will turn an encoded MinGW C++ symbol such as _Z3fooi into readable text such as foo(int). The same command can filter a symbol list or assembler-like text through standard input without changing the source file.

Allow about ten minutes for a first pass. You need a Linux shell and the binutils-mingw-w64-x86-64 package. These examples use GNU Binutils 2.41.90.20240122, installed as package version 2.41.90.20240122-1ubuntu1+11.4. The UCRT alias is installed alongside the primary command and has the same local manpage behaviour.

1. Check the installed command

Start by confirming which executable your shell will run and recording its version. This is a read-only check and does not need elevated privileges.

$ command -v x86_64-w64-mingw32-c++filt
/usr/bin/x86_64-w64-mingw32-c++filt
$ x86_64-w64-mingw32-c++filt --version
GNU c++filt (GNU Binutils) 2.41.90.20240122
$ dpkg-query -W -f='${Package} ${Version}\n' binutils-mingw-w64-x86-64
binutils-mingw-w64-x86-64 2.41.90.20240122-1ubuntu1+11.4

Use the exact target-prefixed command when examining MinGW output. Do not silently substitute an unprefixed c++filt from a different toolchain: its demangler may have different defaults or formats.

Checkpoint

You know the executable and version before comparing output from a build machine or a bug report.

2. Demangle one symbol

Pass a bare mangled name as a command-line argument. The -n option means do not strip a leading underscore; it is the installed command's default and makes the input handling explicit.

$ x86_64-w64-mingw32-c++filt -n _Z3fooi
foo(int)
$ x86_64-w64-mingw32-c++filt -n _Z1fv
f()

Command-line arguments are treated as complete names. Punctuation attached to a name makes that argument invalid, so this is a common trap:

$ x86_64-w64-mingw32-c++filt -n '_Z1fv,'
_Z1fv,

The comma is preserved because the whole argument is not a valid mangled symbol. When you have surrounding punctuation, use standard input instead.

3. Filter a symbol list or source text

With no symbol arguments, c++filt reads standard input and writes the transformed text to standard output. It recognises candidate words inside the input, so punctuation around them can remain in place.

$ printf '%s\n' '_Z1fv,' | x86_64-w64-mingw32-c++filt -n
f(),
$ printf '%s\n' '.type _Z1fv, @function' | x86_64-w64-mingw32-c++filt -n
.type f(), @function

For a file, write to a new destination first:

$ x86_64-w64-mingw32-c++filt -n < symbols.s > symbols-demangled.s
$ cmp --silent symbols.s symbols-demangled.s; printf 'cmp status: %s\n' "$?"
cmp status: 1

A status of 1 here is expected when the output differs. The input remains untouched. If you later decide to replace the original, keep a backup and inspect the new file first; shell redirection with > truncates an existing destination before the command starts.

Checkpoint

Use an argument for one bare symbol, and standard input when the symbol is embedded in assembler text or followed by punctuation.

4. Control the displayed name

The normal output includes function parameter types. Add -p when you need shorter names for a report or a quick symbol comparison.

$ x86_64-w64-mingw32-c++filt -n _Z3fooi
foo(int)
$ x86_64-w64-mingw32-c++filt -n -p _Z3fooi
foo

Use -t carefully. It also attempts to demangle type encodings, which is disabled by default because an ordinary short name can be mistaken for a type. For implementation details, -i requests less verbose output where the demangler has such details to show.

The -s option selects a mangling format. The default is automatic selection; the installed help lists auto, gnu-v3, java, gnat, dlang and rust, among others supported by this build. Check the local help rather than copying a format name from a different Binutils release:

$ x86_64-w64-mingw32-c++filt --help | sed -n '1,14p'
Usage: x86_64-w64-mingw32-c++filt [options] [mangled names]
Options are:
  [-_|--strip-underscore]     Ignore first leading underscore
  [-n|--no-strip-underscore]  Do not ignore a leading underscore (default)
  [-p|--no-params]            Do not display function arguments
  [-i|--no-verbose]           Do not show implementation details (if any)

5. Keep the recursion guard enabled

Binutils mangling can contain deeply nested structures. The installed manpage says the default recursion limit is 2048 levels. Keep that protection enabled with -R when processing untrusted symbol text, or simply omit both recursion options.

Security boundary

-r and --no-recurse-limit disable the guard. The manual warns that a sufficiently complicated name can exhaust stack space and crash the process. Only use that switch for a controlled input when the limit itself blocks a known, legitimate symbol, and run it in an isolated worker if the input is not fully trusted. This command needs no sudo.

$ x86_64-w64-mingw32-c++filt -R -n _Z3fooi
foo(int)
$ x86_64-w64-mingw32-c++filt -r -n _Z3fooi
foo(int)

Those two outputs match for this small symbol. That does not make disabling the limit safe for arbitrary input.

6. Diagnose an unchanged name

If the output is identical to the input, the word may not be a supported mangled name, the wrong format may be selected, or punctuation may have been included in a command-line argument. Compare these cases:

$ x86_64-w64-mingw32-c++filt -n not_a_mangled_symbol
not_a_mangled_symbol
$ x86_64-w64-mingw32-c++filt -s gnu-v3 -n _Z3fooi
foo(int)

An unchanged name is not an error by itself: the program echoes names it cannot demangle. Check the input source, target toolchain and exact version before trying more flags. If an option is rejected, run --help on that installed binary; the local manpage and a newer upstream manual may describe different format lists.

Done means

  • You verified the target-prefixed executable and installed Binutils version.
  • A bare MinGW symbol demangles to the expected readable name.
  • You use standard input when punctuation or surrounding assembler text matters.
  • You know that -p removes displayed parameter types and that -t broadens type detection.
  • The recursion limit remains enabled for untrusted input.
  • Your source file and previous output remain available after any redirected conversion.