nm 获取整个存档的未定义符号,而不是单独的目标文件

nm get undefined symbols for whole archive, not separate object files

我有两个文件:

foo.c: int foo() { extern int bar(); return bar(); }

bar.c: int bar() { extern int missing(); return missing() + 42; }

我编译它们并组成.a静态库:

$ gcc -c foo.c bar.c
$ ar rcs libfoobar.a foo.o bar.o

我想找出整个存档中缺少(未定义)的符号。但我仍然得到 bar 未定义,而它存在于 foo.o:

$ nm -u libfoobar.a
foo.o:
    U bar
bar.o:
    U missing

如何从输出中省略 bar 并仅显示 missing

存档工具只是创建……好吧,一个存档。它不是链接器。引用由您的链接器解析,此过程将在 bar.o 中找到 foo.obar 的引用。存档器不能这样做,nm 也不会这样做 - 它只是 运行 自己独立地覆盖存档内的每个对象。

Link 将整个存档放入单个目标文件并检查:

ar -x libfoo.a      # unpack libfoo.a
ld -r -o tmp.o *.o  # link all objects into tmp.o
nm -u tmp.o         # find undefined symbols in tmp.o
rm *.o              # remove tmp.o as well as the contents of libfoo.a

这应该会给出预期的结果,因为 linker 解析了它可以在 -r 请求的部分 link 中找到的所有符号。

请注意,为获得最佳效果,当前工作目录不应包含任何目标文件。

您可以使用以下脚本获得更一致的结果:

# use: script libfoo.a
tmp=${TEMPDIR:-/tmp}/undefsyms.$$
mkdir $tmp
cp  $tmp/lib.a
cd $tmp
ar -x lib.a
ld -r -o $$.o *.o
nm -u $$.o
rm *
cd ..
rmdir $tmp

如果您为此目的对库进行解包和 link 感到不自在,请使用此脚本,该脚本使用命令行实用程序计算您需要的信息,使用 join 实用程序:

if [ $# -lt 1 ]
then
    echo Usage: [=12=] library.a
    exit 1
fi

lib=

postproc() { cut -w -f 2-3 | sort -u; }
allsyms() { nm -g -P -A $lib | postproc; }
undefsyms() { nm -g -P -A -u $lib | postproc; }
defsyms() { allsyms | grep -v 'U$'; }

comm -2 -3 <(undefsyms | cut -w -f 1) <(defsyms | cut -w -f 1)