1*8f1d5724Srobert //===----------------------------------------------------------------------===//
279c2e3e6Spatrick //
379c2e3e6Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
479c2e3e6Spatrick // See https://llvm.org/LICENSE.txt for license information.
579c2e3e6Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
679c2e3e6Spatrick //
779c2e3e6Spatrick //
8*8f1d5724Srobert // This file implements the default terminate_handler, unexpected_handler and
9*8f1d5724Srobert // new_handler.
1079c2e3e6Spatrick //===----------------------------------------------------------------------===//
1179c2e3e6Spatrick
1279c2e3e6Spatrick #include <exception>
13*8f1d5724Srobert #include <memory>
1479c2e3e6Spatrick #include <stdlib.h>
1579c2e3e6Spatrick #include "abort_message.h"
1679c2e3e6Spatrick #include "cxxabi.h"
1779c2e3e6Spatrick #include "cxa_handlers.h"
1879c2e3e6Spatrick #include "cxa_exception.h"
1979c2e3e6Spatrick #include "private_typeinfo.h"
20*8f1d5724Srobert #include "include/atomic_support.h" // from libc++
2179c2e3e6Spatrick
2279c2e3e6Spatrick #if !defined(LIBCXXABI_SILENT_TERMINATE)
2379c2e3e6Spatrick
24*8f1d5724Srobert static constinit const char* cause = "uncaught";
25*8f1d5724Srobert
26*8f1d5724Srobert #ifndef _LIBCXXABI_NO_EXCEPTIONS
27*8f1d5724Srobert // Demangle the given string, or return the string as-is in case of an error.
demangle(char const * str)28*8f1d5724Srobert static std::unique_ptr<char const, void (*)(char const*)> demangle(char const* str)
29*8f1d5724Srobert {
30*8f1d5724Srobert #if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE)
31*8f1d5724Srobert if (const char* result = __cxxabiv1::__cxa_demangle(str, nullptr, nullptr, nullptr))
32*8f1d5724Srobert return {result, [](char const* p) { std::free(const_cast<char*>(p)); }};
33*8f1d5724Srobert #endif
34*8f1d5724Srobert return {str, [](char const*) { /* nothing to free */ }};
35*8f1d5724Srobert }
3679c2e3e6Spatrick
3779c2e3e6Spatrick __attribute__((noreturn))
demangling_terminate_handler()3879c2e3e6Spatrick static void demangling_terminate_handler()
3979c2e3e6Spatrick {
4079c2e3e6Spatrick using namespace __cxxabiv1;
4179c2e3e6Spatrick __cxa_eh_globals* globals = __cxa_get_globals_fast();
42*8f1d5724Srobert
43*8f1d5724Srobert // If there is no uncaught exception, just note that we're terminating
44*8f1d5724Srobert if (!globals)
45*8f1d5724Srobert abort_message("terminating");
46*8f1d5724Srobert
4779c2e3e6Spatrick __cxa_exception* exception_header = globals->caughtExceptions;
48*8f1d5724Srobert if (!exception_header)
49*8f1d5724Srobert abort_message("terminating");
50*8f1d5724Srobert
5179c2e3e6Spatrick _Unwind_Exception* unwind_exception =
5279c2e3e6Spatrick reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
53*8f1d5724Srobert
54*8f1d5724Srobert // If we're terminating due to a foreign exception
55*8f1d5724Srobert if (!__isOurExceptionClass(unwind_exception))
56*8f1d5724Srobert abort_message("terminating due to %s foreign exception", cause);
57*8f1d5724Srobert
5879c2e3e6Spatrick void* thrown_object =
5979c2e3e6Spatrick __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ?
6079c2e3e6Spatrick ((__cxa_dependent_exception*)exception_header)->primaryException :
6179c2e3e6Spatrick exception_header + 1;
6279c2e3e6Spatrick const __shim_type_info* thrown_type =
6379c2e3e6Spatrick static_cast<const __shim_type_info*>(exception_header->exceptionType);
64*8f1d5724Srobert auto name = demangle(thrown_type->name());
6579c2e3e6Spatrick // If the uncaught exception can be caught with std::exception&
6679c2e3e6Spatrick const __shim_type_info* catch_type =
6779c2e3e6Spatrick static_cast<const __shim_type_info*>(&typeid(std::exception));
6879c2e3e6Spatrick if (catch_type->can_catch(thrown_type, thrown_object))
6979c2e3e6Spatrick {
7079c2e3e6Spatrick // Include the what() message from the exception
7179c2e3e6Spatrick const std::exception* e = static_cast<const std::exception*>(thrown_object);
72*8f1d5724Srobert abort_message("terminating due to %s exception of type %s: %s", cause, name.get(), e->what());
7379c2e3e6Spatrick }
7479c2e3e6Spatrick else
75*8f1d5724Srobert {
76*8f1d5724Srobert // Else just note that we're terminating due to an exception
77*8f1d5724Srobert abort_message("terminating due to %s exception of type %s", cause, name.get());
7879c2e3e6Spatrick }
7979c2e3e6Spatrick }
80*8f1d5724Srobert #else // !_LIBCXXABI_NO_EXCEPTIONS
81*8f1d5724Srobert __attribute__((noreturn))
demangling_terminate_handler()82*8f1d5724Srobert static void demangling_terminate_handler()
83*8f1d5724Srobert {
8479c2e3e6Spatrick abort_message("terminating");
8579c2e3e6Spatrick }
86*8f1d5724Srobert #endif // !_LIBCXXABI_NO_EXCEPTIONS
8779c2e3e6Spatrick
8879c2e3e6Spatrick __attribute__((noreturn))
demangling_unexpected_handler()8979c2e3e6Spatrick static void demangling_unexpected_handler()
9079c2e3e6Spatrick {
9179c2e3e6Spatrick cause = "unexpected";
9279c2e3e6Spatrick std::terminate();
9379c2e3e6Spatrick }
9479c2e3e6Spatrick
9579c2e3e6Spatrick static constexpr std::terminate_handler default_terminate_handler = demangling_terminate_handler;
9679c2e3e6Spatrick static constexpr std::terminate_handler default_unexpected_handler = demangling_unexpected_handler;
97*8f1d5724Srobert #else // !LIBCXXABI_SILENT_TERMINATE
9879c2e3e6Spatrick static constexpr std::terminate_handler default_terminate_handler = ::abort;
9979c2e3e6Spatrick static constexpr std::terminate_handler default_unexpected_handler = std::terminate;
100*8f1d5724Srobert #endif // !LIBCXXABI_SILENT_TERMINATE
10179c2e3e6Spatrick
10279c2e3e6Spatrick //
10379c2e3e6Spatrick // Global variables that hold the pointers to the current handler
10479c2e3e6Spatrick //
10579c2e3e6Spatrick _LIBCXXABI_DATA_VIS
106*8f1d5724Srobert constinit std::terminate_handler __cxa_terminate_handler = default_terminate_handler;
10779c2e3e6Spatrick
10879c2e3e6Spatrick _LIBCXXABI_DATA_VIS
109*8f1d5724Srobert constinit std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;
110*8f1d5724Srobert
111*8f1d5724Srobert _LIBCXXABI_DATA_VIS
112*8f1d5724Srobert constinit std::new_handler __cxa_new_handler = nullptr;
11379c2e3e6Spatrick
11479c2e3e6Spatrick namespace std
11579c2e3e6Spatrick {
11679c2e3e6Spatrick
11779c2e3e6Spatrick unexpected_handler
set_unexpected(unexpected_handler func)1184e0cc08cSpatrick set_unexpected(unexpected_handler func) noexcept
11979c2e3e6Spatrick {
12079c2e3e6Spatrick if (func == 0)
12179c2e3e6Spatrick func = default_unexpected_handler;
12279c2e3e6Spatrick return __libcpp_atomic_exchange(&__cxa_unexpected_handler, func,
12379c2e3e6Spatrick _AO_Acq_Rel);
12479c2e3e6Spatrick }
12579c2e3e6Spatrick
12679c2e3e6Spatrick terminate_handler
set_terminate(terminate_handler func)1274e0cc08cSpatrick set_terminate(terminate_handler func) noexcept
12879c2e3e6Spatrick {
12979c2e3e6Spatrick if (func == 0)
13079c2e3e6Spatrick func = default_terminate_handler;
13179c2e3e6Spatrick return __libcpp_atomic_exchange(&__cxa_terminate_handler, func,
13279c2e3e6Spatrick _AO_Acq_Rel);
13379c2e3e6Spatrick }
13479c2e3e6Spatrick
135*8f1d5724Srobert new_handler
set_new_handler(new_handler handler)136*8f1d5724Srobert set_new_handler(new_handler handler) noexcept
137*8f1d5724Srobert {
138*8f1d5724Srobert return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
139*8f1d5724Srobert }
140*8f1d5724Srobert
14179c2e3e6Spatrick }
142