Home / Alt manpages / x86_64-w64-mingw32-nm(1)

  • x86_64-w64-mingw32-nm(1)
  • User command
  • linux

Inspect MinGW Symbols with x86_64-w64-mingw32-nm

You will use x86_64-w64-mingw32-nm to inspect symbols in a Windows PE object file, isolate unresolved references, and produce output that is easier to feed to another tool. The command reads object files and writes a report; it does not link, modify, or execute them.

Allow about fifteen minutes if you already have an object file. You need a shell, the binutils-mingw-w64-x86-64 package, and a readable .o, executable, DLL, or archive. The examples use GNU Binutils 2.41.90.20240122, installed here as package version 2.41.90.20240122-1ubuntu1+11.4.

The x86_64-w64-mingw32ucrt-nm name is an alias for the same canonical manpage on this system. The command name in the steps is therefore the ordinary MinGW-w64 variant.

1. Check the tool before inspecting a file

Confirm which executable your shell will run, then record its version:

$ command -v x86_64-w64-mingw32-nm
/usr/bin/x86_64-w64-mingw32-nm
$ x86_64-w64-mingw32-nm --version
GNU nm (GNU Binutils) 2.41.90.20240122

Checkpoint

The version is part of the evidence when you are comparing symbol reports from different build machines. Short option spellings are useful at a prompt, but the long spellings in these examples make scripts easier to review.

2. List the symbols in one object file

Pass the object file as an argument. Replace the placeholder with a real path:

$ x86_64-w64-mingw32-nm /path/to/module.o
0000000000000000 T function
0000000000000000 D exported_value
0000000000000000 b local_value

The exact addresses and ordering depend on the file. In the default BSD format, each line normally gives a symbol value, a one-character type, and a name. Uppercase generally marks a global or external symbol; lowercase generally marks a local one.

For PE files, a T type identifies code in the text section, D identifies initialised data, and B or b identifies BSS data. U means undefined. The object format can add other types, so treat the character as a classification rather than a complete type system.

If you omit the input argument, nm looks for a file named a.out. That default is easy to trigger accidentally when a variable expansion is empty, so keep the input path visible and check it first:

$ test -r /path/to/module.o && echo 'input is readable'
input is readable

3. Find unresolved symbols before linking

Use --undefined-only, or its short form -u, when the useful question is "what does this object still need?":

$ x86_64-w64-mingw32-nm --undefined-only /path/to/module.o
                 U __imp_SomeImportedFunction

The output varies with the compiler and object. A blank result is meaningful: this particular object has no undefined symbols that nm reports. It does not prove that a complete program will link, because the linker also considers libraries, relocations, machine architecture, and other inputs.

For the opposite view, use --defined-only or -U. This is handy when you want to list what a module supplies without the noise of its imports:

$ x86_64-w64-mingw32-nm --defined-only /path/to/module.o

Checkpoint

Use the two filters as separate questions. Do not interpret a defined symbol as exported from a DLL automatically; visibility and the final link step still matter.

4. Make C++ names readable when needed

Demangling is off by default. Add --demangle or -C for C++ objects:

$ x86_64-w64-mingw32-nm --demangle /path/to/widget.o
0000000000000000 T Widget::name() const

The compiler's mangling style matters, and the optional argument to --demangle selects a style when the default is not suitable. Keep the undecorated report as well if you are matching an exact linker name, because a readable C++ spelling is not necessarily the bytes stored in the object.

Demangling processes names supplied by the input file. The installed manual enables a recursion limit by default, which is a useful safety boundary for unusually complicated names. Do not disable that limit casually: the manual warns that removing it can exhaust the host's stack.

5. Choose output for people or scripts

The default BSD format is compact and familiar. For a stable, whitespace-separated form, select POSIX output:

$ x86_64-w64-mingw32-nm --format=posix /path/to/module.o
.text t 0
function T 0
exported_value D 0

Use --print-file-name or -A when inspecting several files, so each symbol keeps its source file in the report:

$ x86_64-w64-mingw32-nm --print-file-name build/*.o

Use --numeric-sort or -n to order by address, and --no-sort or -p to retain the order encountered in the file. The default is alphabetical sorting by name. Do not build a parser around column positions from the human-oriented default without testing it against the exact Binutils version and object types you accept.

6. Inspect archives without changing them

Static libraries are archives containing object members. Pass the archive directly to list their symbols:

$ x86_64-w64-mingw32-nm /path/to/libwidgets.a

Add --print-armap or -s when you also need the archive index, which maps names to members that define them. This is useful when a linker reports a missing function and you want to check whether the library contains a candidate definition at all.

These commands are read-only. No elevated privileges are needed for an object file in a directory you can read. Do not use sudo to work around a path or ownership mistake without first checking the file and directory permissions. Running as root can hide the real deployment problem and can create root-owned output if you redirect the report to a file.

7. Recover from the common failures

An error such as "No such file" means the path was wrong or the file disappeared. Re-run the readable-file check and quote paths containing spaces:

$ object='/path with spaces/module.o'
$ test -f "$object" && x86_64-w64-mingw32-nm "$object"

If nm says the file format is not recognised, check that you are using the MinGW-w64 target tool and that the file is really an object, executable, DLL, or archive. A Linux-native tool and a Windows-target object can be different targets even when both files end in .o.

If names appear missing, remember that normal output does not include debugger-only symbols. Add --debug-syms or -a for that diagnostic pass. For a dynamic object, --dynamic or -D asks for dynamic symbols instead of the normal table, but it is only meaningful for object types that have such a table.

Done means

  • x86_64-w64-mingw32-nm --version identifies the toolchain you used.
  • You can list a target object and explain its value, type, and name fields.
  • You can separate undefined symbols with --undefined-only.
  • You can choose demangled, POSIX, file-qualified, or address-sorted output for the job.
  • You have not changed the object, archive, linker configuration, or service state.