blob: 8110f6c1403f74a33008fb3abedcc1c121316401 [file] [log] [blame]
Nick Kledzik778324a2012-03-15 01:52:12 +00001//===------------------------- cxa_default_handlers.cpp -------------------===//
2//
Chandler Carruth57b08b02019-01-19 10:56:40 +00003// 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
Nick Kledzik778324a2012-03-15 01:52:12 +00006//
7//
8// This file implements the default terminate_handler and unexpected_handler.
9//===----------------------------------------------------------------------===//
10
11#include <stdexcept>
12#include <new>
13#include <exception>
James Y Knight0d3145f2017-01-13 19:22:26 +000014#include <cstdlib>
Nick Kledzik778324a2012-03-15 01:52:12 +000015#include "abort_message.h"
16#include "cxxabi.h"
17#include "cxa_handlers.hpp"
18#include "cxa_exception.hpp"
19#include "private_typeinfo.h"
Eli Friedman17a47b92018-04-16 22:00:14 +000020#include "include/atomic_support.h"
Nick Kledzik778324a2012-03-15 01:52:12 +000021
Peter Collingbournea674a8f2018-01-25 01:38:43 +000022#if !defined(LIBCXXABI_SILENT_TERMINATE)
Howard Hinnant2b853bf2013-02-06 19:29:55 +000023static const char* cause = "uncaught";
24
Nick Kledzik778324a2012-03-15 01:52:12 +000025__attribute__((noreturn))
James Y Knight0d3145f2017-01-13 19:22:26 +000026static void demangling_terminate_handler()
Nick Kledzik778324a2012-03-15 01:52:12 +000027{
28 // If there might be an uncaught exception
29 using namespace __cxxabiv1;
30 __cxa_eh_globals* globals = __cxa_get_globals_fast();
31 if (globals)
32 {
33 __cxa_exception* exception_header = globals->caughtExceptions;
34 // If there is an uncaught exception
35 if (exception_header)
36 {
37 _Unwind_Exception* unwind_exception =
38 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
Marshall Clow611a55a2018-10-10 16:18:37 +000039 if (__isOurExceptionClass(unwind_exception))
Nick Kledzik778324a2012-03-15 01:52:12 +000040 {
41 void* thrown_object =
Marshall Clow611a55a2018-10-10 16:18:37 +000042 __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ?
Nick Kledzik778324a2012-03-15 01:52:12 +000043 ((__cxa_dependent_exception*)exception_header)->primaryException :
44 exception_header + 1;
45 const __shim_type_info* thrown_type =
46 static_cast<const __shim_type_info*>(exception_header->exceptionType);
47 // Try to get demangled name of thrown_type
48 int status;
49 char buf[1024];
50 size_t len = sizeof(buf);
51 const char* name = __cxa_demangle(thrown_type->name(), buf, &len, &status);
52 if (status != 0)
53 name = thrown_type->name();
54 // If the uncaught exception can be caught with std::exception&
55 const __shim_type_info* catch_type =
56 static_cast<const __shim_type_info*>(&typeid(std::exception));
57 if (catch_type->can_catch(thrown_type, thrown_object))
58 {
59 // Include the what() message from the exception
60 const std::exception* e = static_cast<const std::exception*>(thrown_object);
61 abort_message("terminating with %s exception of type %s: %s",
62 cause, name, e->what());
63 }
64 else
65 // Else just note that we're terminating with an exception
66 abort_message("terminating with %s exception of type %s",
67 cause, name);
68 }
69 else
70 // Else we're terminating with a foreign exception
71 abort_message("terminating with %s foreign exception", cause);
72 }
73 }
74 // Else just note that we're terminating
75 abort_message("terminating");
76}
77
Howard Hinnant4ac72dd2012-03-19 16:20:34 +000078__attribute__((noreturn))
James Y Knight0d3145f2017-01-13 19:22:26 +000079static void demangling_unexpected_handler()
Nick Kledzik778324a2012-03-15 01:52:12 +000080{
Howard Hinnant2b853bf2013-02-06 19:29:55 +000081 cause = "unexpected";
82 std::terminate();
Nick Kledzik778324a2012-03-15 01:52:12 +000083}
84
James Y Knight0d3145f2017-01-13 19:22:26 +000085static std::terminate_handler default_terminate_handler = demangling_terminate_handler;
86static std::terminate_handler default_unexpected_handler = demangling_unexpected_handler;
87#else
88static std::terminate_handler default_terminate_handler = std::abort;
Asiri Rathnayaked717ce52017-02-15 13:43:05 +000089static std::terminate_handler default_unexpected_handler = std::terminate;
James Y Knight0d3145f2017-01-13 19:22:26 +000090#endif
Nick Kledzik778324a2012-03-15 01:52:12 +000091
92//
93// Global variables that hold the pointers to the current handler
94//
Saleem Abdulrasool18ef5642016-05-26 02:12:20 +000095_LIBCXXABI_DATA_VIS
96std::terminate_handler __cxa_terminate_handler = default_terminate_handler;
97
98_LIBCXXABI_DATA_VIS
Nick Kledzik778324a2012-03-15 01:52:12 +000099std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;
Dave Zarzycki13e35c02012-03-15 08:58:06 +0000100
101namespace std
102{
103
104unexpected_handler
105set_unexpected(unexpected_handler func) _NOEXCEPT
106{
Reid Klecknercf6b0c62014-10-03 20:03:47 +0000107 if (func == 0)
108 func = default_unexpected_handler;
Eli Friedman17a47b92018-04-16 22:00:14 +0000109 return __libcpp_atomic_exchange(&__cxa_unexpected_handler, func,
110 _AO_Acq_Rel);
Dave Zarzycki13e35c02012-03-15 08:58:06 +0000111}
112
113terminate_handler
114set_terminate(terminate_handler func) _NOEXCEPT
115{
Reid Klecknercf6b0c62014-10-03 20:03:47 +0000116 if (func == 0)
117 func = default_terminate_handler;
Eli Friedman17a47b92018-04-16 22:00:14 +0000118 return __libcpp_atomic_exchange(&__cxa_terminate_handler, func,
119 _AO_Acq_Rel);
Dave Zarzycki13e35c02012-03-15 08:58:06 +0000120}
121
Howard Hinnante59dbd72012-03-19 16:56:51 +0000122}