What is dlopen used for under Linux

DllMain on Linux

01 Mar 2020

Windows API users are of course familiar with the global function that the operating system automatically executes when loading and unloading a DLL. (We will ignore the fact that this also happens with every new thread.)

And Linux? Can you force code to be executed in Linux without explicitly calling a function?


An experienced C ++ developer would come up with the idea that “global” objects would be the solution.
Because the standard guarantees that these are constructed before they are called and destroyed after they are exited. So some code in the constructor and destructor and we're done ...

However, there is nothing in the C / C ++ standard about DLLs or SOs, i.e. libraries that are only loaded and unloaded at runtime.

Fortunately, all the compiler manufacturers I know have used this undefined area and filled it out with the following rule:

Global objects are constructed when loading the library before the loading routine (or) returns. And they are also destroyed before the discharge (or) is completed.

Of course, there is no order in which this should be done, except that global data fields are zeroed out before the constructors.

But operating systems don't know anything about C ++ objects, so how does it work internally?

Well, a look at the implementation of the C Runtime will help:

Windows

The system does not actually execute under Windows, it does. And all Windows compilers implement this function automatically with code that goes through the list of global objects and calls their constructors after elementary CRT initialization routines have run through.
Once this is done, the “programmable” is called.

When unloading, the whole thing runs backwards. first calls “our” to then destroy all global objects using the destructor function.

Linux

The ELF format for executable binary files, which is widely used in Linux, contains specifications for special sections (and). If the linker stores functions there, they will be executed one after the other when loading and unloading the library.

In the GCC, you can enter a function in such sections with the attributes and.
Linux itself does not prescribe a binary standard, but this is where the GCC steps in and sets a de facto standard

There is therefore no visible central function (like) that you can implement, but you simply write functions like:

1void __attribute __ ((constructor)) SO_init () 2 {3 / * do some global initialization * / 4} 56void __attribute __ ((destructor)) SO_uninit () 7 {8 / * do some global cleanup * / 9}

The GCC automatically creates corresponding function entries for global C ++ objects.

What do you need that for?

In some (foreign) projects, the prevailing opinion is:

DllMain should not be used as it cannot be ported to Linux.

Well, that's not true.

If possible, you should always try to free resources and break data links before unloading a library.

Of course, a “good” library should offer one and one, but who guarantees us that the user will call these functions at the right time.

Therefore, such specialties should also be carried out when unloading and for everything that has not already been approved.


By the way, a little fun fact by the way:
Somebody tried his hand at being a hacker and created a great documentation on how you can even load and use an EXE file like a DLL.

The topic sounds exciting and I am adding it to my list of “highly interesting” topics.