GNU nm
1. Overview
nm is a GNU Binutils tool used to display the symbols contained in object files, executables, shared libraries, and static libraries.
Its primary purpose is to inspect symbol tables during compilation and linking. It helps reveal how names from source code appear in compiled binaries and how those names are resolved across translation units and libraries.
Typical symbols shown by nm include:
- functions
- global variables
- undefined external references
- weak symbols
- debugging symbols
- section-related special symbols
In essence, nm is a symbol inspection tool.
—
2. Original design goals
The original design goal of nm is to provide a simple way to examine symbol information in binary files.
It is especially useful for understanding:
- which symbols are defined in a file
- which symbols are referenced but not yet resolved
- whether a symbol is local or global
- what kind of symbol it is
- where the linker may obtain or fail to obtain a symbol
So nm is not mainly for disassembly or source-level debugging. Its role is narrower and more focused: it exposes the symbol-level structure of compiled files.
—
2.1. Basic usage
The basic form is:
nm file
If no file is specified, GNU nm uses a.out by default.
Examples:
nm main.o nm libfoo.a nm a.out nm libfoo.so
Default output usually contains three pieces of information for each symbol:
- symbol value or address
- symbol type
- symbol name
Example:
0000000000001139 T main
U printf
0000000000004010 D global_var
0000000000004020 B uninitialized_var
Interpretation:
mainis defined in the text sectionprintfis undefined here and must be resolved elsewhereglobal_varis initialized datauninitialized_varis in the BSS area
—
2.2. Core symbol type letters
The most important symbol letters are:
T/t- text section, usually code
D/d- initialized data
B/b- uninitialized or zero-initialized data
R/r- read-only data
U- undefined symbol
W/w- weak symbol
V/v- weak object
A- absolute symbol
C/c- common symbol
N- debugging symbol
I- indirect reference
?- unknown or format-specific
In general:
- uppercase letters usually indicate global or external symbols
- lowercase letters usually indicate local symbols
The most important letters to remember for everyday usage are:
TDBRUW
—
2.3. Most commonly used options
2.3.1. -C / --demangle
Demangles C++ symbol names into readable function and class names.
nm -C libfoo.a
Very common in C++ projects.
—
2.3.2. -g / --extern-only
Shows only external or global symbols.
nm -g main.o
Useful when local symbols are irrelevant and only exported/imported symbols matter.
—
2.3.3. -u / --undefined-only
Shows only undefined symbols.
nm -u main.o
This is especially useful when diagnosing linker errors.
—
2.3.4. -U / --defined-only
Shows only defined symbols.
nm -U libfoo.a
Useful when checking what a file or library actually provides.
—
2.3.5. -D / --dynamic
Shows dynamic symbols rather than the normal symbol table.
nm -D libfoo.so
Important for shared libraries and dynamically linked executables.
—
2.3.6. -n / --numeric-sort
Sorts symbols by numeric address rather than by name.
nm -n a.out
Useful for understanding layout in address order.
—
2.3.7. -A / -o / --print-file-name
Prints the file name before each symbol.
nm -A *.o
Useful when inspecting many files at once.
—
2.3.8. -l / --line-numbers
Tries to display source file and line number information.
nm -l a.out
Works best when debug information is present.
—
2.3.9. -S / --print-size
Prints symbol size in addition to value.
nm -S a.out
Useful for code size or object size inspection.
—
2.3.10. --size-sort
Sorts symbols by size.
nm --size-sort -S a.out
Useful for finding large functions or objects.
—
2.3.11. -a / --debug-syms
Includes debugger-only symbols.
nm -a a.out
Less common in everyday work, but useful for full inspection.
—
2.4. Common usage scenarios
2.4.1. Diagnosing linker errors
A common linker error is:
undefined reference to `foo`
To inspect unresolved references in an object file:
nm -u main.o
To search for the file or library that defines foo:
nm libfoo.a | grep ' foo$'
This is one of the classic uses of nm.
—
2.4.2. Inspecting what a library exports
For a static library:
nm -g libmylib.a
For a shared library:
nm -D -g libmylib.so
This helps identify the API visible to other code.
—
2.4.3. Understanding object file contents
To inspect what a single object file contains:
nm file.o
This reveals:
- which functions are defined
- which global variables are defined
- which symbols are still unresolved
- what section each symbol belongs to
This makes nm very useful for learning compilation and linking.
—
2.4.4. Inspecting C++ binaries
C++ binaries often contain mangled names. The following form makes them readable:
nm -C a.out
This is useful for examining namespaces, overloaded functions, class methods, and template instantiations.
—
2.4.5. Checking weak vs strong symbols
When symbol resolution behaves unexpectedly, nm can reveal whether a symbol is weak or strong.
Weak symbols often appear as:
WwVv
This is useful in runtime libraries, low-level systems code, and large C/C++ projects.
—
2.4.6. Inspecting static archive indexes
For static libraries, the archive symbol index can be displayed with:
nm -s libfoo.a
This is helpful when studying how symbol lookup works inside .a archives.
—
2.5. Advanced usages
2.5.1. Dynamic symbol table inspection
For shared libraries or dynamically linked executables:
nm -D libfoo.so
This focuses on the dynamic symbol table, which is especially relevant for runtime linking.
—
2.5.2. Size analysis
To inspect symbols together with size information:
nm -S --size-sort a.out
This is useful for:
- code size optimization
- embedded systems work
- tracking binary growth
- locating unusually large functions or objects
—
2.5.3. Source line mapping
When debug information is available:
nm -l a.out nm -l --inlines a.out
This can associate symbols with source file and line information.
—
2.5.4. Working with plugin-based or LTO objects
GNU nm supports plugins and can be used with LTO-related objects.
Example:
nm --plugin /path/to/plugin file.o
This is relevant in more advanced toolchain setups where ordinary nm output may not fully expose LTO-generated symbol information.
—
2.5.5. Choosing output formats
GNU nm supports different output styles, including:
bsdsysvposixjust-symbols
Examples:
nm -f sysv a.out nm -P a.out nm -j a.out
These are useful for:
- scripting
- portability
- machine-friendly output
- compatibility with other tools
—
2.5.6. Inspecting many files at once
When analyzing many object files or archive members:
nm -A *.o nm -A libfoo.a
This makes it easier to determine which file contributes which symbol.
—
2.5.7. Showing synthetic or special symbols
GNU nm can also show linker-generated or target-specific symbols:
nm --synthetic a.out nm --special-syms a.out
This is mainly useful in advanced ABI, linker, or target-format investigation.
—
2.6. Mental model
nm can be understood as answering four main questions:
What symbols does this file define?
nm -U file.o
What symbols does this file still need?
nm -u file.o
- What kinds of symbols are they?
This is determined by the symbol type letters such as
T,D,B,R,U, andW. Are these ordinary symbols or dynamic-linking symbols?
nm file nm -D file
This is the core conceptual model of nm.
—
2.7. Compact cheat sheet
nm file.o # basic symbol table nm -C file.o # demangle C++ names nm -u file.o # undefined symbols only nm -U file.o # defined symbols only nm -g file.o # external/global symbols only nm -D libfoo.so # dynamic symbols nm -n a.out # sort by address nm -S --size-sort a.out # show sizes and sort by size nm -A *.o # print file name with each symbol nm -l a.out # show line number information nm -s libfoo.a # show archive index
—
2.8. Final summary
nm is a focused binary analysis tool for inspecting symbol tables.
Its main strengths are:
- diagnosing linker problems
- checking undefined references
- seeing what a library exports
- understanding symbol layout in compiled files
- reading mangled C++ names in human-readable form
Compared with tools like objdump or readelf, nm is simpler and narrower in scope. Its core task is to expose symbol information clearly and directly.