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

发布于 2024-10-12 02:34:57 字数 1344 浏览 5 评论 0原文

我正在尝试了解有关 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,该链接器脚本隐藏了除libmagic.so中定义并由其导出的3个符号之外的所有符号。这有效...或者至少 libVersion()LIB_VERSION 值匹配(并且它报告版本 2 而不是 1)。

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

我不禁认为这可能是由于运行时链接器对符号的解析存在一些冲突造成的。我尝试了很多事情,比如尝试链接 libsome2.so ,以便所有符号都变为 symbol@@VER_2 (我仍然对此感到困惑,因为命令 < code>nm -CD libsome2.so 仍然将符号列为 symbol 而不是 symbol@@VER_2)...似乎没有任何作用!帮助!!!!!!

编辑:我应该早些时候提到过,但有问题的应用程序是 Firefox,而 libsome1.so 是它附带的 libsqlite3.so。我不太有重新编译它们的选择。此外,使用版本脚本来隐藏符号似乎是目前唯一的解决方案。那么当符号被隐藏时到底会发生什么呢?他们是否成为 SO 的“本地”人员? rtld 不知道它们的存在吗?当导出函数引用隐藏符号时会发生什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冬天旳寂寞 2024-10-19 02:34:57

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文