[PATCH v2 0/2] MR5809: Draft: winecrt0, msvcrt: Implement static constructor support.
-- v2: msvcrt: Implement static constructors support. winecrt0: Implement static constructors support. https://gitlab.winehq.org/wine/wine/-/merge_requests/5809
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winecrt0/crt_dllmain.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dlls/winecrt0/crt_dllmain.c b/dlls/winecrt0/crt_dllmain.c index 181760c884a..56660e55097 100644 --- a/dlls/winecrt0/crt_dllmain.c +++ b/dlls/winecrt0/crt_dllmain.c @@ -25,8 +25,37 @@ #include "windef.h" #include "winbase.h" +#if defined(_MSC_VER) +#define _CRTALLOC(x) __declspec(allocate(x)) +#elif defined(__GNUC__) +#define _CRTALLOC(x) __attribute__((section(x))) +#else +#define _CRTALLOC(x) static /* unsupported */ +#endif + +_CRTALLOC(".CRT$XIA") void (*__xi_a)(void) = 0; +_CRTALLOC(".CRT$XIZ") void (*__xi_z)(void) = 0; +_CRTALLOC(".CRT$XCA") void (*__xc_a)(void) = 0; +_CRTALLOC(".CRT$XCZ") void (*__xc_z)(void) = 0; + +#if defined(__GNUC__) +void (*__CTOR_LIST__)(void) __attribute__((weak)) = 0; +void (*__DTOR_LIST__)(void) __attribute__((weak)) = 0; +#endif + +static void _CRT_INIT(void) +{ + void (**ctor)(void); + if ((ctor = &__xi_a)) while (++ctor != &__xi_z && *ctor) (*ctor)(); + if ((ctor = &__xc_a)) while (++ctor != &__xc_z && *ctor) (*ctor)(); +#if defined(__GNUC__) + if ((ctor = &__CTOR_LIST__) && *ctor == (void *)-1) while (++ctor != &__DTOR_LIST__ && *ctor) (*ctor)(); +#endif +} + BOOL WINAPI DllMainCRTStartup( HINSTANCE inst, DWORD reason, void *reserved ) { + if (reason == DLL_PROCESS_ATTACH) _CRT_INIT(); return DllMain( inst, reason, reserved ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5809
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/msvcrt/crt_main.c | 29 +++++++++++++++++++++++++++++ dlls/msvcrt/crt_wmain.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/dlls/msvcrt/crt_main.c b/dlls/msvcrt/crt_main.c index eb785e30bb0..b388489e704 100644 --- a/dlls/msvcrt/crt_main.c +++ b/dlls/msvcrt/crt_main.c @@ -30,6 +30,34 @@ #include "winbase.h" #include "winternl.h" +#if defined(_MSC_VER) +#define _CRTALLOC(x) __declspec(allocate(x)) +#elif defined(__GNUC__) +#define _CRTALLOC(x) __attribute__((section(x))) +#else +#define _CRTALLOC(x) static /* unsupported */ +#endif + +_CRTALLOC(".CRT$XIA") void (*__xi_a)(void) = 0; +_CRTALLOC(".CRT$XIZ") void (*__xi_z)(void) = 0; +_CRTALLOC(".CRT$XCA") void (*__xc_a)(void) = 0; +_CRTALLOC(".CRT$XCZ") void (*__xc_z)(void) = 0; + +#if defined(__GNUC__) +void (*__CTOR_LIST__)(void) __attribute__((weak)) = 0; +void (*__DTOR_LIST__)(void) __attribute__((weak)) = 0; +#endif + +static void _CRT_INIT(void) +{ + void (**ctor)(void); + if ((ctor = &__xi_a)) while (++ctor != &__xi_z && *ctor) (*ctor)(); + if ((ctor = &__xc_a)) while (++ctor != &__xc_z && *ctor) (*ctor)(); +#if defined(__GNUC__) + if ((ctor = &__CTOR_LIST__) && *ctor == (void *)-1) while (++ctor != &__DTOR_LIST__ && *ctor) (*ctor)(); +#endif +} + int __cdecl main(int argc, char **argv, char **env); static const IMAGE_NT_HEADERS *get_nt_header( void ) @@ -55,6 +83,7 @@ int __cdecl mainCRTStartup(void) #endif _set_app_type(get_nt_header()->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ? _crt_gui_app : _crt_console_app); + _CRT_INIT(); ret = main(argc, argv, env); exit(ret); diff --git a/dlls/msvcrt/crt_wmain.c b/dlls/msvcrt/crt_wmain.c index 79755d1a6e9..38be3ee5942 100644 --- a/dlls/msvcrt/crt_wmain.c +++ b/dlls/msvcrt/crt_wmain.c @@ -30,6 +30,34 @@ #include "winbase.h" #include "winternl.h" +#if defined(_MSC_VER) +#define _CRTALLOC(x) __declspec(allocate(x)) +#elif defined(__GNUC__) +#define _CRTALLOC(x) __attribute__((section(x))) +#else +#define _CRTALLOC(x) static /* unsupported */ +#endif + +_CRTALLOC(".CRT$XIA") void (*__xi_a)(void) = 0; +_CRTALLOC(".CRT$XIZ") void (*__xi_z)(void) = 0; +_CRTALLOC(".CRT$XCA") void (*__xc_a)(void) = 0; +_CRTALLOC(".CRT$XCZ") void (*__xc_z)(void) = 0; + +#if defined(__GNUC__) +void (*__CTOR_LIST__)(void) __attribute__((weak)) = 0; +void (*__DTOR_LIST__)(void) __attribute__((weak)) = 0; +#endif + +static void _CRT_INIT(void) +{ + void (**ctor)(void); + if ((ctor = &__xi_a)) while (++ctor != &__xi_z && *ctor) (*ctor)(); + if ((ctor = &__xc_a)) while (++ctor != &__xc_z && *ctor) (*ctor)(); +#if defined(__GNUC__) + if ((ctor = &__CTOR_LIST__) && *ctor == (void *)-1) while (++ctor != &__DTOR_LIST__ && *ctor) (*ctor)(); +#endif +} + int __cdecl wmain(int argc, WCHAR **argv, WCHAR **env); static const IMAGE_NT_HEADERS *get_nt_header( void ) @@ -55,6 +83,7 @@ int __cdecl wmainCRTStartup(void) #endif _set_app_type(get_nt_header()->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ? _crt_gui_app : _crt_console_app); + _CRT_INIT(); ret = wmain(argc, argv, env); exit(ret); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5809
Completely unsure how to do that properly but it would be useful, to support C++ code build with Wine CRT. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_72654
Is there a reason for not using `_initterm(_e)`? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_73752
For C++ DLLs we need to handle destructors as well, otherwise they won't clean up properly on DLL detach and lead to subtle crashes depending on app logic. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_73754
On Wed Jun 19 16:43:06 2024 +0000, Jinoh Kang wrote:
For C++ DLLs we need to handle destructors as well, otherwise they won't clean up properly on DLL detach and lead to subtle crashes depending on app logic. As far as I understand, except for GNU `__attribute__((destructor))`, the cleanup is registered with `atexit` instead, so it doesn't look like it needs destructors support? MinGW runtime doesn't seem to have them (or maybe I just didn't find them).
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_73755
On Wed Jun 19 16:43:56 2024 +0000, Rémi Bernon wrote:
As far as I understand, except for GNU `__attribute__((destructor))`, the cleanup is registered with `atexit` instead, so it doesn't look like it needs destructors support? MinGW runtime doesn't seem to have them (or maybe I just didn't find them). Sure but `atexit` is process-global right? IIUC our DLL crt0 doesn't provide its own module-local atexit. Calling unloaded DLL functions at process exit will UAF.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_73756
On Wed Jun 19 16:47:22 2024 +0000, Jinoh Kang wrote:
Sure but Wine's currently linked `atexit` is process-global right? IIUC our DLL crt0 doesn't provide its own module-local atexit. Calling unloaded DLL functions at process exit will UAF. https://learn.microsoft.com/en-us/cpp/c-runtime-library/dllonexit?view=msvc-... looks like a good indicator that Windows does something on DLL detach. I'd say either MinGW is wrong or you didn't find it.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_73757
On Thu Jun 20 10:52:21 2024 +0000, Jinoh Kang wrote:
Is there a reason for not using `_initterm(_e)`? I didn't know it existed, but then it's not very easy to pull in: some DLLs like kernel32, kernelbase, the CRT themselves, etc... don't link with msvcrt.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_73824
On Thu Jun 20 12:01:33 2024 +0000, Rémi Bernon wrote:
I didn't know it existed, but then it's not very easy to pull in: some DLLs like kernel32, kernelbase, the CRT themselves, etc... don't link with msvcrt. Ah, thanks for your reply.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_73825
MinGW runtime doesn't seem to have them (or maybe I just didn't find them).
See `__do_global_dtors`. It's registered using `atexit`, which is a static function that, in case of DLLs, executes on `PROCESS_DETACH`. Also, we currently allow exchanging static libraries between MSVC and MinGW targets (so you may build Wine in one mode and use it to build with `winegcc` for the other target). This may get tricky as we extend static libraries, but I think it would be nice to keep if we can. For that, using `__GNUC__` like you do can't work. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5809#note_74195
participants (3)
-
Jacek Caban (@jacek) -
Jinoh Kang (@iamahuman) -
Rémi Bernon