Linking two shared libraries with some of the same characters

I am linking to two different shared libraries. Both libraries define some characters that have a name but have different implementations. I can not get each library to use its own implementation compared to the other.

For example, both libraries define the global function bar() , which each calls internally. The library calls it from foo1() , and the library two calls it from foo2() .

Lib1.so:

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

Lib2.so:

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

If I attach my application to Lib1.so, and then Lib2.so, then the line call from Lib1.so is called even when foo2() called. If, on the other hand, I associate my application with Lib2.so and then Lib1.so, then bar is always called from Lib2.so.

Is there a way for a library to always prefer its own implementation over any other library?

+44
c gcc unix dynamic-linking shared-libraries
Jun 30 '11 at 17:11
source share
3 answers

There are several ways to solve this problem:

  • Pass -Bsymbolic or -Bsymbolic-functions to the linker. This has a global effect: each reference to a global symbol (such as a function for -Bsymbolic-functions ), which can be resolved to a symbol in the library, is resolved to that symbol. In doing so, you lose the ability to embed calls to the internal library on these characters using LD_PRELOAD. Symbols are still exported , so they can be referenced from outside the library.

  • Use the script version to designate characters as local to the library, for example. use something like: {local: bar;}; and pass --version-script=versionfile to the linker. Characters are not exported.

  • Mark the characters with the corresponding visible visibility ( GCC information page for visibility ), which will be either hidden, or internal, or protected. protected visibility characters are exported as .protected , hidden characters are not exported , and internal characters are not exported and you do not agree to not call them from outside the library, even indirectly using function pointers.

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

+45
Jun 30 '11 at 19:27
source share

You will need to create two โ€œwrappersโ€ of shared libs, one for each of your existing libraries. Each of them must be built using a -dynamic list, which lists only a few non-conflict characters that define the API. You will also need -Bsymbolic to avoid any global combination.

Perhaps it would be less difficult to access the resulting libs via dlopen with the appropriate parameters.

+3
Jun 30 '11 at 17:20
source share

Another way to solve this problem is to use a macro to change the namespace.

Background

  • All elements (functions, classes, global variables, ...) are in the namespace.
  • The library is not heavily dependent on macros in the headers.

Decision

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

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

Reasons why use this instead of other solutions

  • When the problem library is used (at least partially) in header files (for example, templates, inline strings, ...); when you include them in your executable code, the resolver has no idea whether these functions should be called from Lib1.so or Lib2.so.
  • Your compiler has poor support / no support for other solutions (this should not happen with our 32/64-bit Intel / AMD processors, but it seems that a Google search may cause a problem with some other platforms).

Potential problems

  • It may be problematic to use both versions in the same cpp file of your executable; #include "my_lib.h" probably uses a macro to protect it from being included repeatedly, and canceling them to avoid this can cause many different problems (the author of the library may change the name of the macro in the future, the header defines some other macros, etc.) .
  • The name LibNS can be used for something else in the library (variable, function, etc.); in this case, this name will also be changed to LibNSv1 or LibNSv2 . This can lead to other problems depending on the library and how it is used.

Notes

  • This is not intended to replace the currently accepted answer (from ninjalj; feel free to copy and paste it), but extends it with a different approach.
  • The main reason I posted this answer is because I ran into this problem today, but the answer didn't help, since the problematic code is in the header files.
  • My source: https://spin.atomicobject.com/2014/06/03/static-linking-c-plus-plus/
+1
Feb 20 '18 at 10:28
source share



All Articles