共享对象中的符号

Posted

技术标签:

【中文标题】共享对象中的符号【英文标题】:symbols in shared objects 【发布时间】:2019-12-13 04:39:29 【问题描述】:

我的情况是:

框架静态库 - libFramework.a 使用该框架的共享对象 - mySharedObj.so 使用两个库的可执行文件 - myExe.elf

我正在分别编译so和elf。 有时框架有一个新版本,我只想更新 so 或只更新精灵(没关系) 但是当我运行应用程序(带调试)时,我看到 so 正在使用 elf 框架库 如何在精灵下运行时“强制”使用它自己的框架实例

顺便说一句,如果偶然 so 和 elf 都有一个同名的类(如果不使用命名空间等),我也会遇到同样的问题 所以使用 elf 类。

【问题讨论】:

【参考方案1】:

可能发生的情况是 libFramework.a 正在公开动态符号。当您启动 myExe.elf 时,它会从自身(或它自己的 libFramework.a 副本,如果您想这样看的话)解析这些动态符号。

加载 mySharedObj.so 后,它会再次解析所有这些符号,并在 myExe.elf 而不是 mySharedObj.so 中查找符号,因为它正在重用之前解析的结果。您可能可以通过运行带有 LD_DEBUG=all 的 myExe.elf 来确认这一点,例如LD_DEBUG=all myExe.elf.

要阻止这种情况发生,您需要防止任何动态符号被 libFramework.a 导出。您可以使用编译器标志-fvisibility=hidden 将默认值更改为隐藏的符号,然后确保您的符号不会再被源代码中的属性变为可见,例如__attribute__ ((visibility ("default"))) 或通过推送和弹出可见性#pragma GCC visibility push(default) #pragma GCC visibility pop。您还可以使用 nm 查看哪些符号被公开为动态符号。

出于性能原因,也值得检查这类东西。如果您的所有符号都是动态的,则运行时动态链接器必须做更多的工作,因此您的程序将需要更长的时间来加载。编译器还可以生成更好的代码,因为它不必放入代码来让函数被动态调用。链接器可以更好地消除死代码等。有很多胜利。

【讨论】:

以上是关于共享对象中的符号的主要内容,如果未能解决你的问题,请参考以下文章

Cython:共享对象中的未定义符号

如何找出从共享对象导出的所有符号?

共享对象,符号,C / C ++ lib链接和加载

是否有任何类似于 objcopy 的命令可以从共享对象文件中删除符号?

将共享库与 dlopen 一起使用 - 共享对象找不到加载程序导出的符号

gcov 检测共享对象引用 __gcov_init 隐藏符号