nm#
nm
是 GNU Binutils 工具集中的一个命令,用于列出目标文件(如 .o
文件、共享库 .so
文件或可执行文件)中的符号表信息。它可以帮助开发者查看文件中定义的符号、引用的符号以及符号的类型、地址等信息。
以下是 nm
指令的详细说明:
基本语法#
nm [选项] 目标文件
常用选项#
选项 |
说明 |
---|---|
|
显示所有符号,包括调试符号。 |
|
仅显示外部(全局)符号。 |
|
仅显示未定义的符号。 |
|
显示动态符号表(适用于共享库)。 |
|
将 C++ 符号名称解码为可读格式(demangle)。 |
|
显示符号所在的文件名和行号(如果有调试信息)。 |
|
按符号地址排序(默认按符号名称排序)。 |
|
按符号地址逆序排序。 |
|
显示符号的大小(如果可用)。 |
|
指定输出格式( |
|
显示帮助信息。 |
|
显示版本信息。 |
符号类型#
nm
输出的符号类型由一个字母表示,常见的符号类型包括:
符号 |
说明 |
---|---|
|
绝对符号(Absolute symbol)。 |
|
未初始化的数据段(BSS)中的符号。 |
|
未初始化的公共符号(Common symbol)。 |
|
已初始化的数据段中的符号。 |
|
已初始化的数据段中的全局符号。 |
|
间接引用的符号。 |
|
调试符号。 |
|
只读数据段中的符号。 |
|
未初始化的数据段中的符号。 |
|
文本段(代码段)中的符号(通常是函数)。 |
|
未定义的符号(通常需要从外部链接)。 |
|
弱符号(Weak symbol)。 |
|
未标记的弱符号。 |
|
未知类型的符号。 |
示例#
1. 查看目标文件的符号表#
nm myfile.o
输出示例:
0000000000000000 T main
0000000000000000 D global_var
U printf
T main
:main
是一个在文本段中定义的函数。D global_var
:global_var
是一个在已初始化数据段中定义的全局变量。U printf
:printf
是一个未定义的符号,需要从外部链接。
2. 查看共享库的动态符号表#
nm -D libexample.so
输出示例:
00000000000005a0 T my_function
U malloc
T my_function
:my_function
是在共享库中定义的函数。U malloc
:malloc
是一个未定义的符号,需要从外部链接。
3. 解码 C++ 符号名称#
nm -C myfile.o
输出示例:
0000000000000000 T main
0000000000000000 D global_var
U std::cout
std::cout
是一个解码后的 C++ 符号名称。
4. 显示符号大小#
nm -S myfile.o
输出示例:
0000000000000000 0000000000000014 T main
0000000000000000 0000000000000004 D global_var
0000000000000014
是main
函数的大小(20 字节)。0000000000000004
是global_var
变量的大小(4 字节)。
应用场景#
调试:查看目标文件或共享库中定义的符号,帮助定位问题。
链接问题:检查未定义的符号(
U
),确保所有符号都能正确链接。符号分析:分析目标文件中的符号类型和大小,了解程序结构。
逆向工程:查看二进制文件中的符号信息,辅助逆向分析。
注意事项#
如果目标文件是剥离了符号表的(stripped),
nm
可能无法显示符号信息。对于动态库,使用
-D
选项可以查看动态符号表。对于 C++ 文件,使用
-C
选项可以解码符号名称,使其更易读。
通过 nm
命令,开发者可以深入了解目标文件的符号信息,为调试、链接和分析提供重要支持。