问题一:
你是否遇到过: 常常遇到加载一些so时, 提示undified symbol,致使加载失败, 但是makefile明明包含了指定的库呀, 怎么还会undified ?
问题二:
你是否还遇到过, 经过ldd -r 查看so, 发现输出包含有undified symbol, 但却仍能正常加载.
问题一的解决之道
咱们要解决的是, 如何让so正确的找到symbol.
可能缘由之一:
假设咱们知道undified symbol的符号肯定存在xxx.a里面.
虽然使用了Makefile里面加上了xxx.a的依赖, 可是, 必定要把xxx.a放在最后面. 由于有可能so依赖的其余的.a库也用到了xxx.a.
(PS:为何要放在后面, 参考本系列的其余文章)
现实案例:
某次编译so时, 对编译结果so文件ldd -r, 发现有undified symbol, 可是明明连接了对应的open_l5库, 为什么还提示未找到符号?
file bin/spp_appwork.so
bin/spp_appwork.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped
ldd -r bin/spp_appwork.so 2>&1 | grep -v "tbase\|Tencent\|write_log\|dl"
linux-gate.so.1 => (0xbfffe000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb7e7e000)
libz.so.1 => /usr/lib/libz.so.1 (0xb7e6c000)
libcrypto.so.0.9.8 => /usr/lib/libcrypto.so.0.9.8 (0xb7d40000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7c5f000)
libm.so.6 => /lib/libm.so.6 (0xb7c3a000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7c2f000)
libc.so.6 => /lib/libc.so.6 (0xb7b0f000)
/lib/ld-linux.so.2 (0x80000000)
undefined symbol: _ZN7COpenL54LoadEii (bin/spp_appwork.so)
undefined symbol: _ZN7COpenL56UpdateEi (bin/spp_appwork.so)
经过调整open_l5库的位置, 问题解决.
可能缘由之二:
该符号原本是应该属于其所依赖的某个so的, 可是因为当前环境的so版本较低, 没有包含指定的符号.
该猜想经过以下方式验证
// 按照正常的流程编译ld_so, 能够正常运行
nemo@vm04_sles10:[ld_so]$ g++ -o ld_so ld_so.cpp -L. -la
nemo@vm04_sles10:[ld_so]$ ./ld_so
lalala
call in funa()
// 找一个其余的so替换liba.so,
nemo@vm04_sles10:[ld_so]$ cp liba.so liba.so.bk
nemo@vm04_sles10:[ld_so]$ cp d.so liba.so
// 启动时会发现undefined symbol
nemo@vm04_sles10:[ld_so]$ ./ld_so
lalala // <========== 程序的前半部分代码执行了, 输出了lalala
./ld_so: symbol lookup error: ./ld_so: undefined symbol: _Z4funav // <========== 报错了.
// 经过ldd -r 查看, 也能够看出未定义的符号.
nemo@vm04_sles10:[ld_so]$ ldd -r ld_so
undefined symbol: _Z4funav (./ld_so) // <============= 未定义的符号.
linux-gate.so.1 => (0xbfffe000)
liba.so (0xb7f87000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e9d000)
libm.so.6 => /lib/libm.so.6 (0xb7e78000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7e6d000)
libc.so.6 => /lib/libc.so.6 (0xb7d4c000)
/lib/ld-linux.so.2 (0xb7f8a000)
现实案例二:
本人在制做绿色版lamp时也遇到相似问题. 在启动apache时, 提示加载libphp5.so失败: undefined symbol: xmlTextReaderSetup
经排查发现, 系统的/usr/local/bin目录存在一个libxml2.so, 和我在当时编译php时使用的libxml2的版本不一致, 经过修改 LD_LIBRARY_PATH, 使之优先寻找我指定目录下的的libxml2库解决.
问题二的解决之道
即便有undefined symbol:, 只要代码在执行的过程当中用不到 也能正常加载so ?
是的. 可是, 一旦在用到的时候, 就会报错了. 就好比上面的例子, 执行ld_so输出了lalala, 而后才报错未找到符号undefined symbol: _Z4funav.
说明:
ld 在连接生成so的时候, 容许undefined symbol, 由于这些确实的符号可能在so被加载时就解决了.
ld 在连接生成可执行文件的时候, 是不容许undefined symbol的php