1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 // This file implements the default terminate_handler, unexpected_handler and
10 //===----------------------------------------------------------------------===//
15 #include "abort_message.h"
17 #include "cxa_handlers.h"
18 #include "cxa_exception.h"
19 #include "private_typeinfo.h"
20 #include "include/atomic_support.h" // from libc++
22 #if !defined(LIBCXXABI_SILENT_TERMINATE)
24 static constinit
const char* cause
= "uncaught";
26 #ifndef _LIBCXXABI_NO_EXCEPTIONS
27 // Demangle the given string, or return the string as-is in case of an error.
28 static std::unique_ptr
<char const, void (*)(char const*)> demangle(char const* str
)
30 #if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE)
31 if (const char* result
= __cxxabiv1::__cxa_demangle(str
, nullptr, nullptr, nullptr))
32 return {result
, [](char const* p
) { std::free(const_cast<char*>(p
)); }};
34 return {str
, [](char const*) { /* nothing to free */ }};
37 __attribute__((noreturn
))
38 static void demangling_terminate_handler()
40 using namespace __cxxabiv1
;
41 __cxa_eh_globals
* globals
= __cxa_get_globals_fast();
43 // If there is no uncaught exception, just note that we're terminating
45 abort_message("terminating");
47 __cxa_exception
* exception_header
= globals
->caughtExceptions
;
48 if (!exception_header
)
49 abort_message("terminating");
51 _Unwind_Exception
* unwind_exception
=
52 reinterpret_cast<_Unwind_Exception
*>(exception_header
+ 1) - 1;
54 // If we're terminating due to a foreign exception
55 if (!__isOurExceptionClass(unwind_exception
))
56 abort_message("terminating due to %s foreign exception", cause
);
59 __getExceptionClass(unwind_exception
) == kOurDependentExceptionClass
?
60 ((__cxa_dependent_exception
*)exception_header
)->primaryException
:
62 const __shim_type_info
* thrown_type
=
63 static_cast<const __shim_type_info
*>(exception_header
->exceptionType
);
64 auto name
= demangle(thrown_type
->name());
65 // If the uncaught exception can be caught with std::exception&
66 const __shim_type_info
* catch_type
=
67 static_cast<const __shim_type_info
*>(&typeid(std::exception
));
68 if (catch_type
->can_catch(thrown_type
, thrown_object
))
70 // Include the what() message from the exception
71 const std::exception
* e
= static_cast<const std::exception
*>(thrown_object
);
72 abort_message("terminating due to %s exception of type %s: %s", cause
, name
.get(), e
->what());
76 // Else just note that we're terminating due to an exception
77 abort_message("terminating due to %s exception of type %s", cause
, name
.get());
80 #else // !_LIBCXXABI_NO_EXCEPTIONS
81 __attribute__((noreturn
))
82 static void demangling_terminate_handler()
84 abort_message("terminating");
86 #endif // !_LIBCXXABI_NO_EXCEPTIONS
88 __attribute__((noreturn
))
89 static void demangling_unexpected_handler()
95 static constexpr std::terminate_handler default_terminate_handler
= demangling_terminate_handler
;
96 static constexpr std::terminate_handler default_unexpected_handler
= demangling_unexpected_handler
;
97 #else // !LIBCXXABI_SILENT_TERMINATE
98 static constexpr std::terminate_handler default_terminate_handler
= ::abort
;
99 static constexpr std::terminate_handler default_unexpected_handler
= std::terminate
;
100 #endif // !LIBCXXABI_SILENT_TERMINATE
103 // Global variables that hold the pointers to the current handler
106 constinit
std::terminate_handler __cxa_terminate_handler
= default_terminate_handler
;
109 constinit
std::unexpected_handler __cxa_unexpected_handler
= default_unexpected_handler
;
112 constinit
std::new_handler __cxa_new_handler
= nullptr;
118 set_unexpected(unexpected_handler func
) noexcept
121 func
= default_unexpected_handler
;
122 return __libcpp_atomic_exchange(&__cxa_unexpected_handler
, func
,
127 set_terminate(terminate_handler func
) noexcept
130 func
= default_terminate_handler
;
131 return __libcpp_atomic_exchange(&__cxa_terminate_handler
, func
,
136 set_new_handler(new_handler handler
) noexcept
138 return __libcpp_atomic_exchange(&__cxa_new_handler
, handler
, _AO_Acq_Rel
);