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