使用一些相同的符号链接两个共享库

发布于 2024-11-18 01:55:39 字数 504 浏览 1 评论 0原文

我链接了两个不同的共享库。这两个库都定义了一些共享名称但具有不同实现的符号。我不能让每个库都使用自己的实现而不是另一个库。

例如,两个库都定义了各自在内部调用的全局函数 bar()。库一从 foo1() 调用它,库二从 foo2() 调用它。

Lib1.so:

T bar
T foo1()     // calls bar()

Lib2.so:

T bar
T foo2()     // calls bar()

如果我将应用程序链接到 Lib1.so,然后链接到 Lib2.so,即使在调用 foo2() 时也会调用 Lib1.so 的 bar 实现。另一方面,如果我将应用程序链接到 Lib2.so,然后链接到 Lib1.so,则始终从 Lib2.so 调用 bar。

有没有办法让一个库总是比任何其他库更喜欢自己的实现?

I link with two different shared libraries. Both libraries define some symbols that share a name but have different implementations. I can't make each library use its own implementation over the other.

For example, both libraries define a global function bar() that each calls internally. Library one calls it from foo1() and library two calls it from foo2().

Lib1.so:

T bar
T foo1()     // calls bar()

Lib2.so:

T bar
T foo2()     // calls bar()

If I link my application against Lib1.so and then Lib2.so the bar implementation from Lib1.so is called even when calling foo2(). If on the other hand, I link my application against Lib2.so and then Lib1.so, then bar is always called from Lib2.so.

Is there a way to make a library always prefer its own implementation above any other library?

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

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

发布评论

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

