18

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

4

3 回答 3

28

假设一个 linux 机器,nm工具,在库文件中列出名称,来救援。

它可以用来进行广泛的搜索,如下所示:首先可以使用 find 找到所有可用的库(假设项目已成功编译而没有添加您要添加​​的组件),然后可以将此类 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

你找到了你通常的嫌疑人。

于 2013-11-11T21:16:05.903 回答
8

使用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+ GNUparallel

在所有文件上运行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 秒
于 2019-05-25T14:44:03.087 回答
4

在这里使用 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
于 2016-05-24T17:18:09.147 回答