从 dlopen()'ed .so 中丢弃未使用的符号

Discard unused symbos from dlopen()'ed .so

我有一组仅以二进制形式分发的共享库 (Intel MKL)。顶级 "runtime" 库 libmkl_rt.so 链接到我的可执行文件,并且可以通过 ldd:

看到
...
libmkl_rt.so => /var/task/lib/libmkl_rt.so (0x00007f8049a1f000)
...

然而,其他的,例如 libmkl_avx.so,我假设是用 dlopen() 动态加载的,因为可执行文件会抛出一个错误,指出如果找不到库则丢失,但不可见ldd.

这些库很大(> 100MB),这是我容器中唯一使用它们的可执行文件。我假设可执行文件不会调用这些库中的每个函数,所以我想精简它们,首先确定调用了哪些函数,然后只保留那些函数。

我怎样才能:

  1. 确定实际使用了动态加载的共享库中的哪些符号?
  2. 仅将那些符号提取到库的 "slim" 副本中?

有这方面的工具吗?

Determine which symbols in the dynamically loaded shared libraries are actually used?

您可以 运行 您的程序在 LD_DEBUG=bindings LD_BIND_NOW=1 下查看绑定了 libmkl_avx.so 中的哪些符号。

Extract only those symbols into a "slim" copy of the library?

不幸的是,由于无法在可执行文件中重新排列函数的相同原因,这是不可能的。链接代码后,所有内部 goto 和全局变量位置都是固定的,无法更改。即使正确反汇编链接代码(以确定函数边界和调用图)也是一个无法解决的问题(像 IDA 这样的工具使用启发式方法来缓解它,但问题仍然存在)。

这应该不是什么大问题,因为 OS 只会加载您的应用程序实际使用的代码页。