mcfgthread [4] has been designed to conform to these standards, in startup and termination behavior, by providing these functions:
```
void __MCF_exit(int status); // for `exit` (C89)
void __MCF_quick_exit(int status); // for `quick_exit` (C99)
void __MCF_Exit(int status); // for `_Exit` (C99) and `_exit` (POSIX)
void __MCF_cxa_finalize(void* dso); // for `__cxa_finalize` (Itanium ABI)
int __MCF_atexit(__MCF_atexit_callback atfn); // for `atexit` (C89)
int __MCF_at_quick_exit(__MCF_atexit_callback atfn); // for
`at_quick_exit()` (C99)
int __MCF_cxa_atexit(__MCF_cxa_dtor_union dtor, void* this,
void* dso); // for `__cxa_atexit` (Itanium ABI)
int __MCF_cxa_at_quick_exit(__MCF_cxa_dtor_union dtor, void* this,
void* dso); // for `__cxa_at_quick_exit` (GNU extension)
int __MCF_thread_atexit(__MCF_atexit_callback atfn); // extension
int __MCF_cxa_thread_atexit(__MCF_cxa_dtor_union dtor, void* this,
void* dso); // for `__cxa_thread_atexit` (GNU extension)
int __MCF_cxa_guard_acquire(int64_t* guard); // for `__cxa_guard_acquire`
(Itanium ABI)
void __MCF_cxa_guard_release(int64_t* guard); // for `__cxa_guard_release`
(Itanium ABI)
void __MCF_cxa_guard_abort(int64_t* guard); // for `__cxa_guard_abort`
(Itanium ABI)
```
To be clear about the responsibilities of the C and C++ runtime libraries, we
take Linux as an example:
* `exit()`, `quick_exit()`, `_Exit()` and `__cxa_finalize()` are provided
by libc.
* `atexit()` and `at_quick_exit()` are linked statically, as wrappers for
`__cxa_atexit()` and `__cxa_at_quick_exit()`, respectively; the latter are
provided by libc.
* `__cxa_thread_atexit()` is provided by libstdc++, as a wrapper for
`__cxa_thread_atexit_impl()` [5]; the latter is provided by libc.
* `__cxa_guard_*()` are provided by libstdc++.
Basing on these facts which we may take as a reference, in order to get standard behaviors, I think
it should be acceptable to provide those functions, which are marked as 'provided by libc', in
mingw-w64 CRT, as static wrappers to those from mcfgthread.
`__cxa_atexit()` and `__cxa_at_quick_exit()` should be provided by the C runtime. If we can't provide them in a DLL (apparently), we may continue to provide them as static ones. This way, the `dso` argument should always reference the DSO handle of the linking module.
There are still some issues left unsolved, however:
* The Itanium ABI specifies that, when the main program calls `exit()`, the
program shall behave like `__cxa_finalize(NULL)` is called; when a shared
library is unloaded, `__cxa_finalize(dso_handle)` shall be called. This
requires overriding the `exit()` function from MSVCRT, as well as
`quick_exit()` from UCRT.
* The Microsoft documentation says that `_cexit()` would flush all open
streams. But I fail to observe such behavior; an explicit call to
`fflush(NULL)` is essential. In the EXE startup code, we must register it
with `__cxa_atexit(fflush, NULL, NULL)` before any user code is executed.
Then the call to `_cexit()` seems unnecessary.
Attached are draft patches for the above, sent for comments only.
[1] https://sourceforge.net/p/mingw-w64/mailman/message/37268447/
[2] https://reviews.llvm.org/D102944
[3] https://itanium-cxx-abi.github.io/cxx-abi/abi.html
[4] https://github.com/lhmouse/mcfgthread
[5]
https://github.com/gcc-mirror/gcc/blob/2eff4fe383a59de94267352e25f77b29d8e6bb42/libstdc%2B%2B-v3/libsupc%2B%2B/atexit_thread.cc#L51
-- Best regards, LIU Hao
From 8efa2a31b22f8ed37a31a4f0acbfa943fa8d65e2 Mon Sep 17 00:00:00 2001 From: LIU Hao <[email protected]> Date: Fri, 7 Oct 2022 22:42:04 +0800 Subject: [PATCH 1/3] crt: Mark `atexit()` as DATA because it's always overridden Signed-off-by: LIU Hao <[email protected]> --- mingw-w64-crt/lib-common/msvcr120_app.def.in | 2 +- mingw-w64-crt/lib32/msvcr120.def.in | 2 +- mingw-w64-crt/lib32/msvcr120d.def.in | 2 +- mingw-w64-crt/lib32/msvcr70.def | 2 +- mingw-w64-crt/lib32/msvcr71.def | 2 +- mingw-w64-crt/lib32/msvcrt10.def | 2 +- mingw-w64-crt/lib32/msvcrt20.def | 2 +- mingw-w64-crt/lib32/msvcrt40.def | 2 +- mingw-w64-crt/lib64/msvcr120.def.in | 2 +- mingw-w64-crt/lib64/msvcr120d.def.in | 2 +- mingw-w64-crt/libarm32/kernelbase.def | 2 +- mingw-w64-crt/libarm32/msvcr110.def | 2 +- mingw-w64-crt/libarm32/msvcr120_clr0400.def | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/mingw-w64-crt/lib-common/msvcr120_app.def.in b/mingw-w64-crt/lib-common/msvcr120_app.def.in index 10cf84d07..ddb407d00 100644 --- a/mingw-w64-crt/lib-common/msvcr120_app.def.in +++ b/mingw-w64-crt/lib-common/msvcr120_app.def.in @@ -2029,7 +2029,7 @@ F_NON_I386(atanf) F_X86_ANY(atanh) F_X86_ANY(atanhf) F_X86_ANY(atanhl) -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib32/msvcr120.def.in b/mingw-w64-crt/lib32/msvcr120.def.in index 98567a956..82adab07b 100644 --- a/mingw-w64-crt/lib32/msvcr120.def.in +++ b/mingw-w64-crt/lib32/msvcr120.def.in @@ -1861,7 +1861,7 @@ atan2 atanh atanhf atanhl -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib32/msvcr120d.def.in b/mingw-w64-crt/lib32/msvcr120d.def.in index 658e5a314..a9552f0b5 100644 --- a/mingw-w64-crt/lib32/msvcr120d.def.in +++ b/mingw-w64-crt/lib32/msvcr120d.def.in @@ -1928,7 +1928,7 @@ atan2 atanh atanhf atanhl -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib32/msvcr70.def b/mingw-w64-crt/lib32/msvcr70.def index 5ec73e781..3d0275339 100644 --- a/mingw-w64-crt/lib32/msvcr70.def +++ b/mingw-w64-crt/lib32/msvcr70.def @@ -709,7 +709,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib32/msvcr71.def b/mingw-w64-crt/lib32/msvcr71.def index 1db6d0b58..796fe52c5 100644 --- a/mingw-w64-crt/lib32/msvcr71.def +++ b/mingw-w64-crt/lib32/msvcr71.def @@ -704,7 +704,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib32/msvcrt10.def b/mingw-w64-crt/lib32/msvcrt10.def index 5a3edf6e6..0265add70 100644 --- a/mingw-w64-crt/lib32/msvcrt10.def +++ b/mingw-w64-crt/lib32/msvcrt10.def @@ -1112,7 +1112,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib32/msvcrt20.def b/mingw-w64-crt/lib32/msvcrt20.def index 48d0487b9..e0e3897ce 100644 --- a/mingw-w64-crt/lib32/msvcrt20.def +++ b/mingw-w64-crt/lib32/msvcrt20.def @@ -1380,7 +1380,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib32/msvcrt40.def b/mingw-w64-crt/lib32/msvcrt40.def index 648f792df..5abc34469 100644 --- a/mingw-w64-crt/lib32/msvcrt40.def +++ b/mingw-w64-crt/lib32/msvcrt40.def @@ -1464,7 +1464,7 @@ asctime asin atan atan2 -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib64/msvcr120.def.in b/mingw-w64-crt/lib64/msvcr120.def.in index 0710c6bfb..a37df574d 100644 --- a/mingw-w64-crt/lib64/msvcr120.def.in +++ b/mingw-w64-crt/lib64/msvcr120.def.in @@ -1803,7 +1803,7 @@ atanf atanh atanhf atanhl -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/lib64/msvcr120d.def.in b/mingw-w64-crt/lib64/msvcr120d.def.in index 4f2d65ee1..98a7b5f1d 100644 --- a/mingw-w64-crt/lib64/msvcr120d.def.in +++ b/mingw-w64-crt/lib64/msvcr120d.def.in @@ -1867,7 +1867,7 @@ atanf atanh atanhf atanhl -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/libarm32/kernelbase.def b/mingw-w64-crt/libarm32/kernelbase.def index 954ea2dc1..d6a487db1 100644 --- a/mingw-w64-crt/libarm32/kernelbase.def +++ b/mingw-w64-crt/libarm32/kernelbase.def @@ -1889,7 +1889,7 @@ _invalid_parameter _onexit _purecall _time64 -atexit +atexit DATA exit hgets hwprintf diff --git a/mingw-w64-crt/libarm32/msvcr110.def b/mingw-w64-crt/libarm32/msvcr110.def index 0b4855db8..e9835df42 100644 --- a/mingw-w64-crt/libarm32/msvcr110.def +++ b/mingw-w64-crt/libarm32/msvcr110.def @@ -1392,7 +1392,7 @@ atan atan2 atan2f atanf -atexit +atexit DATA atof atoi atol diff --git a/mingw-w64-crt/libarm32/msvcr120_clr0400.def b/mingw-w64-crt/libarm32/msvcr120_clr0400.def index a1b3f7f30..a778c7ebf 100644 --- a/mingw-w64-crt/libarm32/msvcr120_clr0400.def +++ b/mingw-w64-crt/libarm32/msvcr120_clr0400.def @@ -1391,7 +1391,7 @@ atan atan2 atan2f atanf -atexit +atexit DATA atof atoi atol -- 2.37.3
From d9f001979ec136f287c8f9d7209a6d9198a062b9 Mon Sep 17 00:00:00 2001 From: LIU Hao <[email protected]> Date: Fri, 7 Oct 2022 22:46:50 +0800 Subject: [PATCH 2/3] crt: Provide wrappers for `*exit()` in libmingwex instead of import libraries This should have no effect on functionality, but allows further customization of them. Signed-off-by: LIU Hao <[email protected]> --- mingw-w64-crt/Makefile.am | 2 +- mingw-w64-crt/crt/exit_wrappers.c | 37 +++++++++++++++++++ .../api-ms-win-crt-runtime-l1-1-0.def.in | 8 ++-- mingw-w64-crt/lib-common/msvcr120_app.def.in | 4 +- mingw-w64-crt/lib-common/msvcrt.def.in | 4 +- mingw-w64-crt/lib-common/ucrtbase.def.in | 8 ++-- mingw-w64-crt/lib32/crtdll.def | 4 +- mingw-w64-crt/lib32/msvcr100.def.in | 4 +- mingw-w64-crt/lib32/msvcr110.def.in | 4 +- mingw-w64-crt/lib32/msvcr120.def.in | 4 +- mingw-w64-crt/lib32/msvcr120d.def.in | 4 +- mingw-w64-crt/lib32/msvcr70.def | 4 +- mingw-w64-crt/lib32/msvcr71.def | 4 +- mingw-w64-crt/lib32/msvcr80.def.in | 4 +- mingw-w64-crt/lib32/msvcr90.def.in | 4 +- mingw-w64-crt/lib32/msvcr90d.def.in | 4 +- mingw-w64-crt/lib32/msvcrt10.def | 4 +- mingw-w64-crt/lib32/msvcrt20.def | 4 +- mingw-w64-crt/lib32/msvcrt40.def | 4 +- mingw-w64-crt/lib64/msvcr100.def.in | 4 +- mingw-w64-crt/lib64/msvcr110.def.in | 4 +- mingw-w64-crt/lib64/msvcr120.def.in | 4 +- mingw-w64-crt/lib64/msvcr120d.def.in | 4 +- mingw-w64-crt/lib64/msvcr80.def.in | 4 +- mingw-w64-crt/lib64/msvcr90.def.in | 4 +- mingw-w64-crt/lib64/msvcr90d.def.in | 4 +- mingw-w64-crt/libarm32/kernelbase.def | 4 +- mingw-w64-crt/libarm32/msvcr110.def | 4 +- mingw-w64-crt/libarm32/msvcr120_clr0400.def | 4 +- 29 files changed, 96 insertions(+), 59 deletions(-) create mode 100644 mingw-w64-crt/crt/exit_wrappers.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 053eab3cf..6dbac2339 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -127,7 +127,7 @@ src_libmingw32=include/oscalls.h include/internal.h include/sect_attribs.h \ crt/usermatherr.c \ crt/xtxtmode.c crt/crt_handler.c \ crt/tlsthrd.c crt/tlsmthread.c crt/tlsmcrt.c \ - crt/cxa_atexit.c crt/cxa_thread_atexit.c crt/tls_atexit.c + crt/cxa_atexit.c crt/cxa_thread_atexit.c crt/tls_atexit.c crt/exit_wrappers.c src_libscrnsave=libsrc/scrnsave.c src_libscrnsavw=libsrc/scrnsave.c diff --git a/mingw-w64-crt/crt/exit_wrappers.c b/mingw-w64-crt/crt/exit_wrappers.c new file mode 100644 index 000000000..714395dec --- /dev/null +++ b/mingw-w64-crt/crt/exit_wrappers.c @@ -0,0 +1,37 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include <stdlib.h> + +/* `exit()`, C89 */ +extern void (*__MINGW_IMP_SYMBOL(exit))(int) __attribute__((__noreturn__)); + +void exit(int status) { + (*__MINGW_IMP_SYMBOL(exit))(status); +} + +/* `_exit()`, POSIX */ +extern void (*__MINGW_IMP_SYMBOL(_exit))(int) __attribute__((__noreturn__)); + +void _exit(int status) { + (*__MINGW_IMP_SYMBOL(_exit))(status); +} + +#ifdef _UCRT +/* `quick_exit()`, C99 */ +extern void (*__MINGW_IMP_SYMBOL(quick_exit))(int) __attribute__((__noreturn__)); + +void quick_exit(int status) { + (*__MINGW_IMP_SYMBOL(quick_exit))(status); +} + +/* `_Exit()`, C99 */ +extern void (*__MINGW_IMP_SYMBOL(_Exit))(int) __attribute__((__noreturn__)); + +void _Exit(int status) { + (*__MINGW_IMP_SYMBOL(_Exit))(status); +} +#endif /* _UCRT */ diff --git a/mingw-w64-crt/lib-common/api-ms-win-crt-runtime-l1-1-0.def.in b/mingw-w64-crt/lib-common/api-ms-win-crt-runtime-l1-1-0.def.in index ea310d426..33e4f5504 100644 --- a/mingw-w64-crt/lib-common/api-ms-win-crt-runtime-l1-1-0.def.in +++ b/mingw-w64-crt/lib-common/api-ms-win-crt-runtime-l1-1-0.def.in @@ -4,7 +4,7 @@ EXPORTS #include "func.def.in" -_Exit +_Exit DATA F_I386(__control87_2) __doserrno __fpe_flt_rounds @@ -42,7 +42,7 @@ _endthread _endthreadex _errno _execute_onexit_table -_exit +_exit DATA F_NON_I386(_fpieee_flt) ; DATA added manually _fpreset DATA @@ -96,7 +96,7 @@ _wcserror_s _wperror _wsystem abort -exit +exit DATA ; Don't use the float env functions from UCRT; fesetround doesn't seem to have ; any effect on the FPU control word as required by other libmingwex math ; routines. @@ -110,7 +110,7 @@ fesetexceptflag DATA fesetround DATA fetestexcept DATA perror -quick_exit +quick_exit DATA raise set_terminate signal diff --git a/mingw-w64-crt/lib-common/msvcr120_app.def.in b/mingw-w64-crt/lib-common/msvcr120_app.def.in index ddb407d00..33f2e9345 100644 --- a/mingw-w64-crt/lib-common/msvcr120_app.def.in +++ b/mingw-w64-crt/lib-common/msvcr120_app.def.in @@ -1080,7 +1080,7 @@ F_ARM32(_execv) F_ARM32(_execve) F_ARM32(_execvp) F_ARM32(_execvpe) -_exit +_exit DATA F_X86_ANY(_exit_app) _expand F_X86_ANY(_fclose_nolock) @@ -2143,7 +2143,7 @@ erfcl erff erfl #endif -exit +exit DATA exp exp2 exp2f diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in b/mingw-w64-crt/lib-common/msvcrt.def.in index 942c4c4eb..d7359f35a 100644 --- a/mingw-w64-crt/lib-common/msvcrt.def.in +++ b/mingw-w64-crt/lib-common/msvcrt.def.in @@ -481,7 +481,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand F_ARM_ANY(_expand_dbg) _fcloseall @@ -1342,7 +1342,7 @@ F_NON_I386(coshf DATA) ctime difftime div -exit +exit DATA exp F_X86_ANY(DATA) F_NON_I386(expf F_X86_ANY(DATA)) F_ARM_ANY(expl == exp) diff --git a/mingw-w64-crt/lib-common/ucrtbase.def.in b/mingw-w64-crt/lib-common/ucrtbase.def.in index a90fd72b7..ae3d3f95a 100644 --- a/mingw-w64-crt/lib-common/ucrtbase.def.in +++ b/mingw-w64-crt/lib-common/ucrtbase.def.in @@ -30,7 +30,7 @@ _CreateFrameInfo F_I386(_CxxThrowException@8) F_NON_I386(_CxxThrowException) F_I386(_EH_prolog) -_Exit +_Exit DATA _FCbuild _FCmulcc _FCmulcr @@ -299,7 +299,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -2305,7 +2305,7 @@ erfcf erfcl F_X86_ANY(DATA) erff erfl F_X86_ANY(DATA) -exit +exit DATA exp F_X86_ANY(DATA) exp2 exp2f @@ -2500,7 +2500,7 @@ putwc putwchar qsort qsort_s -quick_exit +quick_exit DATA raise rand rand_s diff --git a/mingw-w64-crt/lib32/crtdll.def b/mingw-w64-crt/lib32/crtdll.def index fed70ffa6..ab5cd34f3 100644 --- a/mingw-w64-crt/lib32/crtdll.def +++ b/mingw-w64-crt/lib32/crtdll.def @@ -266,7 +266,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fcloseall _fcvt @@ -552,7 +552,7 @@ ctime DATA ;_ctime32 = ctime difftime div -exit +exit DATA exp DATA fabs DATA fclose diff --git a/mingw-w64-crt/lib32/msvcr100.def.in b/mingw-w64-crt/lib32/msvcr100.def.in index 8e8dfb460..0772af371 100644 --- a/mingw-w64-crt/lib32/msvcr100.def.in +++ b/mingw-w64-crt/lib32/msvcr100.def.in @@ -831,7 +831,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1691,7 +1691,7 @@ cos DATA ; If we implement cosh too, we can set it to DATA only. cosh div -exit +exit DATA exp DATA fabs DATA fclose diff --git a/mingw-w64-crt/lib32/msvcr110.def.in b/mingw-w64-crt/lib32/msvcr110.def.in index b864009b6..c0d1a9c1f 100644 --- a/mingw-w64-crt/lib32/msvcr110.def.in +++ b/mingw-w64-crt/lib32/msvcr110.def.in @@ -954,7 +954,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1824,7 +1824,7 @@ cos DATA ; If we implement cosh, we can set it to DATA only. cosh div -exit +exit DATA exp DATA fabs DATA fclose diff --git a/mingw-w64-crt/lib32/msvcr120.def.in b/mingw-w64-crt/lib32/msvcr120.def.in index 82adab07b..af92ebfcf 100644 --- a/mingw-w64-crt/lib32/msvcr120.def.in +++ b/mingw-w64-crt/lib32/msvcr120.def.in @@ -973,7 +973,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1958,7 +1958,7 @@ erfcf erfcl erff erfl -exit +exit DATA exp exp2 exp2f diff --git a/mingw-w64-crt/lib32/msvcr120d.def.in b/mingw-w64-crt/lib32/msvcr120d.def.in index a9552f0b5..b77a3661d 100644 --- a/mingw-w64-crt/lib32/msvcr120d.def.in +++ b/mingw-w64-crt/lib32/msvcr120d.def.in @@ -1026,7 +1026,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _expand_dbg _fclose_nolock @@ -2025,7 +2025,7 @@ erfcf erfcl erff erfl -exit +exit DATA exp exp2 exp2f diff --git a/mingw-w64-crt/lib32/msvcr70.def b/mingw-w64-crt/lib32/msvcr70.def index 3d0275339..c10830281 100644 --- a/mingw-w64-crt/lib32/msvcr70.def +++ b/mingw-w64-crt/lib32/msvcr70.def @@ -312,7 +312,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fcloseall _fcvt @@ -723,7 +723,7 @@ cosh ctime difftime div -exit +exit DATA exp fabs fclose diff --git a/mingw-w64-crt/lib32/msvcr71.def b/mingw-w64-crt/lib32/msvcr71.def index 796fe52c5..53d2e6a14 100644 --- a/mingw-w64-crt/lib32/msvcr71.def +++ b/mingw-w64-crt/lib32/msvcr71.def @@ -305,7 +305,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fcloseall _fcvt @@ -718,7 +718,7 @@ cosh ctime difftime div -exit +exit DATA exp fabs fclose diff --git a/mingw-w64-crt/lib32/msvcr80.def.in b/mingw-w64-crt/lib32/msvcr80.def.in index bb1ec8444..639befe4b 100644 --- a/mingw-w64-crt/lib32/msvcr80.def.in +++ b/mingw-w64-crt/lib32/msvcr80.def.in @@ -162,7 +162,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fcloseall _fcvt @@ -588,7 +588,7 @@ _ctime32 ctime == _ctime32 difftime div -exit +exit DATA exp DATA fabs DATA fclose diff --git a/mingw-w64-crt/lib32/msvcr90.def.in b/mingw-w64-crt/lib32/msvcr90.def.in index 62789337b..83d818703 100644 --- a/mingw-w64-crt/lib32/msvcr90.def.in +++ b/mingw-w64-crt/lib32/msvcr90.def.in @@ -458,7 +458,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1327,7 +1327,7 @@ cos DATA ; If we have cosh implementation, we can set it to DATA only. cosh div -exit +exit DATA exp DATA fabs DATA fclose diff --git a/mingw-w64-crt/lib32/msvcr90d.def.in b/mingw-w64-crt/lib32/msvcr90d.def.in index 1175bfec1..79ed6351f 100644 --- a/mingw-w64-crt/lib32/msvcr90d.def.in +++ b/mingw-w64-crt/lib32/msvcr90d.def.in @@ -515,7 +515,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _expand_dbg _fclose_nolock @@ -1399,7 +1399,7 @@ cos DATA ; If we implement cosh too, we can set it to DATA only. cosh div -exit +exit DATA exp DATA fabs DATA fclose diff --git a/mingw-w64-crt/lib32/msvcrt10.def b/mingw-w64-crt/lib32/msvcrt10.def index 0265add70..6fcb35b19 100644 --- a/mingw-w64-crt/lib32/msvcrt10.def +++ b/mingw-w64-crt/lib32/msvcrt10.def @@ -943,7 +943,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fcloseall _fcvt @@ -1126,7 +1126,7 @@ cosh ctime difftime div -exit +exit DATA exp fabs fclose diff --git a/mingw-w64-crt/lib32/msvcrt20.def b/mingw-w64-crt/lib32/msvcrt20.def index e0e3897ce..de320ec22 100644 --- a/mingw-w64-crt/lib32/msvcrt20.def +++ b/mingw-w64-crt/lib32/msvcrt20.def @@ -1013,7 +1013,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fcloseall _fcvt @@ -1394,7 +1394,7 @@ cosh ctime difftime div -exit +exit DATA exp fabs fclose diff --git a/mingw-w64-crt/lib32/msvcrt40.def b/mingw-w64-crt/lib32/msvcrt40.def index 5abc34469..e07065ecb 100644 --- a/mingw-w64-crt/lib32/msvcrt40.def +++ b/mingw-w64-crt/lib32/msvcrt40.def @@ -1112,7 +1112,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fcloseall _fcvt @@ -1478,7 +1478,7 @@ cosh ctime difftime div -exit +exit DATA exp fabs fclose diff --git a/mingw-w64-crt/lib64/msvcr100.def.in b/mingw-w64-crt/lib64/msvcr100.def.in index aab982691..e91bdaf86 100644 --- a/mingw-w64-crt/lib64/msvcr100.def.in +++ b/mingw-w64-crt/lib64/msvcr100.def.in @@ -786,7 +786,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1644,7 +1644,7 @@ cosf DATA cosh coshf DATA div -exit +exit DATA exp DATA expf DATA fabs DATA diff --git a/mingw-w64-crt/lib64/msvcr110.def.in b/mingw-w64-crt/lib64/msvcr110.def.in index 60304f9fd..d7d8b90d9 100644 --- a/mingw-w64-crt/lib64/msvcr110.def.in +++ b/mingw-w64-crt/lib64/msvcr110.def.in @@ -911,7 +911,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1768,7 +1768,7 @@ cosf cosh coshf div -exit +exit DATA exp expf fabs diff --git a/mingw-w64-crt/lib64/msvcr120.def.in b/mingw-w64-crt/lib64/msvcr120.def.in index a37df574d..f63e9f09e 100644 --- a/mingw-w64-crt/lib64/msvcr120.def.in +++ b/mingw-w64-crt/lib64/msvcr120.def.in @@ -927,7 +927,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1903,7 +1903,7 @@ erfcf erfcl erff erfl -exit +exit DATA exp exp2 exp2f diff --git a/mingw-w64-crt/lib64/msvcr120d.def.in b/mingw-w64-crt/lib64/msvcr120d.def.in index 98a7b5f1d..8298c5fff 100644 --- a/mingw-w64-crt/lib64/msvcr120d.def.in +++ b/mingw-w64-crt/lib64/msvcr120d.def.in @@ -978,7 +978,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _expand_dbg _fclose_nolock @@ -1967,7 +1967,7 @@ erfcf erfcl erff erfl -exit +exit DATA exp exp2 exp2f diff --git a/mingw-w64-crt/lib64/msvcr80.def.in b/mingw-w64-crt/lib64/msvcr80.def.in index 045052ec8..796f5ef09 100644 --- a/mingw-w64-crt/lib64/msvcr80.def.in +++ b/mingw-w64-crt/lib64/msvcr80.def.in @@ -250,7 +250,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fcloseall _fcvt @@ -713,7 +713,7 @@ coshf _ctime32 difftime div -exit +exit DATA exp DATA expf DATA fabs diff --git a/mingw-w64-crt/lib64/msvcr90.def.in b/mingw-w64-crt/lib64/msvcr90.def.in index c8cf9b220..e5e5f57a9 100644 --- a/mingw-w64-crt/lib64/msvcr90.def.in +++ b/mingw-w64-crt/lib64/msvcr90.def.in @@ -403,7 +403,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1266,7 +1266,7 @@ cosf DATA cosh coshf DATA div -exit +exit DATA exp DATA expf DATA fabs DATA diff --git a/mingw-w64-crt/lib64/msvcr90d.def.in b/mingw-w64-crt/lib64/msvcr90d.def.in index 2acdc3fcf..f1544774d 100644 --- a/mingw-w64-crt/lib64/msvcr90d.def.in +++ b/mingw-w64-crt/lib64/msvcr90d.def.in @@ -454,7 +454,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _expand_dbg _fclose_nolock @@ -1332,7 +1332,7 @@ cosf cosh coshf div -exit +exit DATA exp DATA expf DATA fabs diff --git a/mingw-w64-crt/libarm32/kernelbase.def b/mingw-w64-crt/libarm32/kernelbase.def index d6a487db1..f6626c5df 100644 --- a/mingw-w64-crt/libarm32/kernelbase.def +++ b/mingw-w64-crt/libarm32/kernelbase.def @@ -1882,7 +1882,7 @@ __wgetmainargs _amsg_exit _c_exit _cexit -_exit +_exit DATA _initterm _initterm_e _invalid_parameter @@ -1890,7 +1890,7 @@ _onexit _purecall _time64 atexit DATA -exit +exit DATA hgets hwprintf lstrcmp diff --git a/mingw-w64-crt/libarm32/msvcr110.def b/mingw-w64-crt/libarm32/msvcr110.def index e9835df42..0c052a4e7 100644 --- a/mingw-w64-crt/libarm32/msvcr110.def +++ b/mingw-w64-crt/libarm32/msvcr110.def @@ -574,7 +574,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1410,7 +1410,7 @@ cosf cosh coshf div -exit +exit DATA exp expf fabs diff --git a/mingw-w64-crt/libarm32/msvcr120_clr0400.def b/mingw-w64-crt/libarm32/msvcr120_clr0400.def index a778c7ebf..dcb34cca2 100644 --- a/mingw-w64-crt/libarm32/msvcr120_clr0400.def +++ b/mingw-w64-crt/libarm32/msvcr120_clr0400.def @@ -573,7 +573,7 @@ _execv _execve _execvp _execvpe -_exit +_exit DATA _expand _fclose_nolock _fcloseall @@ -1409,7 +1409,7 @@ cosf cosh coshf div -exit +exit DATA exp expf fabs -- 2.37.3
From 5c2f6fb1ff821325c025a215f530ec99b95543d5 Mon Sep 17 00:00:00 2001 From: LIU Hao <[email protected]> Date: Fri, 7 Oct 2022 23:18:46 +0800 Subject: [PATCH 3/3] crt: Implement standard-conforming termination support with mcfgthread This commit implements these functions in accordance with the ISO C standard and the Itanium C++ ABI (except for `atexit()` which behaves in a per-module way like its old behavior, and also on Linux): * `atexit()`, C89 * `exit()`, C89 * `__cxa_atexit()`, Itanium C++ ABI * `_exit()`, POSIX * `_Exit()`, C99 * `at_quick_exit()`, C99 * `quick_exit()`, C99 * `__cxa_at_quick_exit()`, GNU extension Implementation details: 1. An object with the name `__dso_handle` is defined for each module (EXE or DLL). 2. Per-module cleanup callbacks should be registered with `__MCF_cxa_atexit()` or `__MCF_cxa_at_quick_exit()`, passing `&__dso_handle` as its third argument. 3. When a process calls `exit()` or returns from `main()`, `__MCF_cxa_finalize(NULL)` is called, which executes all callbacks registered with `__MCF_cxa_atexit()` in reverse order. 4. When a DLL is unloaded neither by calling `exit()` nor by returning from `main()` (in other words, by `FreeLibrary()`), `__MCF_cxa_finalize(&__dso_handle)`, which executes all callbacks registered with `__MCF_cxa_atexit()` with the same DSO handle in reverse order. Callbacks that have been registered with `__MCF_cxa_at_quick_exit()` are deleted. 5. All standard I/O streams are flushed before the process terminates. Signed-off-by: LIU Hao <[email protected]> --- mingw-w64-crt/Makefile.am | 2 +- mingw-w64-crt/crt/crtdll.c | 29 ++++++++++++++++++++++++++- mingw-w64-crt/crt/crtexe.c | 14 +++++++++++++ mingw-w64-crt/crt/cxa_at_quick_exit.c | 28 ++++++++++++++++++++++++++ mingw-w64-crt/crt/cxa_atexit.c | 19 ++++++++++++++++++ mingw-w64-crt/crt/cxa_thread_atexit.c | 19 ++++++++++++++++++ mingw-w64-crt/crt/exit_wrappers.c | 19 ++++++++++++++++++ mingw-w64-crt/crt/ucrtbase_compat.c | 8 ++++++++ 8 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-crt/crt/cxa_at_quick_exit.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 6dbac2339..a83ed0593 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -127,7 +127,7 @@ src_libmingw32=include/oscalls.h include/internal.h include/sect_attribs.h \ crt/usermatherr.c \ crt/xtxtmode.c crt/crt_handler.c \ crt/tlsthrd.c crt/tlsmthread.c crt/tlsmcrt.c \ - crt/cxa_atexit.c crt/cxa_thread_atexit.c crt/tls_atexit.c crt/exit_wrappers.c + crt/cxa_atexit.c crt/cxa_at_quick_exit.c crt/cxa_thread_atexit.c crt/tls_atexit.c crt/exit_wrappers.c src_libscrnsave=libsrc/scrnsave.c src_libscrnsavw=libsrc/scrnsave.c diff --git a/mingw-w64-crt/crt/crtdll.c b/mingw-w64-crt/crt/crtdll.c index 08cd5922a..87eb34ae9 100644 --- a/mingw-w64-crt/crt/crtdll.c +++ b/mingw-w64-crt/crt/crtdll.c @@ -31,6 +31,12 @@ #endif #include <sect_attribs.h> #include <locale.h> +#include <stdio.h> +#ifdef __USING_MCFGTHREAD__ +#include <mcfgthread/cxa.h> +#endif /* __USING_MCFGTHREAD__ */ + +extern HANDLE __dso_handle; extern void __cdecl _initterm(_PVFV *,_PVFV *); extern void __main (); @@ -181,7 +187,14 @@ __DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) } } if (dwReason == DLL_PROCESS_ATTACH) - __main (); + { +#ifdef __USING_MCFGTHREAD__ + /* Register `fflush(NULL)` before user-defined constructors, so it + * will be executed after all user-defined destructors. */ + __MCF_cxa_atexit ((__MCF_cxa_dtor_cdecl*)(intptr_t) fflush, NULL, &__dso_handle); +#endif + __main (); + } retcode = DllMain(hDllHandle,dwReason,lpreserved); if (dwReason == DLL_PROCESS_ATTACH && ! retcode) { @@ -195,6 +208,16 @@ __DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) if (_CRT_INIT (hDllHandle, dwReason, lpreserved) == FALSE) retcode = FALSE; } +#ifdef __USING_MCFGTHREAD__ + if (dwReason == DLL_PROCESS_DETACH && lpreserved == NULL) + { + /* Call `__cxa_finalize(dso_handle)` if the library is unloaded + * dynamically. This conforms to the Itanium C++ ABI. Note it is + * not called in case of process termination, where a call to + * `__cxa_finalize(NULL)` shall have been made instead. */ + __MCF_cxa_finalize (&__dso_handle); + } +#endif i__leave: __native_dllmain_reason = UINT_MAX; return retcode ; @@ -203,7 +226,11 @@ i__leave: int __cdecl atexit (_PVFV func) { +#ifdef __USING_MCFGTHREAD__ + return __MCF_cxa_atexit ((__MCF_cxa_dtor_cdecl*)(intptr_t) func, NULL, &__dso_handle); +#else return _register_onexit_function(&atexit_table, (_onexit_t)func); +#endif } char __mingw_module_is_dll = 1; diff --git a/mingw-w64-crt/crt/crtexe.c b/mingw-w64-crt/crt/crtexe.c index 65303f818..1b705ac3e 100644 --- a/mingw-w64-crt/crt/crtexe.c +++ b/mingw-w64-crt/crt/crtexe.c @@ -20,6 +20,10 @@ #include <tchar.h> #include <sect_attribs.h> #include <locale.h> +#include <stdio.h> +#ifdef __USING_MCFGTHREAD__ +#include <mcfgthread/cxa.h> +#endif /* __USING_MCFGTHREAD__ */ #if defined(__SEH__) && (!defined(__clang__) || __clang_major__ >= 7) #define SEH_INLINE_ASM @@ -52,6 +56,7 @@ int *__cdecl __p__commode(void); extern int _fmode; extern int _commode; extern int _dowildcard; +extern HANDLE __dso_handle; extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *); @@ -318,6 +323,11 @@ __tmainCRTStartup (void) StartupInfo.wShowWindow : SW_SHOWDEFAULT; } duplicate_ppstrings (argc, &argv); +#ifdef __USING_MCFGTHREAD__ + /* Register `fflush(NULL)` before user-defined constructors, so it + * will be executed after all user-defined destructors. */ + __MCF_cxa_atexit ((__MCF_cxa_dtor_cdecl*)(intptr_t) fflush, NULL, &__dso_handle); +#endif __main (); #ifdef WPRFLAG __winitenv = envp; @@ -424,7 +434,11 @@ static void duplicate_ppstrings (int ac, char ***av) int __cdecl atexit (_PVFV func) { +#ifdef __USING_MCFGTHREAD__ + return __MCF_cxa_atexit ((__MCF_cxa_dtor_cdecl*)(intptr_t) func, NULL, &__dso_handle); +#else return _onexit((_onexit_t)func) ? 0 : -1; +#endif } char __mingw_module_is_dll = 0; diff --git a/mingw-w64-crt/crt/cxa_at_quick_exit.c b/mingw-w64-crt/crt/cxa_at_quick_exit.c new file mode 100644 index 000000000..8fc6d594a --- /dev/null +++ b/mingw-w64-crt/crt/cxa_at_quick_exit.c @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +typedef void (__thiscall * dtor_fn)(void*); +int __cxa_at_quick_exit(dtor_fn dtor, void *obj, void *dso); + +#ifdef __USING_MCFGTHREAD__ + +#include <mcfgthread/cxa.h> + +typedef void* HANDLE; +extern HANDLE __dso_handle; + +int __cxa_at_quick_exit(dtor_fn dtor, void *obj, void *dso) { + /* This statically-linked wrapper always references the calling + * module itself. */ + (void) dso; + return __MCF_cxa_at_quick_exit(dtor, obj, &__dso_handle); +} + +#else /* __USING_MCFGTHREAD__ */ + +/* TODO: unimplemented */ + +#endif /* __USING_MCFGTHREAD__ */ diff --git a/mingw-w64-crt/crt/cxa_atexit.c b/mingw-w64-crt/crt/cxa_atexit.c index c4b5be111..ecddfbdca 100644 --- a/mingw-w64-crt/crt/cxa_atexit.c +++ b/mingw-w64-crt/crt/cxa_atexit.c @@ -6,8 +6,27 @@ typedef void (__thiscall * dtor_fn)(void*); int __cxa_atexit(dtor_fn dtor, void *obj, void *dso); + +#ifdef __USING_MCFGTHREAD__ + +#include <mcfgthread/cxa.h> + +typedef void* HANDLE; +extern HANDLE __dso_handle; + +int __cxa_atexit(dtor_fn dtor, void *obj, void *dso) { + /* This statically-linked wrapper always references the calling + * module itself. */ + (void) dso; + return __MCF_cxa_atexit(dtor, obj, &__dso_handle); +} + +#else /* __USING_MCFGTHREAD__ */ + int __mingw_cxa_atexit(dtor_fn dtor, void *obj, void *dso); int __cxa_atexit(dtor_fn dtor, void *obj, void *dso) { return __mingw_cxa_atexit(dtor, obj, dso); } + +#endif /* __USING_MCFGTHREAD__ */ diff --git a/mingw-w64-crt/crt/cxa_thread_atexit.c b/mingw-w64-crt/crt/cxa_thread_atexit.c index 3078c2444..1d93c3fa8 100644 --- a/mingw-w64-crt/crt/cxa_thread_atexit.c +++ b/mingw-w64-crt/crt/cxa_thread_atexit.c @@ -6,8 +6,27 @@ typedef void (__thiscall * dtor_fn)(void*); int __cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso); + +#ifdef __USING_MCFGTHREAD__ + +#include <mcfgthread/cxa.h> + +typedef void* HANDLE; +extern HANDLE __dso_handle; + +int __cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso) { + /* This statically-linked wrapper always references the calling + * module itself. */ + (void) dso; + return __MCF_cxa_thread_atexit(dtor, obj, &__dso_handle); +} + +#else /* __USING_MCFGTHREAD__ */ + int __mingw_cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso); int __cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso) { return __mingw_cxa_thread_atexit(dtor, obj, dso); } + +#endif /* __USING_MCFGTHREAD__ */ diff --git a/mingw-w64-crt/crt/exit_wrappers.c b/mingw-w64-crt/crt/exit_wrappers.c index 714395dec..3be71e492 100644 --- a/mingw-w64-crt/crt/exit_wrappers.c +++ b/mingw-w64-crt/crt/exit_wrappers.c @@ -5,19 +5,30 @@ */ #include <stdlib.h> +#ifdef __USING_MCFGTHREAD__ +#include <mcfgthread/exit.h> +#endif /* __USING_MCFGTHREAD__ */ /* `exit()`, C89 */ extern void (*__MINGW_IMP_SYMBOL(exit))(int) __attribute__((__noreturn__)); void exit(int status) { +#ifdef __USING_MCFGTHREAD__ + __MCF_exit(status); +#else (*__MINGW_IMP_SYMBOL(exit))(status); +#endif } /* `_exit()`, POSIX */ extern void (*__MINGW_IMP_SYMBOL(_exit))(int) __attribute__((__noreturn__)); void _exit(int status) { +#ifdef __USING_MCFGTHREAD__ + __MCF__Exit(status); +#else (*__MINGW_IMP_SYMBOL(_exit))(status); +#endif } #ifdef _UCRT @@ -25,13 +36,21 @@ void _exit(int status) { extern void (*__MINGW_IMP_SYMBOL(quick_exit))(int) __attribute__((__noreturn__)); void quick_exit(int status) { +#ifdef __USING_MCFGTHREAD__ + __MCF_quick_exit(status); +#else (*__MINGW_IMP_SYMBOL(quick_exit))(status); +#endif } /* `_Exit()`, C99 */ extern void (*__MINGW_IMP_SYMBOL(_Exit))(int) __attribute__((__noreturn__)); void _Exit(int status) { +#ifdef __USING_MCFGTHREAD__ + __MCF__Exit(status); +#else (*__MINGW_IMP_SYMBOL(_Exit))(status); +#endif } #endif /* _UCRT */ diff --git a/mingw-w64-crt/crt/ucrtbase_compat.c b/mingw-w64-crt/crt/ucrtbase_compat.c index 02910ff2f..9ac99f970 100644 --- a/mingw-w64-crt/crt/ucrtbase_compat.c +++ b/mingw-w64-crt/crt/ucrtbase_compat.c @@ -22,6 +22,9 @@ #include <stdio.h> #include <time.h> #include <corecrt_startup.h> +#ifdef __USING_MCFGTHREAD__ +#include <mcfgthread/cxa.h> +#endif /* __USING_MCFGTHREAD__ */ #undef __getmainargs #undef __wgetmainargs @@ -56,6 +59,7 @@ _CRTIMP int __cdecl _configure_wide_argv(int mode); _CRTIMP int __cdecl _set_new_mode(int _NewMode); extern char __mingw_module_is_dll; +extern HANDLE __dso_handle; // Wrappers with legacy msvcrt.dll style API, based on the new ucrtbase.dll functions. @@ -92,12 +96,16 @@ _onexit_t __cdecl (*__MINGW_IMP_SYMBOL(_onexit))(_onexit_t func) = _onexit; int __cdecl at_quick_exit(void (__cdecl *func)(void)) { +#ifdef __USING_MCFGTHREAD__ + return __MCF_cxa_at_quick_exit ((__MCF_cxa_dtor_cdecl*)(intptr_t) func, NULL, &__dso_handle); +#else /* __USING_MCFGTHREAD__ */ // In a DLL, we can't register a function with _crt_at_quick_exit, because // we can't unregister it when the DLL is unloaded. This matches how // at_quick_exit/quick_exit work with MSVC with a dynamically linked CRT. if (__mingw_module_is_dll) return 0; return _crt_at_quick_exit(func); +#endif /* __USING_MCFGTHREAD__ */ } int __cdecl (*__MINGW_IMP_SYMBOL(at_quick_exit))(void (__cdecl *)(void)) = at_quick_exit; -- 2.37.3
OpenPGP_signature
Description: OpenPGP digital signature
_______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
