From f81c82f5fa68177c6707aa2f52cd2dda9a4b3916 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sun, 9 Feb 2025 12:46:03 +0200 Subject: [PATCH] [VCSTARTUP] Implement atexit and _onexit These must use a local table and cannot use the one from ucrtbase. The table is initialized with a .CRT section initializer. --- sdk/lib/vcruntime/CMakeLists.txt | 2 ++ sdk/lib/vcruntime/_onexit.c | 34 +++++++++++++++++++++++++ sdk/lib/vcruntime/atexit.c | 18 +++++++++++++ sdk/lib/vcruntime/inc/internal_shared.h | 1 + 4 files changed, 55 insertions(+) create mode 100644 sdk/lib/vcruntime/_onexit.c create mode 100644 sdk/lib/vcruntime/atexit.c diff --git a/sdk/lib/vcruntime/CMakeLists.txt b/sdk/lib/vcruntime/CMakeLists.txt index 405dc705bd9..6851dcaef0b 100644 --- a/sdk/lib/vcruntime/CMakeLists.txt +++ b/sdk/lib/vcruntime/CMakeLists.txt @@ -35,6 +35,8 @@ list(APPEND VCRT_STARTUP_SOURCES __acrt_initialize_stub.cpp __scrt_uninitialize_crt.cpp __vcrt_init_stubs.c + _onexit.c + atexit.c mainCRTStartup.cpp wmainCRTStartup.cpp ) diff --git a/sdk/lib/vcruntime/_onexit.c b/sdk/lib/vcruntime/_onexit.c new file mode 100644 index 00000000000..3d3572c3bf2 --- /dev/null +++ b/sdk/lib/vcruntime/_onexit.c @@ -0,0 +1,34 @@ +// +// _onexit.c +// +// Copyright (c) 2024 Timo Kreuzer +// +// Implementation of _onexit. +// +// SPDX-License-Identifier: MIT +// + +#include +#include +#include +#include + +_onexit_table_t module_local_atexit_table; +int module_local_atexit_table_initialized = 0; + +int __cdecl __scrt_initialize_onexit(void) +{ + _initialize_onexit_table(&module_local_atexit_table); + module_local_atexit_table_initialized = 1; + return 0; +} + +// CRT startup initializer +_CRTALLOC(".CRT$XIAA") _PIFV const __scrt_onexit_initializer = __scrt_initialize_onexit; + +_onexit_t __cdecl _onexit(_In_opt_ _onexit_t _Func) +{ + assert(module_local_atexit_table_initialized == 1); + int result = _register_onexit_function(&module_local_atexit_table, _Func); + return (result == 0) ? _Func : NULL; +} diff --git a/sdk/lib/vcruntime/atexit.c b/sdk/lib/vcruntime/atexit.c new file mode 100644 index 00000000000..391e416bb82 --- /dev/null +++ b/sdk/lib/vcruntime/atexit.c @@ -0,0 +1,18 @@ +// +// atexit.c +// +// Copyright (c) 2024 Timo Kreuzer +// +// Implementation of atexit. +// +// SPDX-License-Identifier: MIT +// + +#include + +int __cdecl atexit(void (__cdecl* _Func)(void)) +{ + // Go through _onexit, so that the initializer is pulled in. + _onexit_t result = _onexit((_onexit_t)_Func); + return (result == NULL) ? -1 : 0; +} diff --git a/sdk/lib/vcruntime/inc/internal_shared.h b/sdk/lib/vcruntime/inc/internal_shared.h index 968f5ecb498..b3274a030d9 100644 --- a/sdk/lib/vcruntime/inc/internal_shared.h +++ b/sdk/lib/vcruntime/inc/internal_shared.h @@ -31,6 +31,7 @@ extern "C" { #pragma section(".CRT$XPXA", long, read) #pragma section(".CRT$XIA", long, read) +#pragma section(".CRT$XIAA", long, read) // CRT startup #pragma section(".CRT$XIZ", long, read) #pragma section(".CRT$XCA", long, read) #pragma section(".CRT$XCZ", long, read)