mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
Move atexit handling from base lib to libc
This patch untangles the interplay of the base library and the libc during the exit handling. - The CXA ABI for the atexit handling is now provided by the libc. For plain Genode components without libc dependency, __cxa_atexit is a no-op, which is consistent with Genode's notion of components. - The 'abort' implementation of the base library no longer calls 'genode_exit' but merely 'sleep_forever'. This way, the cxx library no longer depends on a 'genode_exit' implementation. - The libc provides 'atexit' support by storing metadata on the libc kernel's heap now, thereby eliminating the former bounded maximum number of atexit handlers. - Shared-library dtors are no longer called via the atexit mechanism by explicitly by the dynamic linker. This slightly changes the call order of destructors (adjustment of the ldso test). Functions marked as destructors are called after the atexit handlers now. - The libc executes atexit handlers in the application context, which supports the I/O operations in those handles, in particular the closing of file descriptors. Fixes #3851
This commit is contained in:
parent
66063e5137
commit
852ab79359
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <util/string.h>
|
||||
#include <base/thread.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/unmanaged_singleton.h>
|
||||
@ -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<Binary>(env, *heap(), config, binary_name());
|
||||
|
@ -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 <base/internal/parent_cap.h>
|
||||
#include <base/internal/crt0.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <base/log.h>
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
OnPrint W
|
||||
_Z14sanitizer_exitv T
|
||||
_Z14sanitizer_initRN6Genode3EnvE T
|
||||
_ZN11__sanitizer10ExtractIntEPKcS1_Pi T
|
||||
_ZN11__sanitizer10FlagParser10ll_strndupEPKcm T
|
||||
|
@ -1 +1 @@
|
||||
181889c6d4af01eed6f89b2df496b83896d18034
|
||||
3ac05b0fdf5b49cd1b375afe08095c4c1a6c5289
|
||||
|
@ -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
|
||||
</log>
|
||||
</events>
|
||||
|
@ -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");
|
||||
|
@ -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 <base/sleep.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <libc/component.h>
|
||||
|
||||
/* libc-internal includes */
|
||||
#include <internal/atexit.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -16,11 +16,16 @@
|
||||
|
||||
/* libc-internal includes */
|
||||
#include <internal/types.h>
|
||||
#include <internal/atexit.h>
|
||||
|
||||
|
||||
extern void genode_exit(int status) __attribute__((noreturn));
|
||||
|
||||
|
||||
extern "C" void _exit(int status)
|
||||
{
|
||||
Libc::execute_atexit_handlers_in_application_context();
|
||||
|
||||
genode_exit(status);
|
||||
}
|
||||
|
||||
|
127
repos/libports/src/lib/libc/internal/atexit.h
Normal file
127
repos/libports/src/lib/libc/internal/atexit.h
Normal file
@ -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 <util/noncopyable.h>
|
||||
#include <util/list.h>
|
||||
#include <base/mutex.h>
|
||||
|
||||
/* libc-internal includes */
|
||||
#include <internal/init.h>
|
||||
#include <internal/types.h>
|
||||
|
||||
namespace Libc { struct Atexit; }
|
||||
|
||||
|
||||
struct Libc::Atexit : Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
using Allocator = Genode::Allocator;
|
||||
|
||||
Allocator &_alloc;
|
||||
|
||||
struct Handler : List<Handler>::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<Handler> _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_ */
|
@ -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_ */
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <internal/monitor.h>
|
||||
#include <internal/pthread.h>
|
||||
#include <internal/cwd.h>
|
||||
#include <internal/atexit.h>
|
||||
|
||||
namespace Libc {
|
||||
class Kernel;
|
||||
@ -192,6 +193,8 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
||||
|
||||
Signal _signal { _pid };
|
||||
|
||||
Atexit _atexit { _heap };
|
||||
|
||||
Reconstructible<Io_signal_handler<Kernel>> _resume_main_handler {
|
||||
_env.ep(), *this, &Kernel::_resume_main };
|
||||
|
||||
|
@ -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);
|
||||
|
@ -4,7 +4,7 @@ From: Christian Prochaska <christian.prochaska@genode-labs.com>
|
||||
|
||||
|
||||
---
|
||||
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 <christian.prochaska@genode-labs.com>
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user