Linux 没有定义的符号 调试方法 nm命令

本文详细介绍了nm命令的功能及其使用方法,包括列出目标文件中的各种符号类型,并通过实例展示了如何使用不同的选项来获取所需的符号信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nm命令
[
在GNU C语言库提供的内容中,有接口可以用来做这件事。用下面的命令查看:
nm -D /lib/libc.so.6 | grep log
]


nm命令还是比较简单而且强大的。它用来列出一个目标文件中的各种符号。符号的种类很多,以下是一些常见的符号类型
nm输出字符 含义
R Read only symbol. 比如在代码中有一个const MAXDATA = 3095; 则MAXDATA就是一个Read only symbol
N 这是一个调试符号
D 这是一个已经初始化的变量的符号。比如代码中int  i = 1和char *str = "Hello"则i和str都是这种类型的符号
T Text段的符号。子程序都是这种符号,比如文件中实现了一个函数function,则function就是这种符号
U 未定义的符号。如果文件中引用了不存在的函数,则这些未定义的函数符号就是这种类型
S 未初始化的符号,比如全局变量int s;则s的符号就是此类型
nm命令的详细用法以及例子见正文。

先来例子,以下是a.c的内容:

#include <stdio.h>

static int s_global;
int i = 1;
char *str = "hello, world";
const ID = 10;
extern int e_global;
void function()
{
        printf("Hello");
}


int get_x()
{
        int x;
        x = 33;
        return x;
}


在执行"gcc -g -O -c a.c"产生a.o之后,用"nm -A a.o"的输出为:

a.o:00000000 R ID
a.o:00000000 T function
a.o:00000014 T get_x
a.o:00000000 D i
a.o:         U printf
a.o:00000000 b s_global
a.o:00000004 D str

nm的用法

nm的用法很简单,以下几个关键字比较常用:

1、"-A",列出符号名的时候同时显示来自于哪个文件。

这在同时列出多个文件(比如一个链接库)的符号时比较有用

2、"-a",列出所有符号

这将会把调试符号也列出来。默认状态下调试符号不会被列出。

3、"-l",列出符号在源代码中对应的行号

指定这个参数后,nm将利用调试信息找出文件名以及符号的行号。对于一个已定义符号,将会找出这个符号定义的行号,对于未定义符号,显示为空

4、"-n",根据符号的地址来排序

默认是按符号名称的字母顺序排序的

5、"-u",只列出未定义符号

同"--undefined-only", 而"--defined-only"将只列出已定义符号

