7

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.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76

1 Answers1

2

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.

yugr
  • 19,769
  • 3
  • 51
  • 96
  • The topological order doesn’t constrain anything mentioned only by `dlopen`. Is that suborder unspecified? – Davis Herring Oct 26 '18 at 14:11
  • @DavisHerring No, if there's no dependency between two libs they may be initialized in arbitrary relative order. Funny enough, I once experimented with fuzzing this ordering and found some bugs in existing programs. – yugr Oct 26 '18 at 15:08
  • I believe the actual ordering picture is a bit more complicated by e.g. `DF_1_INITFIRST` and possibly other flags. – Employed Russian Oct 28 '18 at 17:47
  • @EmployedRussian Yes but GNU loader supports only one `DF_1_INITFIRST` library and `libpthread` already has it so in practice this flag is unusable in normal libs. – yugr Oct 28 '18 at 17:52