有没有一个工具可以查找共享库符号冲突?

有没有一个工具可以查找共享库符号冲突?

我正在编写的某些软件发生崩溃,我怀疑这可能是由两个不同共享库之间的符号冲突引起的(当我禁用其中一个共享库时,另一个开始工作)。

有没有一种工具可以使用它来查看程序加载的库并告诉我是否有多个库中定义的符号?

答案1

有一些常用的实用程序可以在 shell 脚本中使用来解决问题(尽管我不记得见过将它们组合起来解决问题的脚本)。这nm实用程序用于查找目标文件或可执行文件中的符号。在大多数系统上,lddotool在 macOS 上)显示可执行文件使用的共享库。对于前者,例如,我有一个脚本(listused.sh)在 ncurses 中列出了其库中的所有符号以及这些符号是否可以通过使用库的程序进行测试(请参阅报告test/README)。

-C选项很有用(如果您对 C++ 库感兴趣),但这些库可能是剥离的(缺少调试信息)。然而,-D选项(在“最近”的系统上可用,例如,过去 10-15 年更新的几乎所有内容)提供了以下符号:动态的图书馆:

显示动态符号而不是普通符号。这仅对动态对象有意义,例如某些类型的共享库。

仅显示动态符号。该选项仅对共享库有意义。

显示SHT_DYNSYM符号信息。这是 ld.so.1 使用的符号表,甚至在剥离的动态可执行文件中也存在。如果–D未指定,默认行为是显示SHT_SYMTAB符号信息。

这不是较新的系统的功能,至少根据他们的文档:

(有人可能立即知道引入该功能的时间表)。

我在一些脚本中使用了该功能,例如analyze-curses-symbols

进一步阅读:

如果您使用 -quickstart_info 选项,ld 会告诉您是否出现冲突。它还告诉您使用 -Dc 选项运行 elfdump 来查找冲突。有关如何读取 elfdump 生成的输出的更多信息,请参阅 elfdump(1) 手册页。

  • 然而,elfdump 并没有标准化(甚至在某种程度上nm是),并且-Dc在其他实现中没有发现,例如这个,对于 Solaris。 (有有关的适用于 Solaris 的程序)。

答案2

nm -C library.so | grep -i symbol

可能就是您正在寻找的。但它可能不适用于剥离的库。

答案3

Linux动态链接器还提供了一些调试此类问题的方法。例如,您可以获得export LD_DEBUG=bindings有关所有符号绑定的大量信息。将所有这些输出收集在一个文件中,并比较不同场景下的输出,您会注意到一些链接到不同文件的符号。请参阅ld.so 文档以获得更多选择。

例如,当我们将 TensorFlow 链接到我们的二进制文件中时,我们正在追踪崩溃,并且还使用了一些嵌入式 Python。我们将事故减少到了import hashlib。不链接TensorFlow时不会崩溃。 (你发现这也被报道这里这里.)

通过链接 TF,我得到如下输出:

2306643:     binding file /u/zeyer/.linuxbrew/Cellar/[email protected]/3.11.2_1/lib/python3.11/lib-dynload/_hashlib.cpython-311-x86_64-linux-gnu.so [0] to /u/zeyer/.local/lib/python3.11/site-packages/tensorflow/libtensorflow_framework.so.2 [0]: normal symbol `EVP_MD_size' [OPENSSL_1_1_0]

只是运行python -c "import hashlib"给我这样的输出:

   2307740:     binding file /u/zeyer/.linuxbrew/Cellar/[email protected]/3.11.2_1/lib/python3.11/lib-dynload/_hashlib.cpython-311-x86_64-linux-gnu.so [0] to /work/tools/users/zeyer/linuxbrew/lib/libcrypto.so.1.1 [0]: normal symbol `EVP_MD_size' [OPENSSL_1_1_0]

正如您所看到的,在使用 TF 的情况下,它会在 中找到那些与 OpenSSL 相关的符号libtensorflow_framework.so.2,在其他情况下,它会在 中找到它们libcrypto.so.1.1(应该如此)。

我们的解决方案是-L/work/tools/users/zeyer/linuxbrew/lib -Wl,-rpath,/work/tools/users/zeyer/linuxbrew/lib -Wl,-no-as-needed -lcrypto在链接 TF 库之前添加链接器标志。所以我们强制执行libcrypto.so.1.1首先加载。这样就解决了问题。看这里对于我的编译脚本。

相关内容