Linux,GNU GCC,ld,版本脚本和ELF二进制格式 - 它是如何工作的? [英] Linux, GNU GCC, ld, version scripts and the ELF binary format -- How does it work?

查看:128
本文介绍了Linux,GNU GCC,ld,版本脚本和ELF二进制格式 - 它是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Linux中学习更多关于图书馆版本控制的知识,以及如何使这一切都起作用。这里是上下文:

- 我有两个版本的动态库,它们公开了相同的一组接口,比如 libsome1.so libsome2.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 ,以便所有符号都被赋值为符号@@ VER_2 (我仍然感到困惑,因为命令 nm -CD libsome2.so 仍将符号列为符号而不是符号@@ VER_2 )...没有任何东西似乎工作!帮助!!!!!!编辑:我应该早些提到它,但是有问题的应用程序是Firefox,并且 libsome1.so $ b / code>是随附的 libsqlite3.so 。我不太可能重新编译它们。此外,使用版本脚本来隐藏符号似乎是目前唯一的解决方案。那么当符号隐藏时真的发生了什么?它们是否成为SO的本地? rtld是否不知道它们的存在?当一个导出的函数引用一个隐藏的符号时会发生什么?解析方法

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



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



关于工具, nm -D 不显示关于符号版本控制的任何信息。试试 objdump -T readelf -s


I'm trying to learn more about library versioning in Linux and how to put it all to work. Here's the context:

-- I have two versions of a dynamic library which expose the same set of interfaces, say libsome1.so and libsome2.so.

-- An application is linked against libsome1.so.

-- This application uses libdl.so to dynamically load another module, say libmagic.so.

-- Now libmagic.so is linked against libsome2.so. Obviously, without using linker scripts to hide symbols in libmagic.so, at run-time all calls to interfaces in libsome2.so are resolved to libsome1.so. This can be confirmed by checking the value returned by libVersion() against the value of the macro LIB_VERSION.

-- So I try next to compile and link libmagic.so with a linker script which hides all symbols except 3 which are defined in libmagic.so and are exported by it. This works... Or at least libVersion() and LIB_VERSION values match (and it reports version 2 not 1).

-- However, when some data structures are serialized to disk, I noticed some corruption. In the application's directory if I delete libsome1.so and create a soft link in its place to point to libsome2.so, everything works as expected and the same corruption does not happen.

I can't help but think that this may be caused due to some conflict in the run-time linker's resolution of symbols. I've tried many things, like trying to link libsome2.so so that all symbols are alised to symbol@@VER_2 (which I am still confused about because the command nm -CD libsome2.so still lists symbols as symbol and not symbol@@VER_2)... Nothing seems to work!!! Help!!!!!!

Edit: I should have mentioned it earlier, but the app in question is Firefox, and libsome1.so is libsqlite3.so shipped with it. I don't quite have the option of recompiling them. Also, using version scripts to hide symbols seems to be the only solution right now. So what really happens when symbols are hidden? Do they become 'local' to the SO? Does rtld have no knowledge of their existence? What happens when an exported function refers to a hidden symbol?

解决方案

Try compiling both libsome1.so and libsome2.so to add symbol versioning, each with their own version (use the --version-script option to ld). Then link the application and libmagic.so using the new libraries. Then, libsome1.so and libsome2.so should be completely separate.

Problems can still occur if there are unversioned references to symbols. Such references can be satisfied by versioned definitions (so that it is possible to add symbol versioning to a library without breaking binary compatibility). If there are multiple symbols of the same name, it can sometimes be hard to predict which one will be used.

Regarding tools, nm -D does not display any information about symbol versioning. Try objdump -T or readelf -s instead.

这篇关于Linux,GNU GCC,ld,版本脚本和ELF二进制格式 - 它是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