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 23namespace std 24{ 25 26unexpected_handler 27get_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)) 36void 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)) 45void 46unexpected() 47{ 48 __unexpected(get_unexpected()); 49} 50 51terminate_handler 52get_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)) 61void 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)) 82void 83terminate() _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 105extern "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 109new_handler 110set_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 117new_handler 118get_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