nm - Symbol Table Tool Reference (Part 2 of 4)

1. Introduction to nm

1.1 What is nm?

The nm command lists symbols from object files, executables, and libraries. It's an essential tool for developers and system administrators who need to:

Part of: GNU Binutils package
Primary Purpose: Display symbol information from binary files

1.2 When to Use nm

2. Basic Syntax and Options

2.1 Command Syntax

nm [OPTIONS] [FILE...]

2.2 Common Options

Option Description
-A Prefix each line with filename
-a Display all symbols, including debugger-only symbols
-B BSD format output (default on BSD systems)
-C or --demangle Demangle C++ symbol names to human-readable form
-D or --dynamic Display dynamic symbols only (from .dynsym)
-f format Specify output format (bsd, sysv, posix)
-g or --extern-only Display only external (global) symbols
-l or --line-numbers Show filename and line number (if debug info available)
-n or -v Sort numerically by address
-p Don't sort; display in symbol table order
-P or --portability Use POSIX.2 standard output format
-r or --reverse-sort Reverse sort order
-S or --print-size Print size of defined symbols
-s Print archive index
-t radix Print addresses in specified radix (d, o, x)
-u or --undefined-only Display only undefined symbols
--size-sort Sort symbols by size
--special-syms Include special symbols

3. Understanding Symbol Types

3.1 Symbol Type Codes

nm displays a letter code for each symbol. Uppercase = global/external, lowercase = local:

Code Description Details
A Absolute Value won't change with relocation
B / b BSS segment Uninitialized data (zero-initialized)
C Common Uninitialized data (tentative)
D / d Data segment Initialized data section
G / g Small data Initialized small objects (some architectures)
I Indirect Indirect reference to another symbol
N Debugging Debugging symbol
R / r Read-only Read-only data section (.rodata)
S / s Small BSS Uninitialized small objects (some architectures)
T / t Text segment Code section (functions)
U Undefined Referenced but not defined (needs linking)
V / v Weak object Weak symbol that can be overridden
W / w Weak symbol Can be overridden by strong symbol
- Stabs Debugging symbol (stabs format)
? Unknown Unknown symbol type
Key Distinction:

4. Basic Usage Examples

4.1 Examining Binaries

# List all symbols in a binary
nm /bin/ls

# List symbols with addresses in hex
nm /bin/bash

# List symbols in a library
nm /usr/lib/x86_64-linux-gnu/libc.so.6

# List symbols in object file
nm program.o

4.2 Output Format

Standard nm output format:

0000000000001234 T main
0000000000002345 t helper_function
                 U printf
0000000000004000 D global_variable
0000000000005000 b static_variable

Format: [ADDRESS] [TYPE] [NAME]

5. Finding and Filtering Symbols

5.1 Undefined Symbols

# Show only undefined symbols (dependencies)
nm -u /bin/ls

# What functions does this program need?
nm -u myprogram

# Undefined symbols with demangling
nm -Cu myprogram
Use Case: Finding undefined symbols is crucial when debugging linking errors. These are functions/variables your program needs but doesn't define internally.

5.2 Global (External) Symbols

# Show only external/global symbols
nm -g /bin/ls

# What functions does this library export?
nm -gD /usr/lib/libssl.so

5.3 Dynamic Symbols

# Show dynamic symbols only
nm -D /usr/lib/libc.so.6

# What functions are exported by this shared library?
nm -D --defined-only /usr/lib/libpthread.so.0

5.4 Symbol Search

# Find specific symbol
nm /bin/bash | grep "main"

# Case-insensitive search
nm /bin/bash | grep -i "read"

# Find all functions starting with "str"
nm /usr/lib/libc.so.6 | grep " T str"

# Count number of functions
nm -D /usr/lib/libc.so.6 | grep " T " | wc -l

6. Advanced Usage

6.1 C++ Symbol Demangling

# Without demangling (mangled names)
nm mycppprogram
# Output: _Z4funcRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

