Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When exactly is gcc __attribute__((constructor)) run?

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:

  • libA has the constructor
  • libB also has a constructor
  • libC depends on libA and libB
  • program depends on libA
  • program links libC via dlopen()

Now, when I run the program:

  • libA's constructor gets run before main() starts
  • libB's constructor gets run by dlopen()

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?)

like image 561
che Avatar asked Jan 09 '14 14:01

che


1 Answers

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.

like image 115
ninjalj Avatar answered Oct 05 '22 02:10

ninjalj