Linux,GNU GCC,ld,版本脚本和ELF二进制格式 - 它是如何工作的?

the*_*ine 9 linux gcc ld

我正在尝试更多地了解Linux中的库版本以及如何将其全部用于工作.这是上下文:

- 我有两个版本的动态库,它们公开了同一组接口,比如说libsome1.solibsome2.so.

- 与之关联的应用程序libsome1.so.

- libdl.so比如,这个应用程序用来动态加载另一个模块libmagic.so.

- 现在libmagic.so与之相关联libsome2.so.显然,如果不使用链接描述文件来隐藏符号libmagic.so,则在运行时libsome2.so将解析所有对接口的调用libsome1.so.这可以通过检查返回libVersion()的值与宏的值来确认LIB_VERSION.

- 所以我接下来尝试编译并链接libmagic.so一个链接器脚本,该脚本隐藏了除3之外的所有符号,这些符号在其中定义libmagic.so并由其导出.这工作......或者至少libVersion()LIB_VERSION值匹配(并且它报告版本2而不是1).

- 但是,当某些数据结构被序列化到磁盘时,我注意到了一些损坏.在应用程序的目录中,如果我删除libsome1.so并在其指向的位置创建一个软链接libsome2.so,一切都按预期工作,并且不会发生相同的损坏.

我不禁想到这可能是由于运行时链接器的符号解析中的某些冲突引起的.我尝试了很多东西,比如尝试链接libsome2.so以便所有符号都被赋予symbol@@VER_2(我仍然感到困惑,因为命令nm -CD libsome2.so仍然列出符号symbol而不是symbol@@VER_2)...似乎什么都没有用!!! 救命!!!!!!

编辑:我刚才所说,但有问题的应用程序是Firefox和libsome1.solibsqlite3.so随它.我不太可能重新编译它们.此外,使用版本脚本隐藏符号似乎是目前唯一的解决方案.那么当隐藏符号时会发生什么?他们成为SO的"本地"吗?rtld不知道它们的存在吗?当导出的函数引用隐藏符号时会发生什么?

jil*_*les 3

尝试编译两者libsome1.solibsome2.so添加符号版本控制,每个版本都有自己的版本(使用 选项--version-scriptld。然后链接应用程序并libmagic.so使用新库。那么,libsome1.solibsome2.so应该完全分开。

如果存在对符号的未版本控制的引用,仍然可能会出现问题。此类引用可以通过版本化定义来满足(以便可以在不破坏二进制兼容性的情况下向库添加符号版本控制)。如果有多个同名符号,有时很难预测将使用哪一个。

关于工具,nm -D不显示有关符号版本控制的任何信息。尝试objdump -Treadelf -s替代。