dlopen respects an ELF binary format mechanism for running code at load time.
There are actually two such mechanisms:
.finis sections, which contain an array of function pointers for
dlcloseto call. Since the sections may not be present at runtime, there are also
DT_FINIdynamic tags which point to the corresponding sections.
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.