The dynamic objects in a process come from several sources:
DT_NEEDED
for ELF)dlopen
or similar)They can be unloaded explicitly (dlclose
) or implicitly when the process exit
s, 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 dlopen
ed 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.
The algorithm is the same in all cases. After mapping main executable (or dlopen
ed 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.
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