einpoklum einpoklum - 2 months ago 9
C++ Question

Does static initialization (and/or other) code get run when dlopen'ing?

When you

dlopen()
a shared object, is there a mechanism for having code in that DLL execute without being called explicitly? Specifically, C++ static initialization code for globals/statics which the caller of
dlopen()
might not know about? I'm pretty sure the answer should be "yes" but I don't remember what mechanism makes that happen, and how to utilize it for running arbitrary code.

Answer

Yes: dlopen respects an ELF binary format mechanism for running code at load time.

There are actually two such mechanisms:

  • An older one uses special .init and .finis sections, which contain an array of function pointers for dlopen and dlclose to call. Since the sections may not be present at runtime, there are also DT_INIT and DT_FINI dynamic tags which point to the corresponding sections.
  • The newer mechanism is .init_array and .fini_array and corresponding DT_INIT_ARRAY, DT_INIT_ARRAYSZ, DT_FINI_ARRAY and DT_FINI_ARRAYSZ dynamic tags.

The difference between the two mechanisms is described here.

Going up to the source code level, if you decorate a C function with __attribute__((constructor)), the compiler will use one of those two mechanisms to make it run when the object is dlopened. The same goes for the construction code for global C++ objects requiring dynamic initialization.