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

我正试图在Linux中学习更多关于图书馆版本pipe理的知识,以及如何把这一切付诸实施。 这是上下文:

– 我有两个版本的dynamic库,它们公开了相同的一组接口,比如libsome1.solibsome2.so

– 应用程序链接到libsome1.so

– 这个应用程序使用libdl.sodynamic加载另一个模块,比如说libmagic.so

– 现在libmagic.so链接到libsome2.so 。 显然,如果不使用链接器脚本来隐藏libmagic.so符号,则在运行时所有对libsome2.so中的接口的调用libsome2.soparsing为libsome1.so 。 这可以通过检查libVersion()返回的值与macrosLIB_VERSION的值来LIB_VERSION

– 所以我尝试下一步编译链接libmagic.so链接器脚本,隐藏libmagic.so中定义的除3之外的所有符号,并由其导出。 这工作…或者至lesslibVersion()LIB_VERSION值匹配(并报告版本2不是1)。

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

我不禁想到,这可能是由于运行时链接程序的符号parsing中的一些冲突造成的。 我已经尝试了很多东西,比如试图链接libsome2.so这样所有的符号都被symbol@@VER_2symbol@@VER_2 (我仍然感到困惑,因为命令nm -CD libsome2.so仍然将符号列为symbol而不是symbol@@VER_2 )…似乎没有工作! 帮帮我!!!!!!

编辑:我应该早些提到它,但有问题的应用程序是Firefox,而libsome1.solibsqlite3.so随附的。 我不太可能重新编译它们。 而且,使用版本脚本来隐藏符号似乎是目前唯一的解决scheme。 那么当符号被隐藏时究竟发生了什么? 他们成为“本地”的SO? rtld不知道他们的存在吗? 当一个导出的函数引用一个隐藏的符号时会发生什么?

Solutions Collecting From Web of "Linux,GNU GCC,ld,版本脚本和ELF二进制格式 – 它是如何工作的?"

尝试编译libsome1.solibsome2.so以添加符号版本,每个版本都有自己的版本(使用--version-script选项到ld )。 然后使用新库链接应用程序和libmagic.so 。 那么, libsome1.solibsome2.so应该完全分开。

如果有符号的未版本引用,问题仍然会发生。 这些引用可以通过版本化的定义来满足(这样可以在不破坏二进制兼容性的情况下将符号版本化添加到库中)。 如果有多个相同名称的符号,有时可能很难预测使用哪一个符号。

关于工具, nm -D不显示关于符号版本的任何信息。 尝试使用objdump -Treadelf -s