Let's say I have an libA.so with GCC constructor.
My program "program" depends on libA.so, so when I run it, libA.so gets opened and its constructor is executed. Now, I also have a module, libC.so, which also depends on libA. I run dlopen("libC.so")
, which loads libC, and according to my experiments, also executes libA's constructor.
Dependencies look like this:
Now, when I run the program:
Apparently, dlopen executes constructors of libraries when they are loaded into memory. Is this specified somewhere, and how does the linker check which libs are already loaded?
(Why I'm asking: On an occassion, I got a constructor executed twice in situation under some not-fully-understood conditions. Am I right in presuming that this was totally broken and should never happen under normal situation?)
For ELF files, __attribute__((constructor))
marked functions are ultimately run from the DT_INIT
(initialization function) tag. Likewise for __attribute((destructor))
and the DT_FINI
(termination function) tag.
Initialization functions are run after relocations are performed, and before returning control to the program, which for program-load-time loaded shared objects means before tranfering control to main()
, and for runtime loaded shared objects could probably be interpreted as before returning from dlopen()
. Initialization functions from DT_NEEDED
shared objects are run before the initialization function in the current shared object.
Termination functions are run from atexit()
handlers, after user atexit()
handlers. Termination functions are run in reverse order of their corresponding initialization functions.
The ELF standard notes the following:
The dynamic linker ensures that it will not execute any initialization or termination functions more than once.
If you are seeing otherwise, then it's a bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With