通常,在开发库/应用程序时,可以使用ldd
程序检查外部依赖项(链接在动态库中)和未定义的符号:
$ ldd -r libfoo.so
linux-vdso.so.1 (0x00007fff6b9fe000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa55fe31000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa55fa85000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa560386000)
libbar.so.0 => /usr/local/lib/libbar.so.0
undefined symbol: bar_nullfn (libfoo.so)
所以这个例子似乎安装了一个不兼容的libbar.so版本,它缺少bar_nullfn
. 这很少发生在用于构建的机器上libfoo.so
,因为链接器已经在构建阶段抱怨缺少符号。
这很好用,只要运行时链接器可以根据中的信息解析符号(或不解析)libfoo.so
不幸的是,我正在使用插件,即由主机应用程序 dlopen() 编辑的动态库。这些插件使用来自主机应用程序的函数(通过标头公开),但无法在主机上下文之外解析。自然,跑步ldd -r
会给我带来很多误报:
$ ldd -r ./foo.so
linux-vdso.so.1 (0x00007fff6b9fe000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa55fe31000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa55fa85000)
undefined symbol: post (./foo.so)
undefined symbol: startpost (./foo.so)
undefined symbol: clock_free (./foo.so)
undefined symbol: clock_new (./foo.so)
undefined symbol: logpost (./foo.so)
undefined symbol: clock_set (./foo.so)
由于主机提供了这些符号(post
,...),因此即使插件似乎有很多未定义的符号,也可以对插件进行 dlopen() 处理。
链接器被明确指示忽略丢失的符号,以便能够构建这样的插件。
现在我的问题是,有时这样的插件确实有一个未定义的符号,在运行时无法解决。由于在构建过程中要求链接器忽略丢失的符号,因此不会发出警告。但是当插件被加载时,会dlopen()
失败,比如
undefined symbol: psot
ldd 给我:
$ ldd -r ./foo.so
linux-vdso.so.1 (0x00007fff6b9fe000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa55fe31000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa55fa85000)
undefined symbol: post (./foo.so)
undefined symbol: startpost (./foo.so)
undefined symbol: logpsot (./foo.so)
undefined symbol: clock_free (./foo.so)
undefined symbol: clock_new (./foo.so)
undefined symbol: psot (./foo.so)
undefined symbol: logpost (./foo.so)
undefined symbol: clock_set (./foo.so)
目前我知道如何解决这个问题的唯一方法是迭代地修复每个丢失的符号。例如,如果我使用(不存在的)函数在我的插件中输入了两个拼写错误,psot()
并且logpsot()
,我启动我的主机,加载插件,发现我使用了该符号psot
,修复问题,重新编译,重新启动主机/插件,才发现我还写了logpsot
。
我想知道是否有一种方法可以指定可用于解析符号ldd
(或类似符号)的其他二进制对象。例如
ldd --addlib /path/to/host -r ./foo.so
$ ldd -r ./foo.so
linux-vdso.so.1 (0x00007fff6b9fe000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa55fe31000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa55fa85000)
undefined symbol: logpsot (./foo.so)
undefined symbol: psot (./foo.so)