Getting Started with the nm Command
Introduction
The nm command is a tool that allows you to inspect the symbol table of a binary file on Unix-like systems.
It can help us debug and understand the structure of a binary file, especially when linked with libraries.
If you are a C/C++ developer, you will likely encounter this command when dealing with shared libraries or static libraries.
Basic Usage
To use the nm command, you can simply run it with the path to the binary file you want to inspect. For example, if you have a binary file named my_program, you can run:
nm your_program
The nm command also supports inspecting shared libraries, static libraries, and object files, as follows:
nm your_shared_library.so
nm your_archive.a
nm your_object_file.o
Note that all the files above are object files, which are files generated by the compiler during the compilation process. We also call them ELF (Executable Linkable Format) files on Unix-like systems, and PE-COFF files on Windows.
Options Exaplained
The following is a collection of common options in the nm command.
| Option | Meaning |
|---|---|
| -C | Displays symbols without mangling |
| -D / --dynamic | Displays dynamic symbols only |
| --defined-only | Displays defined symbols only |
| -u / --undefined-only | Displays undefined symbols only |
| -g / --extern-only | Displays external symbols only |
Outputs Explained
The output of the nm command is a list of symbols in the object files, each with its corresponding address and type. The following is a list of these types.
| Type | Definition |
|---|---|
| B/b | The symbol living in .bss segment. |
| D/d | The symbol living in .data segment. |
| T/t | The symbol living in .text segment. |
| U | The undefined symbols. |
| u | The global unique symbol. |
| V/v | The symbol of a weak object. |
| W/w | The symbol of a weak symbol that has not been specifically tagged as a weak object symbol. |
| R/r | The symbol living in .rodata segment. |
Examples
To retrieve common symbols between two ELF files
Given two ELF files elf1 and elf2, we use these following commands to retrieve common symbols.
nm -CD --defined-only elf1 | awk '{for (i=2; i<=NF; i++) printf $i (i==NF?RS:OFS)}' | sort > output1.txt
nm -CD --defined-only elf2 | awk '{for (i=2; i<=NF; i++) printf $i (i==NF?RS:OFS)}' | sort > output2.txt
common_symbols=$(comm -12 output1.txt output2.txt | grep -v 'W ' | grep -v 'V ' | grep -v 'u ')