nm
List symbols from object files
TLDR
List global (extern) functions in a file (prefixed with T)
List only undefined symbols in a file
List all symbols, even debugging symbols
Demangle C++ symbols (make them readable)
SYNOPSIS
nm [option(s)] [file(s)]
PARAMETERS
-a, --debug-syms
Display all symbols, including debugger-only symbols, not just external or static symbols.
-C, --demangle
Demangle (decode) low-level symbol names into user-readable names. Useful for C++ or other languages with name mangling.
-D, --dynamic
Display dynamic symbols only, which are used by dynamic linking at runtime. These are usually in the dynamic symbol table.
-g, --extern-only
Display only global (external) symbols, excluding local symbols.
-l, --line-numbers
For each symbol, display the filename and line number where it was defined, if available in the debugging information.
-n, --numeric-sort
Sort symbols by their address (value) numerically instead of alphabetically by name.
-P, --portability
Use the standard output format, which is more easily parseable by scripts and consistent across different systems.
-S, --print-size
For defined symbols, print the symbol's size as well as its value.
-s, --print-armap
When listing symbols from an archive library, print the archive's symbol map.
-t radix, --radix=radix
Specify the radix (base) for printing symbol values (e.g., 'd' for decimal, 'o' for octal, 'x' for hexadecimal).
-u, --undefined-only
Display only undefined symbols, which are referenced by the object file but not defined within it (typically resolved during linking).
--defined-only
Display only symbols that are defined within the object file, excluding undefined ones.
--target=BFDNAME
Specify the object code format if nm cannot determine it automatically (e.g., elf32-i386).
DESCRIPTION
The nm command inspects compiled object files, shared libraries, and static libraries to list the symbols they define or reference. Symbols are essentially names of functions, global variables, and static variables within a program. nm displays the symbol's name, its value (address), and its type, which indicates whether it's a code section (text), data section, uninitialized data (BSS), or undefined (referenced but not defined in the current file).
This utility is invaluable for debugging, reverse engineering, and analyzing software binaries. Developers use it to verify which functions and variables are exported or imported by a library, check for symbol name collisions, or understand the memory layout of an executable. By providing insight into the internal structure of compiled code, nm helps in understanding the linking process and identifying missing or misplaced symbols during software development.
CAVEATS
The exact output format and available options for nm can vary slightly between different Unix-like systems, especially between GNU nm (part of GNU Binutils) and BSD nm. The information displayed by nm is directly dependent on the symbol table present in the object file, which can be influenced by compiler and linker flags (e.g., debug symbols may be stripped to reduce file size).
UNDERSTANDING SYMBOL TYPES
The second field in nm's output is the symbol type, represented by a single character. Uppercase characters indicate global symbols, while lowercase characters indicate local symbols. Common types include:
A: Absolute symbol. Its value is fixed and will not change.
B or b: Uninitialized data (BSS) section symbol.
C: Common symbol. An uninitialized data symbol that may be merged with other common symbols.
D or d: Initialized data section symbol.
N: Debugging symbol.
R or r: Read-only data section symbol.
T or t: Text (code) section symbol.
U: Undefined symbol. Referenced but not defined in this object file, requiring resolution during linking.
V or v: Weak object symbol. Can be overridden by a global symbol definition.
W or w: Weak function symbol. Can be overridden by a global symbol definition.
?: Unknown symbol type, often due to an error.
HISTORY
nm is a long-standing utility in the Unix toolchain, typically part of the GNU Binutils project on Linux systems. Its design and functionality date back to early Unix implementations, providing fundamental capabilities for low-level program analysis. Over time, it has evolved to support new object file formats (like ELF) and architectures, while maintaining its core purpose of listing symbols.