Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking two shared libraries with some of the same symbols

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?

like image 574
drewag Avatar asked Jun 30 '11 17:06

drewag


People also ask

How are shared libraries linked?

Shared libraries (also called dynamic libraries) are linked into the program in two stages. First, during compile time, the linker verifies that all the symbols (again, functions, variables and the like) required by the program, are either linked into the program, or in one of its shared libraries.

Can shared library be statically linked?

You can't statically link a shared library (or dynamically link a static one).

What is linking static library?

Static Linking and Static Libraries is the result of the linker making copy of all used library functions to the executable file. Static Linking creates larger binary files, and need more space on disk and main memory. Examples of static libraries (libraries which are statically linked) are, . a files in Linux and .

How does linking libraries work?

The libraries are physically loaded into the computer's memory instead and during the linking stage of compilation, only the address in the memory of the library function is added in the final executable file. The physical code itself is located at that address.


1 Answers

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.

like image 156
ninjalj Avatar answered Sep 25 '22 10:09

ninjalj