如何在静态库中找到符号定义的位置

a1a*_*1an 9 c++ linker undefined-symbol libraries

假设您使用包含多个工具和库的代码库,并且您希望在这样的代码库中移植(或复活)某些组件,但是关于符号位于各种库中的任何线索要么丢失要么要花费很长时间才能查找代码本身(是改进的文档可以避免这样的问题,但要求很高).发现在哪个库中可以找到代码中使用的符号的最快方法是什么?

a1a*_*1an 17

假设有一个linux盒子,那么列出库文件名称的nm工具就可以解决问题.

它可以用来进行如下的广泛搜索:首先可以找到所有可用的库(假设项目已成功编译而没有你要添加的组件)和一个find,然后这样的查找可以包含在你的循环中在所有发现的库上调用nm; 然后输出然后grep丢弃"U"引用(未定义的符号,也就是使用符号的其他地方).在单个bash行上,它给出:

for lib in $(find base_path -name \*.a) ; do echo $lib ; nm $lib | grep my_symbol | grep -v " U "   ; done
Run Code Online (Sandbox Code Playgroud)

哪里:

  • base_path是代码库的根
  • my_symbol是你要找的符号

echo生成了一个找到的所有库的列表,由于它输出的库名不包含符号,因此它不是那么干净,但它是我发现直接引用库的最快方式,所以当你看到一个:

base_path/component/libA.a
0000000000000080 D my_symbol
Run Code Online (Sandbox Code Playgroud)

你找到了通常的嫌疑人.

  • 你应该指出**nm**是解决方案的关键. (3认同)
  • nm 的 -A 选项将打印文件名。无需在示例中 echo $lib 。 (2认同)

小智 5

使用nm,可以列出二进制文件中定义的符号,并且--defined-only开关忽略未定义的引用。

选项1: find

在单个命令中:

find $path -name \*.a -exec bash -c "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}" \;
Run Code Online (Sandbox Code Playgroud)

其中$path是包含二进制文件的文件树的根,$symbol是您要查找的符号的名称。

选项 2:find+ GNUparallel

nm在所有文件上运行可能需要时间,因此find并行处理结果可能会有所帮助(使用 GNU parallel):

find $path -name \*.a | parallel "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}"
Run Code Online (Sandbox Code Playgroud)

选项 3: fd

最后,我最喜欢的。使用该fd工具的语法比 更简单find,通常速度更快,并且默认情况下并行处理结果:

fd '.*\.a$' -x bash -c "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}"
Run Code Online (Sandbox Code Playgroud)

简单的基准

在我的笔记本电脑上搜索gz_write符号/usr/lib

  • find 大约需要 23 秒
  • find | parallel 大约需要 10 秒
  • fd 大约需要 8 秒