<think>我们已经在之前的对话中详细解释了如何使用`find`和`nm`命令的组合来在多个.so文件中查找包含特定符号表的文件。现在用户的问题是:“我想查找包含指定符号表的so文件请问如何使用nm命令批量查找多个so文件中包含特定符号表的文件”。用户特别提到了使用`nm`命令。回顾:我们已经给出了一个命令模板:find/搜索路径-typef-name"*.so"-execsh-c'nm-g--defined-only"{}"|grep-q"特定符号名"&&echo"{}包含该符号"'\;现在,我们可以根据用户的当前问题,更详细地解释如何使用`nm`命令进行批量查找,并给出具体步骤和示例。步骤:1.打开终端。2.使用`find`命令来定位所有的.so文件,并对每个文件执行`nm`命令。3.在`nm`命令中,我们使用`-g`选项只显示全局符号,使用`--defined-only`选项只显示已定义符号(这样可以避免未定义的引用,即来自其他库的符号)。4.通过管道将`nm`的输出传递给`grep`,使用`-q`选项(安静模式)来检查是否包含特定符号。如果找到,则`grep`返回0(成功),然后执行`&&`后面的命令,即打印文件名。注意:符号名是区分大小写的,且要确保写对符号名的全称(包括命名空间等,比如C++函数名会被修饰,所以可能需要使用`c++filt`来反修饰,但这里先不展开)。示例:在`/usr/lib`目录下查找所有包含符号`pthread_create`的.so文件。命令:find/usr/lib-typef-name"*.so"-execsh-c'nm-g--defined-only"{}"|grep-q"pthread_create"&&echo"{}"'\;注意:这里没有使用`echo"{}包含该符号"`,而是直接输出文件名,因为用户可能只需要文件名。另外,如果.so文件很多,这个命令可能会运行一段时间。为了加快速度,可以限制搜索的深度,例如只搜索一级子目录:find/usr/lib-maxdepth1-typef-name"*.so"-execsh-c'nm-g--defined-only"{}"|grep-q"pthread_create"&&echo"{}"'\;如果用户想要查看符号的类型,可以去掉`grep-q`,直接显示匹配的行,但这样会同时输出符号信息。例如:find/usr/lib-typef-name"*.so"-execsh-c'nm-g--defined-only"{}"|grep"pthread_create"&&echo"{}"'\;但这样会在每个文件匹配的行下面打印文件名,格式可能混乱。我们可以改进为:在每个匹配的文件名之前先打印一个分隔符,然后打印文件名,再打印匹配的行。但这会使得输出较长。用户如果只需要文件名,第一种方式更简洁。另外,考虑到`nm`命令可能对非ELF文件无效,所以如果目录中有非ELF的.so文件(虽然不太可能),命令可能会报错。可以忽略这些错误信息:2>/dev/null改进命令:find/usr/lib-typef-name"*.so"-execsh-c'nm-g--defined-only"{}"2>/dev/null|grep-q"pthread_create"&&echo"{}"'\;如果用户想同时查找多个符号,可以使用正则表达式,例如同时查找`pthread_create`和`pthread_exit`:find/usr/lib-typef-name"*.so"-execsh-c'nm-g--defined-only"{}"|grep-q-E"pthread_create|pthread_exit"&&echo"{}"'\;总结:核心是`nm-g--defined-only`列出每个文件的全局定义符号,然后用`grep`过滤,如果找到就输出文件名。最后,提醒用户:如果搜索的目录需要root权限,那么命令前可能需要加`sudo`。现在,我们按照要求结构化回答,并生成相关问题。</think> ### 如何在多个.so文件中查找特定符号表 使用`nm`命令结合`find`命令可以高效地在多个.so文件中批量查找特定符号表(函数/变量名称)。以下是详细步骤: --- #### 📌 核心命令(推荐方法) ```bash find /目标目录 -type f -name "*.so" -exec sh -c ' nm -gD --defined-only "{}" | grep -q "符号表名称" && echo "找到符号: {}" ' \; ``` **参数解析**: 1. `find /目标目录` - 从指定目录递归搜索(如`/usr/lib`或`.`表示当前目录) - 添加 `-maxdepth 3` 可限制搜索深度(例如只搜3层子目录) 2. `-type f -name "*.so"` - 仅查找扩展名为`.so`的共享库文件 3. `nm -gD --defined-only` - `-gD`:仅显示动态符号表中的全局符号 - `--defined-only`:过滤掉未定义的引用符号(避免干扰)[^1] 4. `grep -q "符号表名称"` - `-q`:静默模式(不输出匹配内容,只返回状态) - 符号名需完全匹配(如`my_function`或`global_variable`) 5. `&& echo "找到符号: {}"` - 仅当符号存在时输出文件名 --- #### 🌰 实际示例 查找`/usr/lib`目录下所有包含符号`pthread_create`的.so文件: ```bash find /usr/lib -type f -name "*.so" -exec sh -c ' nm -gD --defined-only "{}" | grep -q "pthread_create" && echo "文件包含符号: {}" ' \; ``` **输出结果**: ```bash 文件包含符号: /usr/lib/libpthread.so.0 文件包含符号: /usr/lib/x86_64-linux-gnu/libgomp.so.1 ``` --- #### ⚡ 性能优化技巧 1. **并行处理**(加快大目录搜索) ```bash find /目标目录 -name "*.so" -print0 | xargs -0 -P 4 -I {} sh -c ' nm -gD --defined-only "{}" | grep -q "符号名" && echo "{}" ' ``` - `-P 4`:启动4个并行进程 2. **过滤无效文件** 添加 `! -name "*debug*"` 跳过调试文件: ```bash find /目标目录 -name "*.so" ! -name "*debug*" -exec ... ``` 3. **输出到文件** 重定向结果:`... > results.txt` --- #### ⚠️ 注意事项 1. **符号名规范** - C++符号需使用修饰名(如`_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev`) - 获取修饰名:`c++filt _ZNSt...`(还原可读名称) 2. **权限问题** 系统目录需`sudo`执行: ```bash sudo find /usr/lib ... ``` 3. **工具依赖** 安装`binutils`包: ```bash sudo apt install binutils # Debian/Ubuntu ``` --- ### 🔍 相关问题 1. **`nm`和`readelf`在符号查找中有何区别?哪个更高效?** 2. **如何查找C++类成员函数或重载函数的符号?** 3. **Linux中有哪些工具可以分析.so文件的依赖关系?** 4. **符号查找是否支持正则表达式?如何模糊匹配符号名?** > 通过`nm`的`-gD --defined-only`过滤可显著减少噪音[^1],结合`find`的递归搜索能力,能高效定位二进制文件中的符号定义
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值