将两个共享库链接到一些相同的符号

我正试图链接两个不同的共享库。 这两个库定义了一些共享名称但具有不同实现的符号。 我似乎无法find一种方法来使每个图书馆都使用自己的实施。

例如,这两个库定义了一个全局函数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,那么bar总是从Lib2.so中调用。

有没有办法让图书馆总是比其他图书馆更喜欢自己的实现?

有几种方法可以解决这个问题:

  • -Bsymbolic-Bsymbolic-functions传递给链接器。 这具有全局性的作用:每个对可以parsing为库中的符号的全局符号( -Bsymbolic-functions的函数types)的-Bsymbolic-functions被parsing为该符号。 有了这个,你就失去了使用LD_PRELOAD将内部库调用置入这些符号的能力。 这些符号仍然是导出的 ,所以它们可以从库外引用。

  • 使用版本脚本来标记符号为本地的图书馆,例如使用类似于: {local: bar;}; 并将--version-script=versionfile传递给链接器。 符号不会被导出。

  • 标记具有适当可见性的符号( GCC信息页面的可见性 ),将隐藏内部受保护受保护的可见性符号被导出为.protected隐藏的符号不会被导出内部符号不会被导出 ,您不会从库之外调用它们,甚至间接通过函数指针。

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

你将不得不创build两个“包装”共享库,一个用于每个现有的库。 每个应该build立一个 – dynamic列表,只列出了一些定义一个API的非冲突的符号。 您还需要-Bsymbolic来避免任何全局组合。

使用合适的选项通过dlopen访问生成的库也可能不那么紧张。