Linux nm
命令是一种工具,用于检查二进制文件(特别是编译后的目标文件.o
、库文件.a
、.so
以及可执行文件)中的符号。它列出了文件中的所有符号,包括变量、函数、类成员等,以及它们的地址和类型。这对于开发者在调试和分析程序时是非常有用的。
Linux nm命令介绍
nm
(stands for "name list")会列出目标文件的符号表,它包括符号的名称、符号类型以及符号的值(地址)。当编译程序时,编译器会生成这些符号信息,这些信息对于了解程序的结构和解决符号冲突非常重要。
Linux nm命令适用的Linux版本
nm
命令在几乎所有的Linux发行版中都是可用的,因为它是binutils
软件包的一部分,这是大多数Linux系统中的标准集合。然而,不同的发行版可能会有不同的安装方法。
- 对于基于Debian的系统,如Ubuntu:
[linux@bashcommandnotfound.cn ~]$ sudo apt-get install binutils ```
- 对于基于RPM的系统,如Fedora:
[linux@bashcommandnotfound.cn ~]$ sudo dnf install binutils ```
- 对于CentOS 7:
[linux@bashcommandnotfound.cn ~]$ sudo yum install binutils ```
- 对于CentOS 8:
[linux@bashcommandnotfound.cn ~]$ sudo dnf install binutils ```
如果在使用时出现bash: nm: command not found
的错误,请根据上面的指引进行安装。
Linux nm命令的基本语法
基本的命令格式如下:
nm [选项]... [文件]...
Linux nm命令的常用选项或参数说明
选项 | 描述 |
---|---|
-A | 在每行前显示文件名 |
-C | 解码(demangle)低级别的符号名以显示用户级别的名字 |
-D | 显示动态符号而不是普通符号 |
-g | 仅显示外部符号 |
-l | 使用源代码行号 |
-n | 按照地址排序输出符号 |
-p | 不排序输出 |
-r | 反向排序 |
-S | 打印符号的大小 |
-u | 仅显示未定义的符号 |
Linux nm命令的实例
实例1:列出符号表
列出给定目标文件的符号表。
[linux@bashcommandnotfound.cn ~]$ nm /path/to/your/file
实例2:列出符号表并解码名称
列出符号表并将符号名称解码(demangle)成用户级别的名称。
[linux@bashcommandnotfound.cn ~]$ nm -C /path/to/your/file
实例3:仅显示外部符号
显示目标文件中所有外部(global)符号。
[linux@bashcommandnotfound.cn ~]$ nm -g /path/to/your/file
实例4:显示动态符号
显示共享库或动态链接对象的动态符号。
[linux@bashcommandnotfound.cn ~]$ nm -D /path/to/your/shared/library.so
实例5:按地址排序符号表
按照地址对符号进行排序后输出。
[linux@bashcommandnotfound.cn ~]$ nm -n /path/to/your/file
实例6:显示每行前的文件名
在多文件输入时,在每行前显示文件名。
```shell
[linux@bashcommandnotfound.cn ~]$ nm -A /path/to/your/files
实例7:显示源代码的行号
[linux@bashcommandnotfound.cn ~]$ nm -l /path/to/your/file
实例8:反向排序输出符号表
[linux@bashcommandnotfound.cn ~]$ nm -r /path/to/your/file
实例9:打印符号的大小
[linux@bashcommandnotfound.cn ~]$ nm -S /path/to/your/file
实例10:显示未定义的符号
[linux@bashcommandnotfound.cn ~]$ nm -u /path/to/your/file
实例11:列出所有符号及其类型
假设您有一个名为 example.o
的目标文件,要查看所有符号及其类型:
nm example.o
这将列出所有的符号,每个符号旁边都会有一个表示其类型的字符,例如 T
表示文本(代码)段中的符号。
实例12:查找特定符号是否存在
如果您想确认是否存在一个名为 main
的符号,可以使用 grep
:
nm example.o | grep ' main'
实例13:列出未定义的符号
为了找到所有未定义的符号,这些符号需要在链接时解析:
nm -u example.o
实例14:查看符号的大小
如果您对符号的大小感兴趣,可以使用 -S
选项:
nm -S --size-sort example.o
这将列出符号及其大小,并根据大小排序。
实例15:查看C++符号的真实名称
C++ 符号会因为名称修饰(mangling)而变得难以阅读。使用 -C
选项可以得到它们的实际名称:
nm -C example.o
实例16:列出具有源代码行号的符号
如果目标文件带有调试信息(使用 -g
选项编译),可以显示符号的源代码行号:
nm -l example.o
实例17:列出所有全局(外部)符号
要仅列出全局符号,可以使用 -g
选项:
nm -g example.o
这对于理解哪些符号将被其他对象文件或库引用很有帮助。
实例18:在输出中显示文件名
如果您正在处理多个文件并希望知道符号来自哪个文件,可以这样做:
nm -A file1.o file2.o
实例19:按符号名称排序输出
虽然默认输出是按符号值(地址)排序的,但有时按名称排序更有用:
nm example.o | sort
或者使用 nm
的 -p
选项来避免排序:
nm -p example.o
实例20:打印出特定类型的符号
如果您只对某种特定类型的符号感兴趣,例如只想查看文本段(代码)中的符号,可以使用 grep
过滤输出:
nm example.o | grep ' T '
这里的 ' T '
是过滤文本段中的符号,每个类型的符号都有一个特定的字母与之对应。例如,T
表示文本段,B
表示未初始化的数据段,D
表示已初始化的数据段,等等。
实例21:查找静态库中的符号
如果您有一个静态库 libexample.a
并且想要查看它包含的符号:
nm libexample.a
实例22:查看动态库中的符号
对于动态共享库(例如 libexample.so
),您可能想查看动态符号,这些符号在运行时由动态链接器解析:
nm -D libexample.so
实例23:结合使用 nm
和 c++filt
在处理非常复杂的符号,特别是模板实例化生成的符号时,有时即使使用 -C
选项,输出也可能不够清晰。这时可以使用 c++filt
工具来进一步解码符号:
nm example.o | c++filt
Linux nm命令的注意事项
- 使用nm命令时,源文件需要包含调试信息,否则符号可能不会按预期显示。
- 当处理大型文件时,
nm
命令的输出可能会非常庞大,使用工具如less
或grep
来过滤结果可能会有所帮助。 - 解码符号名(
-C
选项)可能不会总是返回预期的结果,特别是当符号信息不完整或被优化掉时。 - 在分析库文件时,记得使用
-D
选项来查看动态符号,这些符号是在运行时由动态链接器解析的。 - 如果遇到
bash: nm: command not found
,请根据您的Linux发行版使用上述提到的相应命令安装binutils
包。
评论区