Search code examples
clinuxlinkerelfdynamic-loading

Symbol conflict in transitive dependencies of two dynamic libraries


I am using two third party dynamic libraries: liba.so and libb.so. They both call a function named common included in another dynamic library, but liba.so should use the one from libsuba.so while libb.so the one from libsubb.so.

I have no access to the source code of these dynamic libraries and I am thus unable to change the function name of one library and recompile it to resolve the conflict.

I am aware that macOS provides a two level namespace that seems to solve the issue, but I didn't found anything similar in ld man pages.

// exe.c
extern void func_a(void);
extern void func_b(void);

void main(void) {
    func_a();
    func_b();
}
// lib(a|b).c
extern void common(void);

void func_(a|b)(void) {
    common();
}
// libsub(a|b).c
#include <stdio.h>

void common(void) {
    printf("Common (A|B)\n");
}
all: exe

exe: exe.c liba.so libb.so
    gcc -L. -Wl,-rpath=. -o $@ $< -la -lb

liba.so: liba.c libsuba.so
    gcc -shared -fPIC -Wl,-rpath=. -L. -o $@ $< -lsuba

libb.so: libb.c libsubb.so
    gcc -shared -fPIC -Wl,-rpath=. -L. -o $@ $< -lsubb

libsub%.so: libsub%.c
    gcc -shared -fPIC -o $@ $<

Is there any way to solve this issue?

Edit: The current output value is:

$ ./exe 
Common A
Common A

and I would like the output to be:

$ ./exe 
Common A
Common B

Solution

  • You should report the issue to the respective vendors of those libraries. I think they are missing namespaces for exported symbols (for sure, if libsuba and libsubb both export a symbol called "common").

    Have you thought about using objcopy --redefine-sym (see this answer)? However, objcopy does not seem to modify the dynamic symbol talbe, rendering this approach useless :(