diff --git a/options/ansi/generic/stdlib-stubs.cpp b/options/ansi/generic/stdlib-stubs.cpp index 188e9026..d4d0aa67 100644 --- a/options/ansi/generic/stdlib-stubs.cpp +++ b/options/ansi/generic/stdlib-stubs.cpp @@ -205,9 +205,35 @@ void *calloc(size_t count, size_t size) { // realloc() is provided by the platform void abort(void) { - __ensure(!"Not implemented"); - __builtin_unreachable(); + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGABRT); + if (mlibc::sys_sigprocmask) { + mlibc::sys_sigprocmask(SIG_UNBLOCK, &set, nullptr); + } + + raise(SIGABRT); + + sigfillset(&set); + sigdelset(&set, SIGABRT); + if (mlibc::sys_sigprocmask) { + mlibc::sys_sigprocmask(SIG_SETMASK, &set, nullptr); + } + + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + + if (mlibc::sys_sigaction(SIGABRT, &sa, nullptr)) + mlibc::panicLogger() << "mlibc: sigaction failed in abort" << frg::endlog; + + if (raise(SIGABRT)) + mlibc::panicLogger() << "mlibc: raise failed in abort" << frg::endlog; + + __builtin_trap(); } + int atexit(void (*func)(void)) { // TODO: the function pointer types are not compatible; // the conversion here is undefined behavior. its fine to do diff --git a/tests/meson.build b/tests/meson.build index ad82fdaf..9ab719c2 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -30,6 +30,10 @@ posix_test_cases = [ 'system' # This test should be in the ANSI tests, but it depends on sys/wait.h ] +posix_fail_test_cases = [ + 'abort' # This test should be in the ANSI tests, but it depends on sigaction +] + glibc_test_cases = [ 'getopt' ] @@ -65,6 +69,16 @@ if not disable_posix_option '-no-pie']) test('posix/' + f, exec) endforeach + + foreach f : posix_fail_test_cases + exec = executable('posix-' + f, ['posix/' + f + '.c', test_sources], + link_with: libc, include_directories: libc_include_dirs, + build_rpath: meson.build_root(), + c_args: '-no-pie', + link_args: ['-Wl,--dynamic-linker=' + meson.build_root() + '/ld.so', + '-no-pie']) + test('posix/' + f, exec, should_fail: true) + endforeach endif # We never disable the posix option so glibc is gated behind the posix option here. diff --git a/tests/posix/abort.c b/tests/posix/abort.c new file mode 100644 index 00000000..ea754ea5 --- /dev/null +++ b/tests/posix/abort.c @@ -0,0 +1,17 @@ +#include +#include +#include + +void handler(int sig, siginfo_t *info, void *ctx) { } + +int main() { + struct sigaction sa; + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + + int ret = sigaction(SIGABRT, &sa, NULL); + assert(!ret); + + abort(); +}