我正在尝试更多地了解 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以使所有符号都指向symbol@@VER_2(我仍然对此感到困惑,因为该命令nm -CD libsome2.so仍然将符号列为symbol而不是symbol@@VER_2)......似乎没有任何作用!帮助!!!!!!
编辑:我应该在前面提到它,但有问题的应用程序是 Firefox,并且libsome1.so是libsqlite3.so随它一起提供的。我没有重新编译它们的选项。此外,使用版本脚本隐藏符号似乎是目前唯一的解决方案。那么当符号被隐藏时会发生什么呢?他们会成为 SO 的“本地人”吗?rtld 不知道它们的存在吗?当导出的函数引用隐藏符号时会发生什么?