Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In what order are shared libraries initialized and finalized?

The dynamic objects in a process come from several sources:

  1. The executable itself
  2. Any libraries it requires (DT_NEEDED for ELF)
  3. Libraries loaded explicitly (dlopen or similar)
  4. Any libraries required by such explicit loads

They can be unloaded explicitly (dlclose) or implicitly when the process exits, running their finalization (atexit functions, static-duration destructors in C++, and __attribute__((destructor)) functions) in either case.

What determines the order in which the dynamic objects are initialized and finalized in these various cases? Obviously the last dlclose for a library unloads it immediately, but what about its tree of dependencies (some of which might also be dependencies of other loaded libraries)? What if a library is dlopened but then unloaded by exit?

I tend to expect the usual reverse order of initialization, but maybe there's a difference between DT_NEEDED and dlopen since "plugins" are loaded by the latter and might be expected to depend on the executable's data rather than the other way around.

like image 788
Davis Herring Avatar asked Nov 07 '22 00:11

Davis Herring


1 Answers

The algorithm is the same in all cases. After mapping main executable (or dlopened library) dynamic linker will execute initialization functions in topological order so that dependencies are initialized before dependents. Note that this may leave the order unspecified in some cases and linker makes arbitrary choice there.

Library destructors are registered in one of it's constructors (via call to __cxa_atexit). Registrarion is performed by prepending cumulative library dtor function to a special list inside Glibc. On exit, the list is traversed in forward direction so dependent destructors will be called before their dependencies.

like image 104
yugr Avatar answered Nov 17 '22 08:11

yugr