cxa_exception.cpp revision 57d64cd19aee4b6cf4acf6184a3f5d454bb69e9d
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===------------------------- cxa_exception.cpp --------------------------===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is dual licensed under the MIT and the University of Illinois Open 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// Source Licenses. See LICENSE.TXT for details. 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements the "Exception Handling APIs" 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// http://www.codesourcery.com/public/cxx-abi/abi-eh.html 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "cxxabi.h" 152eadfb638eb1bb6ccfd6fd0453e764d47e27eed9Chris Lattner 165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <exception> // for std::terminate 17c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#include <cstdlib> // for malloc, free 18da5a6b6d9fd52899499d5b7b46273ec844dcaa6eChris Lattner#include <string> // for memset 198a99764f9b778a54e7440b1ee06a1e48f25d76d8Nate Begeman#include <pthread.h> 208a99764f9b778a54e7440b1ee06a1e48f25d76d8Nate Begeman 215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "cxa_exception.hpp" 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "cxa_handlers.hpp" 235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencernamespace __cxxabiv1 { 255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC++\0 265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1 275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Utility routines 295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline __cxa_exception *exception_from_thrown_object(void *p) throw() { 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ((__cxa_exception *) p) - 1; 315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline void * thrown_object_from_exception(void *p) throw() { 345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return (void *) (((__cxa_exception *) p) + 1 ); 355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline size_t object_size_from_exception_size(size_t size) throw() { 385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return size + sizeof (__cxa_exception); 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Get the exception object from the unwind pointer. 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Relies on the structure layout, where the unwind pointer is right in 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// front of the user's exception object 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic __cxa_exception * 455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerexception_from_exception_object(void *ptr) throw() { 465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer _Unwind_Exception *p = reinterpret_cast<_Unwind_Exception *>(ptr); 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return exception_from_thrown_object(p + 1 ); 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void setExceptionClass(_Unwind_Exception *unwind) throw() { 515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unwind->exception_class = kOurExceptionClass; 525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void setDependentExceptionClass(_Unwind_Exception *unwind) throw() { 555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unwind->exception_class = kOurDependentExceptionClass; 565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Is it one of ours? 595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic bool isOurExceptionClass(_Unwind_Exception *unwind) throw() { 605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return(unwind->exception_class == kOurExceptionClass)|| 615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (unwind->exception_class == kOurDependentExceptionClass); 625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic bool isDependentException(_Unwind_Exception *unwind) throw() { 655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return (unwind->exception_class & 0xFF) == 0x01; 665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This does not need to be atomic 695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline int incrementHandlerCount(__cxa_exception *exception) throw() { 705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ++exception->handlerCount; 715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This does not need to be atomic 745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic inline int decrementHandlerCount(__cxa_exception *exception) throw() { 7573d0d4fac161ed12926e010dcf8b448a8de6a2ecChris Lattner return --exception->handlerCount; 765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "fallback_malloc.cpp" 795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Allocate some memory from _somewhere_ 815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void *do_malloc(size_t size) throw() { 825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer void *ptr = std::malloc(size); 83e2ce1d9440186cf3332368291cd884a6e3ae8946Nate Begeman if (NULL == ptr) // if malloc fails, fall back to emergency stash 845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ptr = fallback_malloc(size); 855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ptr; 8677ed8e4edf6ed78c53fb20ec3210aff2a59c9d87Ted Kremenek} 8777ed8e4edf6ed78c53fb20ec3210aff2a59c9d87Ted Kremenek 8877ed8e4edf6ed78c53fb20ec3210aff2a59c9d87Ted Kremenek// Didn't know you could "return <expression>" from a void function, did you? 895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Well, you can, if the type of the expression is "void" also. 9077ed8e4edf6ed78c53fb20ec3210aff2a59c9d87Ted Kremenekstatic void do_free(void *ptr) throw() { 915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return is_fallback_ptr(ptr) ? fallback_free(ptr) : std::free(ptr); 925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 94d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner/* 95d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler 96d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner stored in exc is called. Otherwise the exceptionDestructor stored in 97d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner exc is called, and then the memory for the exception is deallocated. 98d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner*/ 99d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattnerstatic void exception_cleanup_func(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc) { 100d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner __cxa_exception *exception = exception_from_exception_object(exc); 101d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason) 102d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner std::__terminate(exception->terminateHandler); 103d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner 104d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner void * thrown_object = thrown_object_from_exception(exception); 105d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner if (NULL != exception->exceptionDestructor) 106d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner exception->exceptionDestructor(thrown_object); 107d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner __cxa_free_exception(thrown_object); 108d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner} 109d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner 110d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattnerstatic LIBCXXABI_NORETURN void failed_throw(__cxa_exception *exception) throw() { 111d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner// Section 2.5.3 says: 112d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner// * For purposes of this ABI, several things are considered exception handlers: 113d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner// ** A terminate() call due to a throw. 114d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner// and 115d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner// * Upon entry, Following initialization of the catch parameter, 116d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner// a handler must call: 117d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner// * void *__cxa_begin_catch(void *exceptionObject ); 118d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner (void) __cxa_begin_catch(&exception->unwindHeader); 119d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner std::__terminate(exception->terminateHandler); 120d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner} 121d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner 122d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattnerextern "C" { 123c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff 124c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff// Allocate a __cxa_exception object, and zero-fill it. 125c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff// Reserve "thrown_size" bytes on the end for the user's exception 126c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff// object. Zero-fill the object. If memory can't be allocated, call 127c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff// std::terminate. Return a pointer to the memory to be used for the 128c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff// user's exception object. 129c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroffvoid * __cxa_allocate_exception (size_t thrown_size) throw() { 130c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff size_t actual_size = object_size_from_exception_size(thrown_size); 131c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff void *ptr = do_malloc(actual_size); 132c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff if (NULL == ptr) 133c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff std::terminate(); 134c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff std::memset(ptr, 0, actual_size); 135bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson return thrown_object_from_exception(ptr); 136bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson} 137bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson 138bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson 139bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson// Free a __cxa_exception object allocated with __cxa_allocate_exception. 140bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlssonvoid __cxa_free_exception (void * thrown_exception) throw() { 141bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson do_free(exception_from_thrown_object(thrown_exception)); 142bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson} 143bcba201a1118d7852b8b97187d495ae2a4f49519Anders Carlsson 144861dc46e3c53d64d8685fd9a0f95faac710b61c6Eli Friedman 145861dc46e3c53d64d8685fd9a0f95faac710b61c6Eli Friedman// This function shall allocate a __cxa_dependent_exception and 146c4f8e8b645b8e0e685c089dde0674c6f29a24168Steve Naroff// return a pointer to it. (Really to the object, not past its' end). 147d18b3299debb7b0dbd9d34d9369189dc98c87f53Chris Lattner// Otherwise, it will work like __cxa_allocate_exception. 14813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffvoid * __cxa_allocate_dependent_exception () throw() { 14913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff size_t actual_size = sizeof(__cxa_dependent_exception); 15013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff void *ptr = do_malloc(actual_size); 15113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff if (NULL == ptr) 15213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff std::terminate(); 15313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff std::memset(ptr, 0, actual_size); 15413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff return ptr; 15513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff} 15613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 15713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 15813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff// This function shall free a dependent_exception. 15913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff// It does not affect the reference count of the primary exception. 16013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffvoid __cxa_free_dependent_exception (void * dependent_exception) throw() { 16113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff do_free(dependent_exception); 16213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff} 16313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 16413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 16513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff// 2.4.3 Throwing the Exception Object 16613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff/* 16713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve NaroffAfter constructing the exception object with the throw argument value, 16813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffthe generated code calls the __cxa_throw runtime library routine. This 16913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffroutine never returns. 17013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 17113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve NaroffThe __cxa_throw routine will do the following: 17213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 17313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Obtain the __cxa_exception header from the thrown exception object address, 17413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffwhich can be computed as follows: 17513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1); 17613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Save the current unexpected_handler and terminate_handler in the __cxa_exception header. 17713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Save the tinfo and dest arguments in the __cxa_exception header. 17813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Set the exception_class field in the unwind header. This is a 64-bit value 17913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffrepresenting the ASCII string "XXXXC++\0", where "XXXX" is a 18013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffvendor-dependent string. That is, for implementations conforming to this 18113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve NaroffABI, the low-order 4 bytes of this 64-bit value will be "C++\0". 18213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Increment the uncaught_exception flag. 18313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff* Call _Unwind_RaiseException in the system unwind library, Its argument is the 18413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffpointer to the thrown exception, which __cxa_throw itself received as an argument. 18513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff__Unwind_RaiseException begins the process of stack unwinding, described 18613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffin Section 2.5. In special cases, such as an inability to find a 18713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffhandler, _Unwind_RaiseException may return. In that case, __cxa_throw 18813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffwill call terminate, assuming that there was no handler for the 18913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffexception. 19013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff*/ 19113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve NaroffLIBCXXABI_NORETURN void 19213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff__cxa_throw(void * thrown_exception, std::type_info * tinfo, void (*dest)(void *)) { 19313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff __cxa_eh_globals *globals = __cxa_get_globals(); 19413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff __cxa_exception *exception = exception_from_thrown_object(thrown_exception); 19513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 19613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff exception->unexpectedHandler = std::get_unexpected(); 19713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff exception->terminateHandler = std::get_terminate(); 19813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff exception->exceptionType = tinfo; 19913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff exception->exceptionDestructor = dest; 20013b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff setExceptionClass(&exception->unwindHeader); 20113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff exception->referenceCount = 1; // This is a newly allocated exception, no need for thread safety. 20213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local 20313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 20413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff exception->unwindHeader.exception_cleanup = exception_cleanup_func; 20513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff#if __arm__ 20613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff _Unwind_SjLj_RaiseException(&exception->unwindHeader); 20713b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff#else 20813b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff _Unwind_RaiseException(&exception->unwindHeader); 20913b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff#endif 2103ef5bc03d0bfc05fd76fc83beeb1b7ddbbb463daChris Lattner// If we get here, some kind of unwinding error has occurred. 21113b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff failed_throw(exception); 21213b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff} 21313b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 21413b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff 21513b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroff// 2.5.3 Exception Handlers 21613b7c5ff42d6077a8d59e2c9ec9e7fedd0150ae6Steve Naroffextern void * __cxa_get_exception_ptr(void * exceptionObject) throw() { 2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return exception_from_exception_object(exceptionObject); 2185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/* 2225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerThis routine: 2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* Increment's the exception's handler count. 2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* Places the exception on the stack of currently-caught exceptions if it is not 2255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer already there, linking the exception to the previous top of the stack. 2265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* Decrements the uncaught_exception count. 2275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* Returns the adjusted pointer to the exception object. 2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/ 2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid * __cxa_begin_catch(void * exceptionObject) throw() { 2305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_eh_globals *globals = __cxa_get_globals(); 2315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_exception *exception = exception_from_exception_object(exceptionObject); 2325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// TODO: Handle foreign exceptions? How? 2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Increment the handler count, removing the flag about being rethrown 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer exception->handlerCount = exception->handlerCount < 0 ? 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer -exception->handlerCount + 1 : exception->handlerCount + 1; 2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// place the exception on the top of the stack if it's not there. 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (exception != globals->caughtExceptions) { 2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer exception->nextException = globals->caughtExceptions; 2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer globals->caughtExceptions = exception; 2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer globals->uncaughtExceptions -= 1; // Not atomically, since globals are thread-local 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return thrown_object_from_exception(exception); 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/* 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerUpon exit for any reason, a handler must call: 2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer void __cxa_end_catch (); 2535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerThis routine: 25566b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson* Locates the most recently caught exception and decrements its handler count. 25666b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson* Removes the exception from the caught exception stack, if the handler count goes to zero. 25766b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson* If the handler count goes down to zero, and the exception was not re-thrown 258c5ae899b4bbf65488445316c63168079177db0edSteve Naroff by throw, it locates the primary exception (which may be the same as the one 259c5ae899b4bbf65488445316c63168079177db0edSteve Naroff it's handling) and decrements its reference count. If that reference count 26066b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson goes to zero, the function destroys the exception. In any case, if the current 26166b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlsson exception is a dependent exception, it destroys that. 262c5ae899b4bbf65488445316c63168079177db0edSteve Naroff*/ 26366b5a8a39088598c01a9fa6f032dc908612dc8ecAnders Carlssonvoid __cxa_end_catch() { 2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_eh_globals *globals = __cxa_get_globals_fast(); // __cxa_get_globals called in __cxa_begin_catch 2655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_exception *current_exception = globals->caughtExceptions; 2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NULL != current_exception) { 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // TODO: Handle foreign exceptions? How? 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (current_exception->handlerCount < 0) { 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // The exception has been rethrown 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (0 == incrementHandlerCount(current_exception)) { 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Remove from the chain of uncaught exceptions 2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer globals->caughtExceptions = current_exception->nextException; 2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // but don't destroy 2755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer else { // The exception has not been rethrown 2785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (0 == decrementHandlerCount(current_exception)) { 2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Remove from the chain of uncaught exceptions 2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer globals->caughtExceptions = current_exception->nextException; 2815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (isDependentException(¤t_exception->unwindHeader)) { 2825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Reset current_exception to primaryException and deallocate the dependent exception 2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_dependent_exception* deh = 2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1; 2855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1; 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_free_dependent_exception(deh); 2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Destroy the primary exception only if its referenceCount goes to 0 2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // (this decrement must be atomic) 2905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_decrement_exception_refcount(thrown_object_from_exception(current_exception)); 2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstd::type_info * __cxa_current_exception_type() { 2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// get the current exception 2995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_eh_globals *globals = __cxa_get_globals_fast(); 300e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner if (NULL == globals) 301e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner return NULL; // If there have never been any exceptions, there are none now. 302e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner __cxa_exception *current_exception = globals->caughtExceptions; 303e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner if (NULL == current_exception) 304e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner return NULL; // No current exception 305e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner if (isDependentException(¤t_exception->unwindHeader)) { 306e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner __cxa_dependent_exception* deh = 307e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1; 308e7716e6133e23e4a89248a65a388bc840d8c130cChris Lattner current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1; 309eb14fe839ec24c2ca14e5f094be147a34e3d3339Chris Lattner } 3101f683e9cf2e855b32d3fb4b142aa121cd3cf1088Chris Lattner return current_exception->exceptionType; 3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 312ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian 313ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian// 2.5.4 Rethrowing Exceptions 314ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian/* This routine 315ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian* marks the exception object on top of the caughtExceptions stack 316ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian (in an implementation-defined way) as being rethrown. 317ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian* If the caughtExceptions stack is empty, it calls terminate() 318ab38e4b50268633f037a10841fdfb612513f8d33Fariborz Jahanian (see [C++FDIS] [except.throw], 15.1.8). 3195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer* It then calls _Unwind_Resume_or_Rethrow which should not return 3205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (terminate if it does). 3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/ 3225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerextern LIBCXXABI_NORETURN void __cxa_rethrow() { 3235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_eh_globals *globals = __cxa_get_globals(); 3245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_exception *exception = globals->caughtExceptions; 3255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NULL == exception) // there's no current exception! 3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer std::terminate (); 3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 329a9c01021724b9b546d282b8609cbe559734812ecChris Lattner// TODO: Handle foreign exceptions? How? 330a9c01021724b9b546d282b8609cbe559734812ecChris Lattner 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch) 3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer exception->handlerCount = -exception->handlerCount; 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer globals->uncaughtExceptions += 1; 3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// __cxa_end_catch will remove this exception from the caughtExceptions stack if necessary 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#if __arm__ 3375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (void) _Unwind_SjLj_Resume_or_Rethrow(&exception->unwindHeader); 33804421087832a031c90bd58f128c7c0e741db8dd2Chris Lattner#else 3394be1f47de20525ad90f02ba8682a7e2cbd3205d1Eli Friedman (void) _Unwind_Resume_or_Rethrow (&exception->unwindHeader); 3404be1f47de20525ad90f02ba8682a7e2cbd3205d1Eli Friedman#endif 3414be1f47de20525ad90f02ba8682a7e2cbd3205d1Eli Friedman 3424be1f47de20525ad90f02ba8682a7e2cbd3205d1Eli Friedman// If we get here, some kind of unwinding error has occurred. 34304421087832a031c90bd58f128c7c0e741db8dd2Chris Lattner failed_throw(exception); 34404421087832a031c90bd58f128c7c0e741db8dd2Chris Lattner} 3455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/* 3475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer If p is not null, atomically increment the referenceCount field of the 3485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_exception header associated with the thrown object referred to by p. 3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/ 3505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid 3515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer__cxa_increment_exception_refcount(void* p) throw() 3525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 3535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (p != NULL ) 3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer { 3555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_exception* header = exception_from_thrown_object(p); 3565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __sync_add_and_fetch(&header->referenceCount, 1); 3577da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner } 35808ad47cbd1f81fcb31dbc731c13b885a07e12704Bill Wendling} 3595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 360ca51c97fbb10b9d48e1857e01c532493f87cd5f0Bill Wendling/* 3615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer If p is not null, atomically decrement the referenceCount field of the 362cb4f9a6d0be445d84af35ba81323be6127816f9eChris Lattner __cxa_exception header associated with the thrown object referred to by p. 3635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer If the referenceCount drops to zero, destroy and deallocate the exception. 3645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/ 365acb818a4f7d9b608826171094d6b5a555a8fe694Steve Naroffvoid 366f46699ce225811d8d9dbab9d00189a0e54469457Chris Lattner__cxa_decrement_exception_refcount(void* thrown_object) throw() 367acb818a4f7d9b608826171094d6b5a555a8fe694Steve Naroff{ 368acb818a4f7d9b608826171094d6b5a555a8fe694Steve Naroff if (thrown_object != NULL ) 369cb4f9a6d0be445d84af35ba81323be6127816f9eChris Lattner { 37008ad47cbd1f81fcb31dbc731c13b885a07e12704Bill Wendling __cxa_exception* header = exception_from_thrown_object(thrown_object); 37108ad47cbd1f81fcb31dbc731c13b885a07e12704Bill Wendling if (__sync_sub_and_fetch(&header->referenceCount, size_t(1)) == 0) 3725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer { 3735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NULL != header->exceptionDestructor) 3745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer header->exceptionDestructor(thrown_object); 3757323a6297edad643c202594dcf3d9a174de96ca6Anders Carlsson __cxa_free_exception(thrown_object); 3765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/* 3815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Returns a pointer to the thrown object (if any) at the top of the 3825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer caughtExceptions stack. Atommically increment the exception's referenceCount. 3835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer If there is no such thrown object, returns null. 3845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/ 385fdd75663fffeb2058a7847975e50837e61200593Anton Korobeynikovvoid* 3865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer__cxa_current_primary_exception() throw() 3875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 388fdd75663fffeb2058a7847975e50837e61200593Anton Korobeynikov// get the current exception 3897da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner __cxa_eh_globals* globals = __cxa_get_globals(); 3905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_exception* current_exception = globals->caughtExceptions; 3917da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner if (NULL == current_exception) 3927da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner return NULL; // No current exception 3937da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner if (isDependentException(¤t_exception->unwindHeader)) { 3947da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner __cxa_dependent_exception* deh = 3957da36f642e907ff5a5ba4b18b5bfebfabf36ecc7Chris Lattner reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1; 3965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1; 3975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer void* thrown_object = thrown_object_from_exception(current_exception); 399e6386394677ed4f77b20e2e3d5446a3a2f628e53Steve Naroff __cxa_increment_exception_refcount(thrown_object); 400e6386394677ed4f77b20e2e3d5446a3a2f628e53Steve Naroff return thrown_object; 401213541a68a3e137d11d2cefb612c6cdb410d7e8eNate Begeman} 402213541a68a3e137d11d2cefb612c6cdb410d7e8eNate Begeman 403fec0b49c3fa621fbf63e420f3d54a5bb3a0265d2Steve Naroff/* 404fec0b49c3fa621fbf63e420f3d54a5bb3a0265d2Steve Naroff If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler 405027282d1c1ac151aa7b1b3b45babc918b8ad456aSteve Naroff stored in exc is called. Otherwise the referenceCount stored in the 406027282d1c1ac151aa7b1b3b45babc918b8ad456aSteve Naroff primary exception is decremented, destroying the primary if necessary. 407fa28b30d5a1e93e5263be33e343532b900d2c643Chris Lattner Finally the dependent exception is destroyed. 408fa28b30d5a1e93e5263be33e343532b900d2c643Chris Lattner*/ 40904421087832a031c90bd58f128c7c0e741db8dd2Chris Lattnerstatic 41004421087832a031c90bd58f128c7c0e741db8dd2Chris Lattnervoid 4115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdependent_exception_cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc) 4125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 4135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_dependent_exception* deh = 4145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer reinterpret_cast<__cxa_dependent_exception*>(exc + 1) - 1; 4155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason) 4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer std::__terminate(deh->terminateHandler); 4175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_decrement_exception_refcount(deh->primaryException); 4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_free_dependent_exception(deh); 4195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/* 422ca51c97fbb10b9d48e1857e01c532493f87cd5f0Bill Wendling If thrown_object is not null, allocate, initialize and thow a dependent 4235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer exception. 4245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer*/ 4255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid 4265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer__cxa_rethrow_primary_exception(void* thrown_object) 4275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 4285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if ( thrown_object != NULL ) 429fec0b49c3fa621fbf63e420f3d54a5bb3a0265d2Steve Naroff { 4305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_exception* header = exception_from_thrown_object(thrown_object); 4315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_dependent_exception* deh = 4325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (__cxa_dependent_exception*)__cxa_allocate_dependent_exception(); 4335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer deh->primaryException = thrown_object; 4345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_increment_exception_refcount(thrown_object); 4355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer deh->exceptionType = header->exceptionType; 4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer deh->unexpectedHandler = std::get_unexpected(); 4375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer deh->terminateHandler = std::get_terminate(); 4385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer setDependentExceptionClass(&deh->unwindHeader); 4395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __cxa_get_globals()->uncaughtExceptions += 1; 4405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer deh->unwindHeader.exception_cleanup = dependent_exception_cleanup; 4415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#if __arm__ 4425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer _Unwind_SjLj_RaiseException(&deh->unwindHeader); 4435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#else 4445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer _Unwind_RaiseException(&deh->unwindHeader); 4455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif 4462e5f54aa1dd15a62c34a9d1d24a5a0692f43934aTed Kremenek // Some sort of unwinding error. Note that terminate is a handler. 4474cc627111453b75519d5130b57e06256da7b00e8Chris Lattner __cxa_begin_catch(&deh->unwindHeader); 4484cc627111453b75519d5130b57e06256da7b00e8Chris Lattner } 4492e5f54aa1dd15a62c34a9d1d24a5a0692f43934aTed Kremenek // If we return client will call terminate() 4501d09ecca892185ba067e47ba879f424de59950efChris Lattner} 4511d09ecca892185ba067e47ba879f424de59950efChris Lattner 4521d09ecca892185ba067e47ba879f424de59950efChris Lattner_Unwind_Reason_Code 4534cc627111453b75519d5130b57e06256da7b00e8Chris Lattner__gxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass, 4542e5f54aa1dd15a62c34a9d1d24a5a0692f43934aTed Kremenek _Unwind_Exception* exceptionObject, _Unwind_Context* context) 4554cc627111453b75519d5130b57e06256da7b00e8Chris Lattner{ 4562e5f54aa1dd15a62c34a9d1d24a5a0692f43934aTed Kremenek} 457e9b12198c4cc7f5687960100351b4af006c14469Steve Naroff 458e9b12198c4cc7f5687960100351b4af006c14469Steve Naroff} // extern "C" 4591d09ecca892185ba067e47ba879f424de59950efChris Lattner 4601d09ecca892185ba067e47ba879f424de59950efChris Lattner} // abi 4611d09ecca892185ba067e47ba879f424de59950efChris Lattner