Linux shared library global constructors depend on each other

Linux shared library global constructors depend on each other … here is a solution to the problem.

Linux shared library global constructors depend on each other

Operating System Centos 5.6 i686 2.6.18-53.1.4.el5vm
GCC version 4.1.2 20080704 (Red Hat 4.1.2-48).
LD version 2.17.50.0.6-6.el5 20061020

I compiled it like this :
gcc -c -fnon-call-exceptions -fexceptions -Wall -DUNICODE -D_UNICODE -D_REENTRANT -I.

And link in this way:
gcc -lstdc++ -pthread -ldl -lrt –no-relocate -wl,-rpath,$SO_dir -L$SO_DIR $ library

I have 3 libraries and an executable: A.so, B.so, C.so, ElfExec
B.so depends on A.so.
C.so depends on B.so
In the code, A.so has a header through which the functionality A.h is exposed, and B.so has a B.h header in the code that includes the A.h and B features. C.so Include B.h.
in your code
A.h defines a type of static variable K that can be used if and only if the static memory manager in A.so is initialized. The variable K is defined directly in the header in A.h, so its initialization is propagated in the global constructor of all the objects that make up B.so and C.so.

I link everything like this :
gcc “ALL B MODULES”-lstdc++ -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L$SO_DIR A.so
gcc “all C modules” -lstdc++ -pthread -ldl -lrt –no-relocate -wl,-rpath,$SO_DIR -L$SO_DIR B.so
gcc “ALL ElfExec MODULES”-lstdc++ -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L$SO_DIR C.so
I also tried:
gcc “ALL ElfExec MODULES”-lstdc++ -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L$SO_DIR A.so B.so C.so

When you run ElfExec, you get a SIGSEGV because it tries to initialize the variable K before A.so’s static memory manager initializes.
This is because the global constructor of C.so is called before the global constructor of A.so.
If I make an application that only needs B.so ElfExec2
gcc “ALL ElfExec1 MODULES”-lstdc++ -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L$SO_DIR B.so
This works fine.

In the case of ElfExec1, the linker found that it needed to call the global constructor in A.so before calling the global constructor in B.so.
This did not happen in the case of ElfExec.

My solution is to link C.so like this:
gcc “ALL C MODULES”-lstdc++ -pthread -ldl -lrt –no-relocate -Wl,-rpath,$SO_DIR -L$SO_DIR A.so B.so
This makes C.so directly dependent on the A.so.

Is there another way to tell the linker the order of the global constructor calls?

Solution

As you can see, don’t believe that the linker knows better than you. If the order is important, you need to specify the order programmatically. Don’t just try to trick the linker.

If these weren’t libraries, you would do it, right? Constructors/initializers that call each other in the correct order?

My first choice was to design the library with no or no global variables.

If you can’t, my second option is to have every library that needs to initialize global variables have an init method. The consumer of the library needs to call the init method before performing any operations, and the library must attempt to prevent the use/construction before the init is completed correctly. Perhaps making them static to init methods and then setting global pointers to them (K*k) might help that implementation. This should be enough to get the initialization chains together in the correct order.

Finally, if there is a barrier to getting a user of any library (meaning B for A, or C for B, and application for C) to call the init method, you can use a language extension like this for gcc:

extern "C" __attribute__ ((constructor)) void A_lib_ctor()
{
    // ....
}
extern "C" __attribute__ ((destructor)) void A_lib_dtor()
{
    // ....
}

Automate what you need when the library loads. This sacrifices some portability. Probably sacrifice more, the new version of gcc supports constructor (precedence) syntax.

My last option was the complicated step of manually loading the library using dlopen.

The design is better, the most important choices work for you, and the later ones are worse.

Related Problems and Solutions