diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 6d73431493..1ee666eaba 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -39,9 +39,7 @@ # _Z11genode_exiti T -_Z13genode_atexitPFvvE T _Z16main_thread_utcbv T -_Z21genode___cxa_finalizePv T _Z22__ldso_raise_exceptionv T _ZN5Timer10Connection16schedule_timeoutEN6Genode12MicrosecondsERNS1_11Time_source15Timeout_handlerE T _ZN5Timer10Connection18_schedule_one_shotERN6Genode7TimeoutENS1_12MicrosecondsE T @@ -625,12 +623,12 @@ _ZTVSt9exception D 40 _ZTVSt9type_info D 64 _ZdlPv W _ZdlPvm W -__aeabi_atexit T +__aeabi_atexit W __aeabi_unwind_cpp_pr0 T __aeabi_unwind_cpp_pr1 T __cxa_allocate_dependent_exception T __cxa_allocate_exception T -__cxa_atexit T +__cxa_atexit W __cxa_bad_cast T __cxa_bad_typeid T __cxa_begin_catch T diff --git a/repos/base/src/include/base/internal/globals.h b/repos/base/src/include/base/internal/globals.h index 4a210fd40c..4eeb3aa8c2 100644 --- a/repos/base/src/include/base/internal/globals.h +++ b/repos/base/src/include/base/internal/globals.h @@ -38,7 +38,6 @@ namespace Genode { void init_root_proxy(Env &); void init_tracing(Env &); void init_log(Parent &); - void init_exit(Parent &); void init_parent_resource_requests(Env &); void init_heartbeat_monitoring(Env &); void deinit_heartbeat_monitoring(); diff --git a/repos/base/src/lib/cxx/misc.cc b/repos/base/src/lib/cxx/misc.cc index ae845d4ce7..7be5c76e05 100644 --- a/repos/base/src/lib/cxx/misc.cc +++ b/repos/base/src/lib/cxx/misc.cc @@ -41,29 +41,16 @@ extern "C" void __pure_virtual() } -/** - * Prototype for exit-handler support function provided by '_main.cc' +/* + * Plain Genode components do not support the atexit mechanism. + * + * To accommodate applications that depend on this mechansim, the libc + * overrides this weak no-op function with a working implementation. */ -extern int genode___cxa_atexit(void(*func)(void*), void *arg, - void *dso_handle); - - -extern "C" int __cxa_atexit(void(*func)(void*), void *arg, - void *dso_handle) +extern "C" __attribute__((weak)) +int __cxa_atexit(void(*)(void*), void *, void *) { - return genode___cxa_atexit(func, arg, dso_handle); -} - - -/** - * Prototype for finalize support function provided by '_main.cc' - */ -extern int genode___cxa_finalize(void *dso); - - -extern "C" void __cxa_finalize(void *dso) -{ - genode___cxa_finalize(dso); + return -1; } @@ -71,11 +58,10 @@ extern "C" void __cxa_finalize(void *dso) ** Support required for ARM EABI ** ***********************************/ - -extern "C" int __aeabi_atexit(void *arg, void(*func)(void*), - void *dso_handle) +extern "C" __attribute__((weak)) +int __aeabi_atexit(void *, void(*)(void*), void *) { - return genode___cxa_atexit(func, arg, dso_handle); + return -1; } @@ -118,10 +104,6 @@ extern "C" void abort(void) Genode::warning("abort called - thread: ", name.string()); - /* Notify the parent of failure */ - if (name != "main") - genode_exit(1); - Genode::sleep_forever(); } diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc index 157ccd972c..9ac7c9f307 100644 --- a/repos/base/src/lib/ldso/main.cc +++ b/repos/base/src/lib/ldso/main.cc @@ -19,6 +19,7 @@ #include #include #include +#include /* base-internal includes */ #include @@ -43,15 +44,11 @@ namespace Linker { }; static Binary *binary_ptr = nullptr; +static Parent *parent_ptr = nullptr; bool Linker::verbose = false; Stage Linker::stage = STAGE_BINARY; Link_map *Link_map::first; -/** - * Registers dtors - */ -int genode_atexit(Linker::Func); - Linker::Region_map::Constructible_region_map &Linker::Region_map::r() { @@ -344,8 +341,6 @@ extern char **genode_argv; extern int genode_argc; extern char **genode_envp; -void genode_exit(int status); - static int exit_status; static void exit_on_suspended() { genode_exit(exit_status); } @@ -411,19 +406,22 @@ struct Linker::Binary : private Root_object, public Elf_object { Init::list()->exec_static_constructors(); - /* call static constructors and register destructors */ + /* call static constructors */ Func * const ctors_start = (Func *)lookup_symbol("_ctors_start"); Func * const ctors_end = (Func *)lookup_symbol("_ctors_end"); for (Func * ctor = ctors_end; ctor != ctors_start; (*--ctor)()); - Func * const dtors_start = (Func *)lookup_symbol("_dtors_start"); - Func * const dtors_end = (Func *)lookup_symbol("_dtors_end"); - for (Func * dtor = dtors_start; dtor != dtors_end; genode_atexit(*dtor++)); - static_construction_finished = true; stage = STAGE_SO; } + void call_dtors() + { + Func * const dtors_start = (Func *)lookup_symbol("_dtors_start"); + Func * const dtors_end = (Func *)lookup_symbol("_dtors_end"); + for (Func * dtor = dtors_end; dtor != dtors_start; (*--dtor)()); + } + void call_entry_point(Env &env) { /* apply the component-provided stack size */ @@ -496,6 +494,19 @@ struct Linker::Binary : private Root_object, public Elf_object }; +void genode_exit(int status) +{ + binary_ptr->call_dtors(); + + /* inform parent about the exit status */ + if (parent_ptr) + parent_ptr->exit(status); + + /* wait for destruction by the parent */ + Genode::sleep_forever(); +} + + /********************************** ** Linker object implementation ** **********************************/ @@ -791,6 +802,8 @@ void Component::construct(Genode::Env &env) verbose = config.verbose(); + parent_ptr = &env.parent(); + /* load binary and all dependencies */ try { binary_ptr = unmanaged_singleton(env, *heap(), config, binary_name()); diff --git a/repos/base/src/lib/startup/_main.cc b/repos/base/src/lib/startup/_main.cc index 3c72589913..5d6780a17a 100644 --- a/repos/base/src/lib/startup/_main.cc +++ b/repos/base/src/lib/startup/_main.cc @@ -8,8 +8,6 @@ * The startup code calls constructors for static objects before calling * main(). Furthermore, this file contains the support of exit handlers * and destructors. - * - * Some code within this file is based on 'atexit.c' of FreeBSD's libc. */ /* @@ -29,176 +27,8 @@ #include #include - -enum { ATEXIT_SIZE = 256 }; - - -/*************** - ** C++ stuff ** - ***************/ - void * __dso_handle = 0; -enum Atexit_fn_type { ATEXIT_FN_EMPTY, ATEXIT_FN_STD, ATEXIT_FN_CXA }; - -struct atexit_fn -{ - Atexit_fn_type fn_type; - union - { - void (*std_func)(void); - void (*cxa_func)(void *); - } fn_ptr; /* function pointer */ - void *fn_arg; /* argument for CXA callback */ - void *fn_dso; /* shared module handle */ -}; - -/* all members are initialized with 0 */ -static struct atexit -{ - bool enabled; - int index; - struct atexit_fn fns[ATEXIT_SIZE]; -} _atexit; - - -static Genode::Mutex &atexit_mutex() -{ - static Genode::Mutex _atexit_lock; - return _atexit_lock; -} - - -static void atexit_enable() -{ - _atexit.enabled = true; -} - - -static int atexit_register(struct atexit_fn *fn) -{ - Genode::Mutex::Guard atexit_lock_guard(atexit_mutex()); - - if (!_atexit.enabled) - return 0; - - if (_atexit.index >= ATEXIT_SIZE) { - Genode::error("Cannot register exit handler - ATEXIT_SIZE reached"); - return -1; - } - - _atexit.fns[_atexit.index++] = *fn; - - return 0; -} - - -/** - * Register a function to be performed at exit - */ -int genode_atexit(void (*func)(void)) -{ - struct atexit_fn fn; - int error; - - fn.fn_type = ATEXIT_FN_STD; - fn.fn_ptr.std_func = func; - fn.fn_arg = 0; - fn.fn_dso = 0; - - error = atexit_register(&fn); - return (error); -} - - -/** - * Register a function to be performed at exit or when an shared object - * with given dso handle is unloaded dynamically. - * - * This function is called directly by compiler generated code, so - * it needs to be declared as extern "C" and cannot be local to - * the cxx lib. - */ -int genode___cxa_atexit(void (*func)(void*), void *arg, void *dso) -{ - struct atexit_fn fn; - int error; - - fn.fn_type = ATEXIT_FN_CXA; - fn.fn_ptr.cxa_func = func; - fn.fn_arg = arg; - fn.fn_dso = dso; - - error = atexit_register(&fn); - return (error); -} - - -/* - * Call all handlers registered with __cxa_atexit for the shared - * object owning 'dso'. Note: if 'dso' is NULL, then all remaining - * handlers are called. - */ -void genode___cxa_finalize(void *dso) -{ - struct atexit_fn fn; - int n = 0; - - atexit_mutex().acquire(); - for (n = _atexit.index; --n >= 0;) { - if (_atexit.fns[n].fn_type == ATEXIT_FN_EMPTY) - continue; /* already been called */ - if (dso != 0 && dso != _atexit.fns[n].fn_dso) - continue; /* wrong DSO */ - fn = _atexit.fns[n]; - - /* - * Mark entry to indicate that this particular handler - * has already been called. - */ - _atexit.fns[n].fn_type = ATEXIT_FN_EMPTY; - atexit_mutex().release(); - - /* call the function of correct type */ - if (fn.fn_type == ATEXIT_FN_CXA) - fn.fn_ptr.cxa_func(fn.fn_arg); - else if (fn.fn_type == ATEXIT_FN_STD) - fn.fn_ptr.std_func(); - - atexit_mutex().acquire(); - } - atexit_mutex().release(); -} - - -extern "C" void __cxa_finalize(void *dso); - -static Genode::Parent *_parent_ptr; - - -namespace Genode { void init_exit(Parent &parent) { _parent_ptr = &parent; } } - - -/** - * Terminate the process. - */ -void genode_exit(int status) -{ - /* call handlers registered with 'atexit()' or '__cxa_atexit()' */ - __cxa_finalize(0); - - /* call destructors for global static objects. */ - void (**func)(); - for (func = &_dtors_start; func != &_dtors_end; (*func++)()); - - /* inform parent about the exit status */ - if (_parent_ptr) - _parent_ptr->exit(status); - - /* wait for destruction by the parent */ - Genode::sleep_forever(); -} - /** * Dummy default arguments for main function @@ -242,16 +72,6 @@ namespace Genode { extern "C" int _main() { - /* - * Allow exit handlers to be registered. - * - * This is done after the creation of the environment to prevent its - * destruction. The environment is still needed to notify the parent - * after all exit handlers (including static object destructors) have - * been called. - */ - atexit_enable(); - Genode::bootstrap_component(); /* never reached */ @@ -259,22 +79,13 @@ extern "C" int _main() } -static int exit_status; -static void exit_on_suspended() { genode_exit(exit_status); } - - extern int main(int argc, char **argv, char **envp); void Component::construct(Genode::Env &env) __attribute__((weak)); -void Component::construct(Genode::Env &env) +void Component::construct(Genode::Env &) { /* call real main function */ - exit_status = main(genode_argc, genode_argv, genode_envp); - - /* trigger suspend in the entry point */ - env.ep().schedule_suspend(exit_on_suspended, nullptr); - - /* return to entrypoint and exit via exit_on_suspended() */ + main(genode_argc, genode_argv, genode_envp); } diff --git a/repos/base/src/lib/startup/init_main_thread.cc b/repos/base/src/lib/startup/init_main_thread.cc index 771ae7c6ca..e0a6efc392 100644 --- a/repos/base/src/lib/startup/init_main_thread.cc +++ b/repos/base/src/lib/startup/init_main_thread.cc @@ -106,7 +106,6 @@ extern "C" void init_main_thread() */ (void*)env_deprecated(); init_log(*env_deprecated()->parent()); - init_exit(*env_deprecated()->parent()); /* create a thread object for the main thread */ main_thread(); diff --git a/repos/base/src/test/sanitizer/main.cc b/repos/base/src/test/sanitizer/main.cc index 2c723d287c..9f1fcb444a 100644 --- a/repos/base/src/test/sanitizer/main.cc +++ b/repos/base/src/test/sanitizer/main.cc @@ -15,6 +15,7 @@ #include extern void sanitizer_init(Genode::Env &); +extern void sanitizer_exit(); void Component::construct(Genode::Env &env) { @@ -30,4 +31,10 @@ void Component::construct(Genode::Env &env) int * volatile ptr = nullptr; *ptr = 0x55; + + /* + * Not reached in this test, but calls exit handlers registered by + * sanitizers in general. + */ + sanitizer_exit(); } diff --git a/repos/libports/lib/symbols/libsanitizer_common b/repos/libports/lib/symbols/libsanitizer_common index 5047a42161..9b591f1e11 100644 --- a/repos/libports/lib/symbols/libsanitizer_common +++ b/repos/libports/lib/symbols/libsanitizer_common @@ -1,4 +1,5 @@ OnPrint W +_Z14sanitizer_exitv T _Z14sanitizer_initRN6Genode3EnvE T _ZN11__sanitizer10ExtractIntEPKcS1_Pi T _ZN11__sanitizer10FlagParser10ll_strndupEPKcm T diff --git a/repos/libports/ports/sanitizer.hash b/repos/libports/ports/sanitizer.hash index 76d672cd24..af638a244e 100644 --- a/repos/libports/ports/sanitizer.hash +++ b/repos/libports/ports/sanitizer.hash @@ -1 +1 @@ -181889c6d4af01eed6f89b2df496b83896d18034 +3ac05b0fdf5b49cd1b375afe08095c4c1a6c5289 diff --git a/repos/libports/recipes/pkg/test-ldso/runtime b/repos/libports/recipes/pkg/test-ldso/runtime index 0530aae605..389c748665 100644 --- a/repos/libports/recipes/pkg/test-ldso/runtime +++ b/repos/libports/recipes/pkg/test-ldso/runtime @@ -94,13 +94,13 @@ [init -> test-ldso] ~Lib_1_local_3 0x12345675* [init -> test-ldso] ~Local_2 0x1020303d* [init -> test-ldso] ~Local_1 0x5060707d* - [init -> test-ldso] attr_destructor_2 0x4030200d* - [init -> test-ldso] attr_destructor_1 0x8070604c* [init -> test-ldso] ~Global_2 0x1020301* [init -> test-ldso] ~Global_1 0x5060705* [init -> test-ldso] ~Lib_1_global_2 0x1020301* [init -> test-ldso] ~Lib_1_global_1 0x5060705* [init -> test-ldso] ~Lib_2_global 0x11223340* + [init -> test-ldso] attr_destructor_2 0x4030200d* + [init -> test-ldso] attr_destructor_1 0x8070604c* [init] child "test-ldso" exited with exit value 123 diff --git a/repos/libports/src/lib/gcov/libc/libc.cc b/repos/libports/src/lib/gcov/libc/libc.cc index 9a45b30cb2..3bd82b49b2 100644 --- a/repos/libports/src/lib/gcov/libc/libc.cc +++ b/repos/libports/src/lib/gcov/libc/libc.cc @@ -68,13 +68,6 @@ extern "C" void abort() } -extern void genode_atexit(void (*func)(void)); -extern "C" void atexit(void (*func)(void)) -{ - genode_atexit(func); -} - - extern "C" int atoi(const char *nptr) { Genode::error("atoi() called: not implemented"); diff --git a/repos/libports/src/lib/libc/atexit.cc b/repos/libports/src/lib/libc/atexit.cc index 4e1e62c635..4300db0621 100644 --- a/repos/libports/src/lib/libc/atexit.cc +++ b/repos/libports/src/lib/libc/atexit.cc @@ -11,14 +11,78 @@ * under the terms of the GNU Affero General Public License version 3. */ -extern void genode_atexit(void (*func)(void)); -extern "C" void atexit(void (*func)(void)) +/* Genode includes */ +#include + +/* libc includes */ +#include + +/* libc-internal includes */ +#include + +using namespace Libc; + + +static Libc::Atexit *_atexit_ptr; + + +void Libc::init_atexit(Atexit &atexit) { - genode_atexit(func); + _atexit_ptr = &atexit; } -extern void genode___cxa_finalize(void *dso); + +void Libc::execute_atexit_handlers_in_application_context() +{ + if (!_atexit_ptr) { + error("missing call of 'init_atexit'"); + sleep_forever(); + } + + /* + * The atexit handlers must be executed in application context because the + * handlers may perform I/O such as the closing of file descriptors. + */ + with_libc([&] () { + _atexit_ptr->execute_handlers(nullptr); + }); +} + + +/********************* + ** CXA ABI support ** + *********************/ + +/* + * The C++ compiler generates calls to '__cxa_atexit' for each object that + * is instantiated as static local variable. + */ + +extern "C" int __cxa_atexit(void (*func)(void*), void *arg, void *dso) +{ + if (!_atexit_ptr) + return -1; + + _atexit_ptr->register_cxa_handler(func, arg, dso); + return 0; +} + + +extern "C" int __aeabi_atexit(void *arg, void(*func)(void*), void *dso) +{ + return __cxa_atexit(func, arg, dso); +} + + extern "C" void __cxa_finalize(void *dso) { - genode___cxa_finalize(dso); + execute_atexit_handlers_in_application_context(); } + + +extern "C" int atexit(void (*func)(void)) +{ + _atexit_ptr->register_std_handler(func); + return 0; +} + diff --git a/repos/libports/src/lib/libc/exit.cc b/repos/libports/src/lib/libc/exit.cc index bf178584f0..fb321e7dc6 100644 --- a/repos/libports/src/lib/libc/exit.cc +++ b/repos/libports/src/lib/libc/exit.cc @@ -16,11 +16,16 @@ /* libc-internal includes */ #include +#include + extern void genode_exit(int status) __attribute__((noreturn)); + extern "C" void _exit(int status) { + Libc::execute_atexit_handlers_in_application_context(); + genode_exit(status); } diff --git a/repos/libports/src/lib/libc/internal/atexit.h b/repos/libports/src/lib/libc/internal/atexit.h new file mode 100644 index 0000000000..b25a9d5474 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/atexit.h @@ -0,0 +1,127 @@ +/* + * \brief POSIX atexit handling + * \author Norman Feske + * \date 2020-08-17 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _LIBC__INTERNAL__ATEXIT_H_ +#define _LIBC__INTERNAL__ATEXIT_H_ + +/* Genode includes */ +#include +#include +#include + +/* libc-internal includes */ +#include +#include + +namespace Libc { struct Atexit; } + + +struct Libc::Atexit : Noncopyable +{ + private: + + using Allocator = Genode::Allocator; + + Allocator &_alloc; + + struct Handler : List::Element + { + enum class Type { STD, CXA }; + + Type type; + + void (*std_func)(void); + void (*cxa_func)(void *); + + void *fn_arg; /* argument for CXA callback */ + void *dso; /* shared object handle */ + + void execute() + { + switch (type) { + case Type::CXA: cxa_func(fn_arg); break; + case Type::STD: std_func(); break; + } + } + }; + + Mutex _mutex { }; + + List _handlers { }; + + public: + + Atexit(Allocator &alloc) : _alloc(alloc) { } + + void register_cxa_handler(void (*func)(void*), void *arg, void *dso) + { + Mutex::Guard guard(_mutex); + + _handlers.insert( + new (_alloc) Handler { .type = Handler::Type::CXA, + .std_func = nullptr, + .cxa_func = func, + .fn_arg = arg, + .dso = dso }); + } + + void register_std_handler(void (*func)()) + { + Mutex::Guard guard(_mutex); + + _handlers.insert( + new (_alloc) Handler { .type = Handler::Type::STD, + .std_func = func, + .cxa_func = nullptr, + .fn_arg = nullptr, + .dso = nullptr }); + } + + /* + * Execute all exit handler for shared object 'dso'. + * + * If 'dso' is nullptr, all remaining handlers are executed. + */ + void execute_handlers(void *dso) + { + auto try_execute_one_matching_handler = [&] () + { + Handler *handler_ptr = nullptr; + + /* search matching handler */ + { + Mutex::Guard guard(_mutex); + + handler_ptr = _handlers.first(); + while (handler_ptr && dso && (handler_ptr->dso != dso)) { + handler_ptr = handler_ptr->next(); + } + } + + if (!handler_ptr) + return false; + + handler_ptr->execute(); + _handlers.remove(handler_ptr); + destroy(_alloc, handler_ptr); + return true; + }; + + while (try_execute_one_matching_handler()); + } +}; + + +namespace Libc { void execute_atexit_handlers_in_application_context(); } + +#endif /* _LIBC__INTERNAL__ATEXIT_H_ */ diff --git a/repos/libports/src/lib/libc/internal/init.h b/repos/libports/src/lib/libc/internal/init.h index da20ad703b..a75bd65222 100644 --- a/repos/libports/src/lib/libc/internal/init.h +++ b/repos/libports/src/lib/libc/internal/init.h @@ -40,6 +40,7 @@ namespace Libc { struct File_descriptor_allocator; struct Timer_accessor; struct Cwd; + struct Atexit; /** * Support for shared libraries @@ -143,6 +144,11 @@ namespace Libc { * Signal handling */ void init_signal(Signal &); + + /** + * Atexit handling + */ + void init_atexit(Atexit &); } #endif /* _LIBC__INTERNAL__INIT_H_ */ diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index b531ae25fc..e829117b08 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -42,6 +42,7 @@ #include #include #include +#include namespace Libc { class Kernel; @@ -192,6 +193,8 @@ struct Libc::Kernel final : Vfs::Io_response_handler, Signal _signal { _pid }; + Atexit _atexit { _heap }; + Reconstructible> _resume_main_handler { _env.ep(), *this, &Kernel::_resume_main }; diff --git a/repos/libports/src/lib/libc/kernel.cc b/repos/libports/src/lib/libc/kernel.cc index af4ba55b18..f20c1f0f1b 100644 --- a/repos/libports/src/lib/libc/kernel.cc +++ b/repos/libports/src/lib/libc/kernel.cc @@ -510,6 +510,8 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap) : _env(env), _heap(heap) { + init_atexit(_atexit); + atexit(close_file_descriptors_on_exit); init_semaphore_support(_timer_accessor); diff --git a/repos/libports/src/lib/sanitizer/sanitizer.patch b/repos/libports/src/lib/sanitizer/sanitizer.patch index db78a5e2e6..30ea08c3e3 100644 --- a/repos/libports/src/lib/sanitizer/sanitizer.patch +++ b/repos/libports/src/lib/sanitizer/sanitizer.patch @@ -4,7 +4,7 @@ From: Christian Prochaska --- - sanitizer_common/sanitizer_genode.cc | 330 ++++++++++++++++++++ + sanitizer_common/sanitizer_genode.cc | 345 ++++++++++++++++++++ sanitizer_common/sanitizer_internal_defs.h | 6 sanitizer_common/sanitizer_platform.h | 4 sanitizer_common/sanitizer_posix.h | 2 @@ -13,15 +13,15 @@ From: Christian Prochaska sanitizer_common/sanitizer_symbolizer_libcdep.cc | 10 - .../sanitizer_symbolizer_posix_libcdep.cc | 31 +- ubsan/ubsan_diag.cc | 4 - 9 files changed, 376 insertions(+), 15 deletions(-) + 9 files changed, 391 insertions(+), 15 deletions(-) create mode 100644 sanitizer_common/sanitizer_genode.cc diff --git a/sanitizer_common/sanitizer_genode.cc b/sanitizer_common/sanitizer_genode.cc new file mode 100644 -index 0000000..cd2bc92 +index 0000000..52dda98 --- /dev/null +++ b/sanitizer_common/sanitizer_genode.cc -@@ -0,0 +1,330 @@ +@@ -0,0 +1,345 @@ +/* + * \brief Genode-specific functions from sanitizer_common.h + * and sanitizer_libc.h @@ -48,7 +48,6 @@ index 0000000..cd2bc92 +using namespace __sanitizer; + + -+extern int genode_atexit(void (*func)(void)); +extern void genode_exit(int) __attribute__((noreturn)); + + @@ -74,11 +73,20 @@ index 0000000..cd2bc92 + +void sanitizer_init(Genode::Env &env) +{ -+Genode::log("sanitizer_init()"); + genode_env = &env; +} + + ++static void (*atexit_func)(void) = nullptr; ++ ++ ++void sanitizer_exit() ++{ ++ if (atexit_func) ++ atexit_func(); ++} ++ ++ +/* sanitizer_common.h */ + + @@ -91,7 +99,14 @@ index 0000000..cd2bc92 + +int __sanitizer::Atexit(void (*function)(void)) +{ -+ return genode_atexit(function); ++ if (atexit_func) { ++ Genode::error("sanitizer: ", __func__, ++ ": only one exit handler is currently supported"); ++ return -1; ++ } ++ ++ atexit_func = function; ++ return 0; +} + + @@ -629,14 +644,13 @@ index 978d966..7d38a9b 100644 using namespace __ubsan; -@@ -209,8 +211,10 @@ static void RenderText(InternalScopedString *Buffer, const char *Message, +@@ -209,7 +211,9 @@ static void RenderText(InternalScopedString *Buffer, const char *Message, #if SANITIZER_WINDOWS sprintf_s(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float); #else +#if 0 snprintf(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float); - #endif +#endif + #endif Buffer->append("%s", FloatBuffer); break; - }