1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //
8 // This file implements the default terminate_handler, unexpected_handler and
9 // new_handler.
10 //===----------------------------------------------------------------------===//
11 
12 #include <exception>
13 #include <stdlib.h>
14 #include "abort_message.h"
15 #include "cxxabi.h"
16 #include "cxa_handlers.h"
17 #include "cxa_exception.h"
18 #include "private_typeinfo.h"
19 #include "include/atomic_support.h" // from libc++
20 
21 #if !defined(LIBCXXABI_SILENT_TERMINATE)
22 
23 _LIBCPP_SAFE_STATIC
24 static const char* cause = "uncaught";
25 
26 __attribute__((noreturn))
27 static void demangling_terminate_handler()
28 {
29 #ifndef _LIBCXXABI_NO_EXCEPTIONS
30     // If there might be an uncaught exception
31     using namespace __cxxabiv1;
32     __cxa_eh_globals* globals = __cxa_get_globals_fast();
33     if (globals)
34     {
35         __cxa_exception* exception_header = globals->caughtExceptions;
36         // If there is an uncaught exception
37         if (exception_header)
38         {
39             _Unwind_Exception* unwind_exception =
40                 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
41             if (__isOurExceptionClass(unwind_exception))
42             {
43                 void* thrown_object =
44                     __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ?
45                         ((__cxa_dependent_exception*)exception_header)->primaryException :
46                         exception_header + 1;
47                 const __shim_type_info* thrown_type =
48                     static_cast<const __shim_type_info*>(exception_header->exceptionType);
49 #if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE)
50                 // Try to get demangled name of thrown_type
51                 int status;
52                 char buf[1024];
53                 size_t len = sizeof(buf);
54                 const char* name = __cxa_demangle(thrown_type->name(), buf, &len, &status);
55                 if (status != 0)
56                     name = thrown_type->name();
57 #else
58                 const char* name = thrown_type->name();
59 #endif
60                 // If the uncaught exception can be caught with std::exception&
61                 const __shim_type_info* catch_type =
62                     static_cast<const __shim_type_info*>(&typeid(std::exception));
63                 if (catch_type->can_catch(thrown_type, thrown_object))
64                 {
65                     // Include the what() message from the exception
66                     const std::exception* e = static_cast<const std::exception*>(thrown_object);
67                     abort_message("terminating with %s exception of type %s: %s",
68                                   cause, name, e->what());
69                 }
70                 else
71                     // Else just note that we're terminating with an exception
72                     abort_message("terminating with %s exception of type %s",
73                                    cause, name);
74             }
75             else
76                 // Else we're terminating with a foreign exception
77                 abort_message("terminating with %s foreign exception", cause);
78         }
79     }
80 #endif
81     // Else just note that we're terminating
82     abort_message("terminating");
83 }
84 
85 __attribute__((noreturn))
86 static void demangling_unexpected_handler()
87 {
88     cause = "unexpected";
89     std::terminate();
90 }
91 
92 static constexpr std::terminate_handler default_terminate_handler = demangling_terminate_handler;
93 static constexpr std::terminate_handler default_unexpected_handler = demangling_unexpected_handler;
94 #else
95 static constexpr std::terminate_handler default_terminate_handler = ::abort;
96 static constexpr std::terminate_handler default_unexpected_handler = std::terminate;
97 #endif
98 
99 //
100 // Global variables that hold the pointers to the current handler
101 //
102 _LIBCXXABI_DATA_VIS
103 _LIBCPP_SAFE_STATIC std::terminate_handler __cxa_terminate_handler = default_terminate_handler;
104 
105 _LIBCXXABI_DATA_VIS
106 _LIBCPP_SAFE_STATIC std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;
107 
108 _LIBCXXABI_DATA_VIS
109 _LIBCPP_SAFE_STATIC std::new_handler __cxa_new_handler = 0;
110 
111 namespace std
112 {
113 
114 unexpected_handler
115 set_unexpected(unexpected_handler func) noexcept
116 {
117     if (func == 0)
118         func = default_unexpected_handler;
119     return __libcpp_atomic_exchange(&__cxa_unexpected_handler, func,
120                                     _AO_Acq_Rel);
121 }
122 
123 terminate_handler
124 set_terminate(terminate_handler func) noexcept
125 {
126     if (func == 0)
127         func = default_terminate_handler;
128     return __libcpp_atomic_exchange(&__cxa_terminate_handler, func,
129                                     _AO_Acq_Rel);
130 }
131 
132 new_handler
133 set_new_handler(new_handler handler) noexcept
134 {
135     return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
136 }
137 
138 }
139