评论(3

小傻瓜 2024-11-25 01:55:39

有多种方法可以解决此问题:

  • -Bsymbolic-Bsymbolic-functions 传递给链接器。这具有全局效果:对可以解析为库中符号的全局符号(具有 -Bsymbolic-functions 的函数类型)的每个引用都会解析为该符号。这样,您就失去了使用 LD_PRELOAD 对这些符号进行内部库调用的能力。 符号仍会导出,因此可以从库外部引用它们。

  • 使用版本脚本将符号标记为库的本地,例如使用类似:{local: bar;}; 和将 --version-script=versionfile 传递给链接器。 符号导出。

  • 用适当的可见性标记符号(GCC 可见性信息页面),可以是隐藏内部受保护受保护可见性符号导出为.protected隐藏符号为 导出,并且您妥协不从库外部调用它们,即使是通过函数指针间接调用它们。

您可以使用 objdump -T 来检查导出了哪些符号。

There are several ways to solve this:

  • Pass -Bsymbolic or -Bsymbolic-functions to the linker. This has a global effect: every reference to a global symbol (of function type for -Bsymbolic-functions) that can be resolved to a symbol in the library is resolved to that symbol. With this you lose the ability to interpose internal library calls to those symbols using LD_PRELOAD. The symbols are still exported, so they can be referenced from outside the library.

  • Use a version script to mark symbols as local to the library, e.g. use something like: {local: bar;}; and pass --version-script=versionfile to the linker. The symbols are not exported.

  • Mark symbols with an approppiate visibility (GCC info page for visibility), which will be either hidden, internal, or protected. protected visibility symbols are exported as .protected, hidden symbols are not exported, and internal symbols are not exported and you compromise not to call them from outside the library, even indirectly through function pointers.

You can check which symbols are exported with objdump -T.

小姐丶请自重 2024-11-25 01:55:39

您必须创建两个“包装器”共享库,每个现有库一个。每个都应该使用 --dynamic-list 构建,该列表仅列出定义 API 的一些不冲突的符号。您还需要 -Bsymbolic 以避免任何全局组合。

通过 dlopen 使用合适的选项访问生成的库可能会压力更小。

You will have to create two 'wrapper' shared libs, one for each of your existing libs. Each one should be built with a --dynamic-list that lists only a few non-conflicting symbols that define an API. You will also need -Bsymbolic to avoid any global combination.

It might be less stressful to access the resulting libs via dlopen with suitable options, as well.

错爱 2024-11-25 01:55:39

解决这个问题的另一种方法是使用宏来更改命名空间。

先决条件

  • 所有元素(函数、类、全局变量……)都位于命名空间中。
  • 该库并不严重依赖标头中的宏。

解决方案

  • 编译库时,使用命名空间名称定义宏以将其定义为不同的内容。例如,如果命名空间为 LibNS,则对一种情况使用 -DLibNS=LibNSv1,对另一种情况使用 -DLibNS=LibNSv2
  • 代码中使用库时,根据自己的实际情况定义宏;

    <前><代码>#define LibNS LibNSv1
    #include“my_lib.h”
    #undef LibNS

使用此解决方案而不是其他解决方案的原因

  • 当在头文件(例如模板、内联等)中(至少部分)使用有问题的库时;当您将它们包含在可执行文件的代码中时,解析器不知道应该从 Lib1.so 还是 Lib2.so 调用这些函数。
  • 您的编译器对其他解决方案的支持很差/不支持(我们的 intel/amd 32/64 位 CPU 不应该发生这种情况,但从 Google 搜索看来,其他一些平台可能也存在问题)。

潜在问题

  • 在可执行文件的一个 cpp 文件中使用这两个版本可能会出现问题; #include "my_lib.h" 可能使用宏来防止多重包含并取消定义它们以避免这可能会导致许多不同的问题(库作者将来可能会更改宏名称,标头定义了一些其他宏等)。
  • 名称 LibNS 可能用于库中的其他内容(变量、函数等);在这种情况下,该名称也将更改为 LibNSv1LibNSv2。这可能会导致其他问题,具体取决于库及其使用方式。

注释

  • 这并不意味着取代当前接受的答案(来自 ninjalj;随意复制粘贴它),而是用另一种方法扩展它。
  • 我发布这个答案的主要原因是我今天遇到了这个问题,但由于头文件中存在有问题的代码,答案没有帮助。
  • 我的来源:https://spin.atomicobject。 com/2014/06/03/static-linking-c-plus-plus/

Another way to solve this problem is using macro to change namespace.

Prerequisites

  • All elements (functions, classes, global variables, ...) are in a namespace.
  • The library doesn't heavily depend on macros in headers.

Solution

  • When compiling the library, define macro with namespace name to define it to something different. For example if the namespace is LibNS, use -DLibNS=LibNSv1 for one case and -DLibNS=LibNSv2 for the other.
  • When using libraries in the code, define macro according your current situation;

    #define LibNS LibNSv1
    #include "my_lib.h"
    #undef LibNS
    

Reasons why use this instead of other solutions

  • When the problematic library is used (at least partially) in header files (for example templates, inlines, ...); when you include them in your executable's code, resolver doesn't have idea whether these functions should be called from Lib1.so or Lib2.so.
  • Your compiler has poor/none support for other solutions (shouldn't happen with our intel/amd 32/64 bit CPUs, but it seems from Google search that some other platforms might have the problem).

Potential problems

  • It might be problematic to use both version in one cpp file of your executable; #include "my_lib.h" probably uses macro to protect against multiple-inclusion and undefining them to avoid this might cause lots of different problems (library author might change the macro name in the future, header defines some other macros, etc.).
  • The name LibNS might be used for something else in the library (variable, function, etc.); in that case, this name will be also changed to LibNSv1 or LibNSv2. This might lead to other problems depending on the library and how it's used.

Notes

  • This isn't meant to replace currently accepted answer (from ninjalj; feel free to copy-paste it), but extend it with another approach.
  • Main reason why I posted this answer is that I encountered this problem today, but answer didn't help due to problematic code being in header files.
  • My source: https://spin.atomicobject.com/2014/06/03/static-linking-c-plus-plus/
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文