>_cmd.script

nm

List symbols from object files and executables

Development

By CMD Script Team · 4 min read · Last updated

SYNTAX
nm [OPTIONS] FILE...

Options

Command options and flags
FlagDescription
-DDisplay dynamic symbols instead of normal symbols; needed for stripped shared libraries and dynamic executables
-uShow only undefined symbols — ones referenced but not defined in this file
-CDemangle C++ symbol names into human-readable form (e.g. foo::bar(int) instead of _ZN3foo3barEi)
-gShow only external (global) symbols, hiding local/static ones
--size-sortSort output by symbol size instead of by name or address
-APrefix each line with the filename, useful when passing multiple files at once

Distribution compatibility

  • Ubuntu
  • Debian
  • Fedora
  • Arch
  • macOS (via Xcode Command Line Tools, part of llvm binutils)

What it does

nm lists the symbol table of an object file, static library, or executable — every function and global/static variable it defines, references, or exports, along with each symbol's type and (when available) address. It's the standard way to inspect exactly what names a compiled file provides and what it still needs, which makes it the primary tool for diagnosing linker errors like "undefined reference to foo".

Beginner examples

  • nm myfile.o — list every symbol defined or referenced in an object file
  • nm -u myfile.o — show only symbols this file references but doesn't define (undefined symbols)
  • nm -C myprogram — demangle C++ symbol names into readable form
  • nm -D libexample.so — list dynamic symbols exported by a shared library
  • nm -g myfile.o — show only external/global symbols, hiding local statics
nm -u myfile.o

Advanced examples

  • Track down which library defines a missing symbol during a link failure: nm -D /usr/lib/x86_64-linux-gnu/*.so 2>/dev/null | grep my_missing_symbol
  • Compare defined vs. undefined symbols across a set of object files before linking: for f in *.o; do echo "== $f =="; nm -u "$f"; done
  • Sort symbols by size to find unusually large functions or data objects: nm --size-sort -C myprogram
  • Confirm a shared library actually exports the symbols a program expects at runtime: nm -D --defined-only libexample.so
nm -C -u myapp.o | grep " U "

Common mistakes

  • Running plain nm on a shared library and getting no output, forgetting that release/shared libraries are often built without a regular symbol table — use nm -D for the dynamic symbol table instead.
  • Trying to match C++ symbol names by eye without -C, and being confused by mangled names like _ZN3Foo3barEi — always demangle with -C when working with C++ binaries.
  • Assuming a symbol marked undefined (U) is a bug — it's often expected and simply means the definition lives in another translation unit or library that will be linked in later.
  • Forgetting that nm on a fully stripped binary (see strip) will show little or no symbol information, since stripping removes exactly the data nm reads.

Tips

  • When chasing an "undefined reference" linker error, run nm -u on the failing object file to get the exact symbol name the linker is looking for, then grep for that name across candidate libraries.
  • Use -C by default when working with C++ code — mangled names are nearly unreadable without it.
  • nm -D is essential for shared libraries (.so files), which typically only carry a dynamic symbol table, not a full one.
  • Combine nm with grep and shell loops to search across many object files or libraries at once when hunting a specific symbol.

Best practices

  • Use nm -u as a first diagnostic step for any "undefined reference" linker error before guessing at missing -l flags or include paths.
  • Always demangle C++ output with -C to avoid misreading mangled names as unrelated symbols.
  • Check nm -D --defined-only on a shared library to confirm its public API before relying on it, especially for libraries without clear documentation.
  • Keep an unstripped build artifact around during development so nm (and other debugging tools) can still provide useful symbol information; strip only final release builds.

Try it yourself

A simulated shell with a sample home directory — experiment freely, nothing leaves your browser. Type help to list supported commands.

Real-world use cases

  • Diagnosing a linker error by confirming exactly which object file references an undefined symbol and searching libraries for its definition.
  • Verifying a shared library actually exports the functions an application expects to dynamically link against.
  • Auditing a compiled binary to confirm no unexpected internal functions were accidentally exported as global symbols.
  • Investigating ABI compatibility issues between library versions by comparing their exported symbol lists.

Common interview questions

  • What does an undefined symbol (U) in nm output mean? It means the object file references that symbol but doesn't define it itself — the linker must find its definition in another object file or library to successfully link.
  • Why would nm show no output on a shared library? Many shared libraries are built without a regular symbol table; use nm -D to read the dynamic symbol table instead, which is what's actually used for runtime linking.
  • Why are C++ symbol names in nm output often unreadable? Because C++ compilers mangle names to encode namespace, class, and argument type information for overload resolution; nm -C demangles them back into human-readable form.
  • How would you debug an 'undefined reference to X' linker error using nm? Run nm -u on the object file that fails to link to confirm the exact expected symbol name, then run nm (or nm -D for shared libs) on candidate libraries to find which one, if any, actually defines it.

Frequently Asked Questions

What does an undefined symbol in nm output mean?

A symbol shown as undefined (typically marked U) is referenced in that object file but not defined there — the linker expects to find its definition in another object file or library. Running nm -u is a quick way to see exactly what a .o file expects to be supplied at link time.

How do I use nm to debug an 'undefined reference' linker error?

Run nm -u on the object file that's failing to link to confirm the exact symbol name it expects, then run nm on candidate libraries (with -D for shared libraries) to check whether any of them actually define that symbol, and under what exact name — mismatches are often due to name mangling or missing extern "C".

Why do C++ symbol names look garbled in nm output?

C++ compilers mangle function and method names to encode their namespace, class, argument types, and overload information into a unique linker symbol. Use nm -C to demangle these back into readable names like MyClass::doWork(int).

What's the difference between plain nm and nm -D?

Plain nm reads the regular symbol table, which is often stripped from shared libraries and release executables. nm -D reads the dynamic symbol table instead, which is what's actually used for runtime dynamic linking and remains present even when the regular symbol table is stripped.

Cheat sheet

Download a quick-reference cheat sheet for nm.