There are several motivations to enable ctor/dtor support:
1. ASan. This is not just about my wine-asan work, this is important for @bernhardu's PE asan work as well. The compiler generates ctors that poisons memory around global variables so misuses of them can be caught. This is the same both of our implementations of ASan. 2. Building third-party codebases against wine's CRT. This is not necessary for mingw-gcc or llvm-mingw, but the MSVC frontend of clang is another option for cross-compiling to Windows. However right now that requires Windows SDK. Bringing wine CRT to the point of being functional enough will give us another option. Could be useful for things like Proton. 3. (Controversial) Many dlls perform init/deinit tasks in `DllMain`. Some of them might benefit from a conversion to ctor/dtor.
Since nothing in wine uses ctor/dtor right now, this change shouldn't have any impact by itself.
-- v2: msvcrt: Run ctors and dtors from mainCRTStartup.
From: Yuxuan Shui yshui@codeweavers.com
--- dlls/winecrt0/crt_dllmain.c | 63 +++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)
diff --git a/dlls/winecrt0/crt_dllmain.c b/dlls/winecrt0/crt_dllmain.c index 181760c884a..6baca232e70 100644 --- a/dlls/winecrt0/crt_dllmain.c +++ b/dlls/winecrt0/crt_dllmain.c @@ -22,11 +22,74 @@
#include <stdarg.h> #include <stdio.h> +#include <process.h> #include "windef.h" #include "winbase.h"
+#if defined(__GNUC__) +/* Reference: mingw-w64-crt: crt/gccmain.c */ +typedef void (*fnptr)(void); +extern fnptr __CTOR_LIST__[]; +extern fnptr __DTOR_LIST__[]; +#elif defined(_MSC_VER) +/* Sections named .CRT$??? in objects files are automatically merged into .CRT in the + * final binary during linking, sorted by the section names alphabetically. The names + * don't have significance to the linker but conventions do apply. */ +#pragma section(".CRT$XCA", read, write) +#pragma section(".CRT$XCZ", read, write) +#pragma section(".CRT$XTA", read, write) +#pragma section(".CRT$XTZ", read, write) +#pragma comment(linker, "/merge:.CRT=.rdata") +__declspec(allocate(".CRT$XCA")) _PVFV __xc_a[] = { NULL }; +__declspec(allocate(".CRT$XCZ")) _PVFV __xc_z[] = { NULL }; +__declspec(allocate(".CRT$XTA")) _PVFV __xt_a[] = { NULL }; +__declspec(allocate(".CRT$XTZ")) _PVFV __xt_z[] = { NULL }; +#endif + +static void do_global_ctors_dtors( DWORD reason ) +{ +#if defined(__GNUC__) + if (reason == DLL_PROCESS_ATTACH) + { + ULONG_PTR nfns = (ULONG_PTR)__CTOR_LIST__[0], i; + if (nfns == (ULONG_PTR)-1) + for (nfns = 0; __CTOR_LIST__[nfns + 1]; nfns++); + for (i = nfns; i >= 1; i--) __CTOR_LIST__[i](); + } + else if (reason == DLL_PROCESS_DETACH) + { + SIZE_T i; + for (i = 1; __DTOR_LIST__[i]; i++) __DTOR_LIST__[i](); + } +#elif defined(_MSC_VER) + if (reason == DLL_PROCESS_ATTACH) + { + fnptr *current = __xc_a; + + while (current < __xc_z) + { + if (*current) + (*current)(); + current++; + } + } + else if (reason == DLL_PROCESS_DETACH) + { + fnptr *current = __xt_a; + + while (current < __xt_z) + { + if (*current) + (*current)(); + current++; + } + } +#endif +} + BOOL WINAPI DllMainCRTStartup( HINSTANCE inst, DWORD reason, void *reserved ) { + do_global_ctors_dtors( reason ); return DllMain( inst, reason, reserved ); }
From: Yuxuan Shui yshui@codeweavers.com
--- dlls/msvcr100/Makefile.in | 1 + dlls/msvcr110/Makefile.in | 1 + dlls/msvcr120/Makefile.in | 1 + dlls/msvcr70/Makefile.in | 1 + dlls/msvcr71/Makefile.in | 1 + dlls/msvcr80/Makefile.in | 1 + dlls/msvcr90/Makefile.in | 1 + dlls/msvcrt/Makefile.in | 1 + dlls/msvcrt/crt_init.c | 49 +++++++++++++++++++++++++++++++++++++ dlls/msvcrt/crt_main.c | 2 ++ dlls/msvcrt/crt_wmain.c | 2 ++ dlls/ucrtbase/Makefile.in | 1 + dlls/winecrt0/crt_dllmain.c | 4 +-- 13 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 dlls/msvcrt/crt_init.c
diff --git a/dlls/msvcr100/Makefile.in b/dlls/msvcr100/Makefile.in index a0a3f64d6bf..34182e69f19 100644 --- a/dlls/msvcr100/Makefile.in +++ b/dlls/msvcr100/Makefile.in @@ -10,6 +10,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/msvcr110/Makefile.in b/dlls/msvcr110/Makefile.in index e6798427795..fdbcba054d4 100644 --- a/dlls/msvcr110/Makefile.in +++ b/dlls/msvcr110/Makefile.in @@ -10,6 +10,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/msvcr120/Makefile.in b/dlls/msvcr120/Makefile.in index b233753fa2e..3465d77a31e 100644 --- a/dlls/msvcr120/Makefile.in +++ b/dlls/msvcr120/Makefile.in @@ -10,6 +10,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/msvcr70/Makefile.in b/dlls/msvcr70/Makefile.in index 9413738ae1f..be93d88764b 100644 --- a/dlls/msvcr70/Makefile.in +++ b/dlls/msvcr70/Makefile.in @@ -9,6 +9,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/msvcr71/Makefile.in b/dlls/msvcr71/Makefile.in index 6e0b855cac3..c59ce97e8e4 100644 --- a/dlls/msvcr71/Makefile.in +++ b/dlls/msvcr71/Makefile.in @@ -9,6 +9,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/msvcr80/Makefile.in b/dlls/msvcr80/Makefile.in index 2a84383f79d..78accf161e9 100644 --- a/dlls/msvcr80/Makefile.in +++ b/dlls/msvcr80/Makefile.in @@ -9,6 +9,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/msvcr90/Makefile.in b/dlls/msvcr90/Makefile.in index d476d2e3080..3dfc080e554 100644 --- a/dlls/msvcr90/Makefile.in +++ b/dlls/msvcr90/Makefile.in @@ -9,6 +9,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/msvcrt/Makefile.in b/dlls/msvcrt/Makefile.in index aa068b62e51..a4023568d71 100644 --- a/dlls/msvcrt/Makefile.in +++ b/dlls/msvcrt/Makefile.in @@ -9,6 +9,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/msvcrt/crt_init.c b/dlls/msvcrt/crt_init.c new file mode 100644 index 00000000000..d3957ce409e --- /dev/null +++ b/dlls/msvcrt/crt_init.c @@ -0,0 +1,49 @@ +/* Utility functions for calling MSVC/MingW ctors & dtors from mainCRTStartup. */ + +#if 0 +#pragma makedep implib +#endif + +#include <process.h> +#include <stdlib.h> +#include "minwindef.h" + +#if defined(__GNUC__) +/* Reference: mingw-w64-crt: crt/gccmain.c */ +typedef void (*fnptr)(void); +extern fnptr __CTOR_LIST__[]; +extern fnptr __DTOR_LIST__[]; +#elif defined(_MSC_VER) +extern _PVFV __xc_a[] = { NULL }; +extern _PVFV __xc_z[] = { NULL }; +extern _PVFV __xt_a[] = { NULL }; +extern _PVFV __xt_z[] = { NULL }; +#endif + +static __cdecl void do_global_dtors(void) +{ +#if defined(__GNUC__) + SIZE_T i; + for (i = 1; __DTOR_LIST__[i]; i++) __DTOR_LIST__[i](); +#elif defined(_MSC_VER) + _initterm(__xt_a, __xt_z); +#endif +} + +void do_global_ctors(void) +{ +#if defined(__GNUC__) + ULONG_PTR nfns = (ULONG_PTR)__CTOR_LIST__[0], i; + if (nfns == (ULONG_PTR)-1) + for (nfns = 0; __CTOR_LIST__[nfns + 1]; nfns++); + for (i = nfns; i >= 1; i--) __CTOR_LIST__[i](); +#elif defined(_MSC_VER) + _initterm(__xc_a, __xc_z); +#endif + +#ifdef _UCRT + _crt_atexit(do_global_dtors); +#else + _onexit((_onexit_t)do_global_dtors); +#endif +} diff --git a/dlls/msvcrt/crt_main.c b/dlls/msvcrt/crt_main.c index eb785e30bb0..5eb9e5032a0 100644 --- a/dlls/msvcrt/crt_main.c +++ b/dlls/msvcrt/crt_main.c @@ -31,6 +31,7 @@ #include "winternl.h"
int __cdecl main(int argc, char **argv, char **env); +void do_global_ctors( void );
static const IMAGE_NT_HEADERS *get_nt_header( void ) { @@ -54,6 +55,7 @@ int __cdecl mainCRTStartup(void) __getmainargs(&argc, &argv, &env, 0, &new_mode); #endif _set_app_type(get_nt_header()->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ? _crt_gui_app : _crt_console_app); + do_global_ctors();
ret = main(argc, argv, env);
diff --git a/dlls/msvcrt/crt_wmain.c b/dlls/msvcrt/crt_wmain.c index 79755d1a6e9..71cc0e48ec7 100644 --- a/dlls/msvcrt/crt_wmain.c +++ b/dlls/msvcrt/crt_wmain.c @@ -31,6 +31,7 @@ #include "winternl.h"
int __cdecl wmain(int argc, WCHAR **argv, WCHAR **env); +void do_global_ctors(void);
static const IMAGE_NT_HEADERS *get_nt_header( void ) { @@ -54,6 +55,7 @@ int __cdecl wmainCRTStartup(void) __wgetmainargs(&argc, &argv, &env, 0, &new_mode); #endif _set_app_type(get_nt_header()->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ? _crt_gui_app : _crt_console_app); + do_global_ctors();
ret = wmain(argc, argv, env);
diff --git a/dlls/ucrtbase/Makefile.in b/dlls/ucrtbase/Makefile.in index a3bb54750af..1bd1073dcf1 100644 --- a/dlls/ucrtbase/Makefile.in +++ b/dlls/ucrtbase/Makefile.in @@ -9,6 +9,7 @@ SOURCES = \ console.c \ cpp.c \ crt_gccmain.c \ + crt_init.c \ crt_main.c \ crt_winmain.c \ crt_wmain.c \ diff --git a/dlls/winecrt0/crt_dllmain.c b/dlls/winecrt0/crt_dllmain.c index 6baca232e70..042ff65f337 100644 --- a/dlls/winecrt0/crt_dllmain.c +++ b/dlls/winecrt0/crt_dllmain.c @@ -64,7 +64,7 @@ static void do_global_ctors_dtors( DWORD reason ) #elif defined(_MSC_VER) if (reason == DLL_PROCESS_ATTACH) { - fnptr *current = __xc_a; + _PVFV *current = __xc_a;
while (current < __xc_z) { @@ -75,7 +75,7 @@ static void do_global_ctors_dtors( DWORD reason ) } else if (reason == DLL_PROCESS_DETACH) { - fnptr *current = __xt_a; + _PVFV *current = __xt_a;
while (current < __xt_z) {