# With demangling (readable names)
nm -C mycppprogram
# Output: func(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
Always use -C for C++ binaries! It makes the output human-readable by converting mangled names back to their original C++ form.

6.2 Size Analysis

# Show symbol sizes
nm -S myprogram

# Sort by size (find largest symbols)
nm --size-sort -S myprogram

# Sort by size in reverse (largest first)
nm --size-sort -r -S myprogram

# Find bloated functions
nm --size-sort -S mybinary | tail -20

6.3 Address and Line Numbers

# Show line numbers (requires debug info)
nm -l myprogram

# Sort by address
nm -n myprogram

# Show addresses in decimal
nm -t d myprogram

# Show addresses in octal
nm -t o myprogram

6.4 Multiple Files

# Process multiple files
nm file1.o file2.o file3.o

# Prefix output with filename
nm -A *.o

# Find symbol across multiple object files
nm -A *.o | grep "my_function"

7. Practical Debugging Scenarios

7.1 Resolving Link Errors

# Problem: undefined reference to 'foo'
# Solution: Find which library has it

# Check if symbol is defined in your objects
nm -g *.o | grep " T foo"

# Search system libraries
nm -D /usr/lib/x86_64-linux-gnu/*.so | grep " T foo"

# Or use a script
for lib in /usr/lib/x86_64-linux-gnu/*.so*; do
    if nm -D "$lib" 2>/dev/null | grep -q " T foo"; then
        echo "Found in: $lib"
    fi
done

7.2 Finding Duplicate Symbols

# Find duplicate global symbols across object files
nm -g *.o | grep " T " | awk '{print $3}' | sort | uniq -d

# More detailed duplicate search
for symbol in $(nm -g *.o | grep " T " | awk '{print $3}' | sort | uniq -d); do
    echo "Duplicate: $symbol"
    nm -A *.o | grep " T $symbol"
done

7.3 Checking Library Compatibility

# Compare symbols between two library versions
nm -D libfoo.so.1 | sort > v1.txt
nm -D libfoo.so.2 | sort > v2.txt
diff v1.txt v2.txt

# Find removed symbols (potential compatibility issues)
diff v1.txt v2.txt | grep "^<"

# Find added symbols
diff v1.txt v2.txt | grep "^>"

7.4 Analyzing Binary Stripping

# Check if binary has symbols
nm myprogram

# If stripped, you'll get:
# nm: myprogram: no symbols

# Verify with file command
file myprogram

# Compare before and after stripping
nm myprogram > before.txt
strip myprogram
nm myprogram > after.txt 2>&1
diff before.txt after.txt

8. Integration with Other Tools

8.1 nm + ldd (Finding Dependencies)

# List shared library dependencies
ldd /bin/ls

# Check what symbols are used from a specific library
nm -u /bin/ls | grep "printf"
nm -D /usr/lib/libc.so.6 | grep " T printf"

8.2 nm + objdump

# nm shows symbols, objdump shows disassembly
nm -n myprogram          # List symbols by address
objdump -d myprogram     # Show disassembly

# Find function, then disassemble it
nm myprogram | grep "my_function"
objdump -d myprogram | grep -A 20 "my_function"

8.3 nm + readelf

# nm shows symbol names
nm -D mylib.so

# readelf shows detailed symbol table
readelf -s mylib.so

# Compare output
nm -D mylib.so > nm_output.txt
readelf -s mylib.so > readelf_output.txt

9. Scripting with nm

9.1 Parse nm Output

#!/bin/bash
# Count functions, variables, and undefined symbols

echo "Functions: $(nm myprogram | grep " T " | wc -l)"
echo "Variables: $(nm myprogram | grep " [DdBb] " | wc -l)"
echo "Undefined: $(nm -u myprogram | wc -l)"

9.2 Find Large Symbols

#!/bin/bash
# Report symbols larger than 1KB

nm --size-sort -S myprogram | awk '$2 > 1024 {print $0}'

10. Next Steps

Continue to:

← Back to NetworkManager Index ↑ Back to EXPANDED