【问题标题】:ELF symbol visibilityELF 符号可见性
【发布时间】:2015-05-06 05:33:45
【问题描述】:
假设我在文件 spec_a.h 中定义了一个 api (sym1)
在 lib_imp1.so 中有这个 api 的实现。
我可以有一个 dlopen 共享库 dlsym() sym1 的应用程序并调用它。应用程序是否可以将 sym1 未定义的其他共享库 dlopen() 解析为 lib_imp1.so 中的 sym1?
如果是这样,我们该怎么做?
如果可能,那么我们可以有两个实现,lib_imp1.so 和 lib_imp2.so,对于同一个符号 sym1,它们都有两个不同的地址。
如果应用程序使用未解析的 sym1 加载另一个共享库,我们可以控制它解析到哪个 sym1(lib_imp1.so 或 lib_imp2.so)吗?
在生成 lib_imp1.so 时,我们可以说虽然我们希望导出 sym1,但我们不希望将任何未解析的符号解析为它吗? (某种受控出口??)
谢谢
【问题讨论】:
标签:
shared-libraries
visibility
symbols
elf
【解决方案1】:
我可以拥有一个 dlopen 共享库 dlsym() sym1 并调用它的应用程序。应用程序是否可以 dlopen() 将 sym1 未定义的其他共享库解析为 lib_imp1.so 中的 sym1?
是的:如果第一个dlopen 使用RTLD_GLOBAL,那么从lib_imp1.so 导出的所有符号(包括sym1)都会进入全局范围,并且对稍后加载的其他库可见。
如果可能,那么我们可以有两个实现,lib_imp1.so 和 lib_imp2.so,对于同一个符号 sym1,它们都有两个不同的地址。
是的。这是不明智的。
如果应用程序加载另一个具有未解析 sym1 的共享库,我们可以控制它解析到哪个 sym1(lib_imp1.so 或 lib_imp2.so)吗?
没有。假设你 dlopened 和 lib_imp1.so 和 lib_imp2.so 和 RTLD_GLOBAL,任何后续库将始终从提供它的第一个 dlopened 库绑定到 sym1(即它将解析为 lib_imp1.so 定义)。
此外,如果lib_imp1.so 也导出sym2,并且lib_imp2.so 中的任何内容调用sym2,则该符号也解析为lib_imp1.so 中的定义(除非你采取特殊的照顾和使用-Bsymbolic)。
最终结果是 UNIX .so 库的行为与归档库非常相似,而不是 Windows DLLs。这使得在单个进程中导出相同接口的两个独立实现在很大程度上是不可行的。
在生成 lib_imp1.so 时,我们是否可以说,虽然我们希望导出 sym1,但不希望将任何未解析的符号解析为它?
dlsym 使用完全相同相同的解析过程。如果您使符号不可用于任何解析,dlsym 也将找不到它。相反,导出符号的确切含义是“使其可用于解析”(通过dlopen 或只是常规的未解析依赖项解析)。