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

时间:2013-11-11 21:16:06

标签: c++ linker libraries undefined-symbol

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

3 个答案:

答案 0 :(得分:16)

假设有一个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

其中:

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

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

base_path/component/libA.a
0000000000000080 D my_symbol

你找到了通常的嫌疑人。

答案 1 :(得分:1)

使用nm的--defined-only开关在这里很有用,因为它将删除未定义的引用。下面是一个可能对其他人有用的csh脚本。

#!/bin/csh
#
#recurse from current dir and output name of any .a files
#that contain the desired symbol.
echo "Search for: $1"
foreach i (`find . -name '*.a'`)
    nm --defined-only $i | grep $1
    if ($status == 0) then
        echo $i
    endif
end

答案 2 :(得分:0)

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

选项1:find

在一个命令中:

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

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

选项2:find + GNU parallel

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

find $path -name \*.a | parallel "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}"

选项3:fd

最后,我的最爱。使用fd工具(其语法比find简单)通常更快,并且默认情况下并行处理结果:

fd '.*\.a$' -x bash -c "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}"

简单基准测试

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

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