检查AArch64静态库未定义符号仅来自libc与stdlib的方法
我构建了一个C++软件模块,以包含API的头文件(.h)和承载实现的静态库(.a)形式交付。该模块仅依赖标准库,因此需要检查static_lib.a中的所有未定义符号是否均来自libc和stdlib,否则说明存在函数实现缺失。
该模块在x86_64 Linux计算机上交叉编译为AArch64架构。
现有方案与问题
可行但繁琐的方案
将测试可执行文件与static_lib.a链接,依靠链接器查找未定义引用,但此类可执行文件需调用API提供的所有函数,且在函数增减时需手动更新。
我尝试的最优方案
- 通过以下命令获取libc.so和libstdc++.so路径:
gcc [cflags] --print-file-name=libc.so gcc [cflags] --print-file-name=libstdc++.so - 通过以下命令获取libc和stdlib提供的符号列表:
nm --format=posix --dynamic $LIBC_PATH $LIBSTD_PATH | awk '{print $1}' | grep -v ':$' > stdsyms - 通过以下命令获取我的库中的未定义符号列表:
nm --format=posix --undefined-only static_lib.a | awk '{print $1}' | grep -v ':$' > undefined - 检查undefined中的所有符号是否都存在于stdsyms中:
while read symbol; do grep -q "^$symbol$" stdsyms || echo $symbol >> missing; done < undefined if [ -s missing ]; then echo "missing symbols:"; cat missing; false; fi
遇到的问题
libc.so实际是一个文本链接脚本,内容如下:
/* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ OUTPUT_FORMAT(elf64-littleaarch64) GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux-aarch64.so.1 ) )
nm无法解析该脚本。我考虑过解析文件提取/lib/libc.so.6,并从gcc的cflags中提取--sysroot参数构建实际路径,但这种方式非常脆弱。尝试用gcc [cflags] --print-file-name=libc.a替代也没有结果。
针对他人回答的补充说明
实际上该库已使用部分链接(使用-r -nostlib标志)。
然后将main.o与lib.o链接,如果链接成功,则不存在未解析符号。
这要求用于创建main.o的main.c调用库API的所有函数,而我找不到简便的自动化方法。
它实际上是一个链接脚本,但明确告知了将使用的libc.so.6和libc_nonshared.a,因此可以扫描这些文件。
我最终可能会采用这种方式,但希望找到无需手动解析该文件的解决方案(比如以特殊模式调用链接器?我会做一些测试)。
解决方案
可以通过链接器的特殊模式来规避nm无法解析链接脚本的问题,具体是直接让链接器检查静态库的未定义符号,无需手动解析标准库的实际路径。需要注意的是:这种方式仅能检测出静态库中“未定义”的符号,对于API中未被实现的“缺失”符号,目前唯一有效的解决方案还是构建一个调用了所有API函数的可执行文件并完成链接。
内容的提问来源于stack exchange,提问作者many-sigsegv

