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 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.
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.
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