1 //===------------------------- cxa_handlers.cpp ---------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 // 9 // This file implements the functionality associated with the terminate_handler, 10 // unexpected_handler, and new_handler. 11 //===----------------------------------------------------------------------===// 12 13 #include <stdexcept> 14 #include <new> 15 #include <exception> 16 #include "abort_message.h" 17 #include "config.h" 18 #include "cxxabi.h" 19 #include "cxa_handlers.hpp" 20 #include "cxa_exception.hpp" 21 #include "private_typeinfo.h" 22 23 namespace std 24 { 25 26 unexpected_handler 27 get_unexpected() _NOEXCEPT 28 { 29 return __sync_fetch_and_add(&__cxa_unexpected_handler, (unexpected_handler)0); 30 // The above is safe but overkill on x86 31 // Using of C++11 atomics this should be rewritten 32 // return __cxa_unexpected_handler.load(memory_order_acq); 33 } 34 35 __attribute__((visibility("hidden"), noreturn)) 36 void 37 __unexpected(unexpected_handler func) 38 { 39 func(); 40 // unexpected handler should not return 41 abort_message("unexpected_handler unexpectedly returned"); 42 } 43 44 __attribute__((noreturn)) 45 void 46 unexpected() 47 { 48 __unexpected(get_unexpected()); 49 } 50 51 terminate_handler 52 get_terminate() _NOEXCEPT 53 { 54 return __sync_fetch_and_add(&__cxa_terminate_handler, (terminate_handler)0); 55 // The above is safe but overkill on x86 56 // Using of C++11 atomics this should be rewritten 57 // return __cxa_terminate_handler.load(memory_order_acq); 58 } 59 60 __attribute__((visibility("hidden"), noreturn)) 61 void 62 __terminate(terminate_handler func) _NOEXCEPT 63 { 64 #if __has_feature(cxx_exceptions) 65 try 66 { 67 #endif // __has_feature(cxx_exceptions) 68 func(); 69 // handler should not return 70 abort_message("terminate_handler unexpectedly returned"); 71 #if __has_feature(cxx_exceptions) 72 } 73 catch (...) 74 { 75 // handler should not throw exception 76 abort_message("terminate_handler unexpectedly threw an exception"); 77 } 78 #endif // #if __has_feature(cxx_exceptions) 79 } 80 81 __attribute__((noreturn)) 82 void 83 terminate() _NOEXCEPT 84 { 85 // If there might be an uncaught exception 86 using namespace __cxxabiv1; 87 __cxa_eh_globals* globals = __cxa_get_globals_fast(); 88 if (globals) 89 { 90 __cxa_exception* exception_header = globals->caughtExceptions; 91 if (exception_header) 92 { 93 _Unwind_Exception* unwind_exception = 94 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; 95 bool native_exception = 96 (unwind_exception->exception_class & get_vendor_and_language) == 97 (kOurExceptionClass & get_vendor_and_language); 98 if (native_exception) 99 __terminate(exception_header->terminateHandler); 100 } 101 } 102 __terminate(get_terminate()); 103 } 104 105 extern "C" new_handler __cxa_new_handler = 0; 106 // In the future these will become: 107 // std::atomic<std::new_handler> __cxa_new_handler(0); 108 109 new_handler 110 set_new_handler(new_handler handler) _NOEXCEPT 111 { 112 return __sync_swap(&__cxa_new_handler, handler); 113 // Using of C++11 atomics this should be rewritten 114 // return __cxa_new_handler.exchange(handler, memory_order_acq_rel); 115 } 116 117 new_handler 118 get_new_handler() _NOEXCEPT 119 { 120 return __sync_fetch_and_add(&__cxa_new_handler, (new_handler)0); 121 // The above is safe but overkill on x86 122 // Using of C++11 atomics this should be rewritten 123 // return __cxa_new_handler.load(memory_order_acq); 124 } 125 126 } // std 127