侧边栏壁纸
Linux入门自学网博主等级

每日学一条Linux命令,终成Linux大神

  • 累计撰写 725 篇文章
  • 累计创建 143 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Linux nm命令教程:检查二进制文件变量、函数、类成员、地址和类型等所有符号

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:结合使用 nmc++filt

在处理非常复杂的符号,特别是模板实例化生成的符号时,有时即使使用 -C 选项,输出也可能不够清晰。这时可以使用 c++filt 工具来进一步解码符号:

nm example.o | c++filt

Linux nm命令的注意事项

  • 使用nm命令时,源文件需要包含调试信息,否则符号可能不会按预期显示。
  • 当处理大型文件时,nm 命令的输出可能会非常庞大,使用工具如 lessgrep 来过滤结果可能会有所帮助。
  • 解码符号名(-C 选项)可能不会总是返回预期的结果,特别是当符号信息不完整或被优化掉时。
  • 在分析库文件时,记得使用 -D 选项来查看动态符号,这些符号是在运行时由动态链接器解析的。
  • 如果遇到 bash: nm: command not found,请根据您的Linux发行版使用上述提到的相应命令安装 binutils 包。
0

评论区