crt: Do not use atexit() for calling gcc global destructors in DLL builds

Function atexit() for DLL libraries is provided by mingw-w64, which is
statically linked on demand when needed.

Global destructors for DLL libraries are currently called via first
registered DLL atexit callback and atexit callbacks are executed explicitly
from the DLL entry point (for process detach event) in reverse order.

Execution of global destructors does not require DLL atexit support, so
call them explicitly after the invocation of atexit callbacks.

Provide two new functions __mingw_dll_do_global_ctors() and
__mingw_dll_do_global_dtors() which are suitable only for DLL builds.

__mingw_dll_do_global_ctors() is doing same thing as __main() except it
does not register atexit callback for dtors. It contains guard which
prevents executing globacl constructor multiple times.

__mingw_dll_do_global_dtors() is doing exactly same thing as
atexit callback __do_global_dtors(), just is called explictly.

Both functions __mingw_dll_do_global_ctors() and __mingw_dll_do_global_dtors()
must be separated from the compilation unit which provides __main symbol to
prevent linker referencing the atexit symbol. For this purpose provide
these two new functions via mingw_dll_ctors_dtors.c compilation unit.
And to prevent code duplicate at source level, define its functionality
directly in the gccmain.c with the preprocessor condition.

Signed-off-by: LIU Hao <lh_mouse@126.com>
4 files changed