LLD是链接器,只在构建阶段检查符号,不用于事后诊断;查已有.so未定义符号应使用ldd -r或readelf -d与nm -D组合。

LLVM LLD 本身不提供运行时符号检查功能
LLD 是链接器(linker),只在构建阶段工作,它不会分析已生成的 .so 文件是否存在未解析符号。你看到的 “undefined symbol” 报错,只可能发生在 LLD 执行链接时(比如生成可执行文件或新共享库的过程中),而**不是**对已有 libxxx.so 的事后诊断工具。
想查已有共享库里的未解析符号?用 ldd -r,不是 LLD
检查运行前静态依赖和符号状态,Linux 标准做法是用系统自带的 ldd(基于 glibc 的动态链接器模拟):
-
ldd -r libexample.so会列出所有重定位项(relocations)和未满足的符号(undefined symbol行) - 若输出含
undefined symbol,说明该库引用了某个符号,但没在自身或其直接依赖中定义——常见于:漏链接实现库、C++ name mangling 不匹配、头文件/实现不一致 - 注意:
ldd -r不执行代码,但会尝试解析所有NEEDED库;若某依赖缺失,它可能报not found并跳过后续符号检查
更底层、更安全的替代:用 readelf -d 和 nm -D 组合
当不能信任 ldd(比如面对不可信二进制,或旧版 glibc 可能触发初始化代码)时,应绕过它:
-
readelf -d libexample.so | grep NEEDED—— 看它声明依赖哪些库(静态 DT_NEEDED 条目) -
nm -D libexample.so | grep " U "—— 列出所有未定义的动态符号(U = undefined) - 对比两者:
nm -D输出的U符号,必须能在readelf -d列出的依赖库中被nm -D找到定义(D = defined),否则就是真正缺失 - 这个组合不调用任何动态链接器逻辑,无执行风险,也不受
LD_LIBRARY_PATH影响
为什么不用 objdump -T 或 nm -C 直接看?
这几个命令行为有关键差异:
-
nm -D只显示动态符号表(即导出/导入的符号),适合检查运行时链接行为;nm默认显示静态符号,噪音大且无关 -
objdump -T等价于nm -D,可用但输出格式略冗长 -
nm -C用于 demangle C++ 符号名,仅在看到乱码符号(如_Z12my_functionv)时才需要加,否则反而干扰快速扫描 - 不要用
ldd查运行中进程——它对/proc/PID/exe的结果仍是编译期声明,不是真实加载项;真要看运行时,得用sudo pldd <pid>
visibility=hidden 导致本该导出的符号没出现在动态符号表里——这些都不会被 ldd -r 报错,但会导致运行时报 symbol lookup error。

















