1*c05d8e5dSAndroid Build Coastguard Worker //===------------------------- cxa_exception.cpp --------------------------===//
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*c05d8e5dSAndroid Build Coastguard Worker //
5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*c05d8e5dSAndroid Build Coastguard Worker //
8*c05d8e5dSAndroid Build Coastguard Worker //
9*c05d8e5dSAndroid Build Coastguard Worker // This file implements the "Exception Handling APIs"
10*c05d8e5dSAndroid Build Coastguard Worker // http://mentorembedded.github.io/cxx-abi/abi-eh.html
11*c05d8e5dSAndroid Build Coastguard Worker //
12*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*c05d8e5dSAndroid Build Coastguard Worker
14*c05d8e5dSAndroid Build Coastguard Worker #include "cxxabi.h"
15*c05d8e5dSAndroid Build Coastguard Worker
16*c05d8e5dSAndroid Build Coastguard Worker #include <exception> // for std::terminate
17*c05d8e5dSAndroid Build Coastguard Worker #include <cstring> // for memset
18*c05d8e5dSAndroid Build Coastguard Worker #include "cxa_exception.hpp"
19*c05d8e5dSAndroid Build Coastguard Worker #include "cxa_handlers.hpp"
20*c05d8e5dSAndroid Build Coastguard Worker #include "fallback_malloc.h"
21*c05d8e5dSAndroid Build Coastguard Worker #include "include/atomic_support.h"
22*c05d8e5dSAndroid Build Coastguard Worker
23*c05d8e5dSAndroid Build Coastguard Worker #if __has_feature(address_sanitizer)
24*c05d8e5dSAndroid Build Coastguard Worker extern "C" void __asan_handle_no_return(void);
25*c05d8e5dSAndroid Build Coastguard Worker #endif
26*c05d8e5dSAndroid Build Coastguard Worker
27*c05d8e5dSAndroid Build Coastguard Worker // +---------------------------+-----------------------------+---------------+
28*c05d8e5dSAndroid Build Coastguard Worker // | __cxa_exception | _Unwind_Exception CLNGC++\0 | thrown object |
29*c05d8e5dSAndroid Build Coastguard Worker // +---------------------------+-----------------------------+---------------+
30*c05d8e5dSAndroid Build Coastguard Worker // ^
31*c05d8e5dSAndroid Build Coastguard Worker // |
32*c05d8e5dSAndroid Build Coastguard Worker // +-------------------------------------------------------+
33*c05d8e5dSAndroid Build Coastguard Worker // |
34*c05d8e5dSAndroid Build Coastguard Worker // +---------------------------+-----------------------------+
35*c05d8e5dSAndroid Build Coastguard Worker // | __cxa_dependent_exception | _Unwind_Exception CLNGC++\1 |
36*c05d8e5dSAndroid Build Coastguard Worker // +---------------------------+-----------------------------+
37*c05d8e5dSAndroid Build Coastguard Worker
38*c05d8e5dSAndroid Build Coastguard Worker namespace __cxxabiv1 {
39*c05d8e5dSAndroid Build Coastguard Worker
40*c05d8e5dSAndroid Build Coastguard Worker // Utility routines
41*c05d8e5dSAndroid Build Coastguard Worker static
42*c05d8e5dSAndroid Build Coastguard Worker inline
43*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception*
cxa_exception_from_thrown_object(void * thrown_object)44*c05d8e5dSAndroid Build Coastguard Worker cxa_exception_from_thrown_object(void* thrown_object)
45*c05d8e5dSAndroid Build Coastguard Worker {
46*c05d8e5dSAndroid Build Coastguard Worker return static_cast<__cxa_exception*>(thrown_object) - 1;
47*c05d8e5dSAndroid Build Coastguard Worker }
48*c05d8e5dSAndroid Build Coastguard Worker
49*c05d8e5dSAndroid Build Coastguard Worker // Note: This is never called when exception_header is masquerading as a
50*c05d8e5dSAndroid Build Coastguard Worker // __cxa_dependent_exception.
51*c05d8e5dSAndroid Build Coastguard Worker static
52*c05d8e5dSAndroid Build Coastguard Worker inline
53*c05d8e5dSAndroid Build Coastguard Worker void*
thrown_object_from_cxa_exception(__cxa_exception * exception_header)54*c05d8e5dSAndroid Build Coastguard Worker thrown_object_from_cxa_exception(__cxa_exception* exception_header)
55*c05d8e5dSAndroid Build Coastguard Worker {
56*c05d8e5dSAndroid Build Coastguard Worker return static_cast<void*>(exception_header + 1);
57*c05d8e5dSAndroid Build Coastguard Worker }
58*c05d8e5dSAndroid Build Coastguard Worker
59*c05d8e5dSAndroid Build Coastguard Worker // Get the exception object from the unwind pointer.
60*c05d8e5dSAndroid Build Coastguard Worker // Relies on the structure layout, where the unwind pointer is right in
61*c05d8e5dSAndroid Build Coastguard Worker // front of the user's exception object
62*c05d8e5dSAndroid Build Coastguard Worker static
63*c05d8e5dSAndroid Build Coastguard Worker inline
64*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception*
cxa_exception_from_exception_unwind_exception(_Unwind_Exception * unwind_exception)65*c05d8e5dSAndroid Build Coastguard Worker cxa_exception_from_exception_unwind_exception(_Unwind_Exception* unwind_exception)
66*c05d8e5dSAndroid Build Coastguard Worker {
67*c05d8e5dSAndroid Build Coastguard Worker return cxa_exception_from_thrown_object(unwind_exception + 1 );
68*c05d8e5dSAndroid Build Coastguard Worker }
69*c05d8e5dSAndroid Build Coastguard Worker
70*c05d8e5dSAndroid Build Coastguard Worker // Round s up to next multiple of a.
71*c05d8e5dSAndroid Build Coastguard Worker static inline
aligned_allocation_size(size_t s,size_t a)72*c05d8e5dSAndroid Build Coastguard Worker size_t aligned_allocation_size(size_t s, size_t a) {
73*c05d8e5dSAndroid Build Coastguard Worker return (s + a - 1) & ~(a - 1);
74*c05d8e5dSAndroid Build Coastguard Worker }
75*c05d8e5dSAndroid Build Coastguard Worker
76*c05d8e5dSAndroid Build Coastguard Worker static inline
cxa_exception_size_from_exception_thrown_size(size_t size)77*c05d8e5dSAndroid Build Coastguard Worker size_t cxa_exception_size_from_exception_thrown_size(size_t size) {
78*c05d8e5dSAndroid Build Coastguard Worker return aligned_allocation_size(size + sizeof (__cxa_exception),
79*c05d8e5dSAndroid Build Coastguard Worker alignof(__cxa_exception));
80*c05d8e5dSAndroid Build Coastguard Worker }
81*c05d8e5dSAndroid Build Coastguard Worker
__setExceptionClass(_Unwind_Exception * unwind_exception,uint64_t newValue)82*c05d8e5dSAndroid Build Coastguard Worker void __setExceptionClass(_Unwind_Exception* unwind_exception, uint64_t newValue) {
83*c05d8e5dSAndroid Build Coastguard Worker ::memcpy(&unwind_exception->exception_class, &newValue, sizeof(newValue));
84*c05d8e5dSAndroid Build Coastguard Worker }
85*c05d8e5dSAndroid Build Coastguard Worker
86*c05d8e5dSAndroid Build Coastguard Worker
setOurExceptionClass(_Unwind_Exception * unwind_exception)87*c05d8e5dSAndroid Build Coastguard Worker static void setOurExceptionClass(_Unwind_Exception* unwind_exception) {
88*c05d8e5dSAndroid Build Coastguard Worker __setExceptionClass(unwind_exception, kOurExceptionClass);
89*c05d8e5dSAndroid Build Coastguard Worker }
90*c05d8e5dSAndroid Build Coastguard Worker
setDependentExceptionClass(_Unwind_Exception * unwind_exception)91*c05d8e5dSAndroid Build Coastguard Worker static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) {
92*c05d8e5dSAndroid Build Coastguard Worker __setExceptionClass(unwind_exception, kOurDependentExceptionClass);
93*c05d8e5dSAndroid Build Coastguard Worker }
94*c05d8e5dSAndroid Build Coastguard Worker
95*c05d8e5dSAndroid Build Coastguard Worker // Is it one of ours?
__getExceptionClass(const _Unwind_Exception * unwind_exception)96*c05d8e5dSAndroid Build Coastguard Worker uint64_t __getExceptionClass(const _Unwind_Exception* unwind_exception) {
97*c05d8e5dSAndroid Build Coastguard Worker // On x86 and some ARM unwinders, unwind_exception->exception_class is
98*c05d8e5dSAndroid Build Coastguard Worker // a uint64_t. On other ARM unwinders, it is a char[8]
99*c05d8e5dSAndroid Build Coastguard Worker // See: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
100*c05d8e5dSAndroid Build Coastguard Worker // So we just copy it into a uint64_t to be sure.
101*c05d8e5dSAndroid Build Coastguard Worker uint64_t exClass;
102*c05d8e5dSAndroid Build Coastguard Worker ::memcpy(&exClass, &unwind_exception->exception_class, sizeof(exClass));
103*c05d8e5dSAndroid Build Coastguard Worker return exClass;
104*c05d8e5dSAndroid Build Coastguard Worker }
105*c05d8e5dSAndroid Build Coastguard Worker
__isOurExceptionClass(const _Unwind_Exception * unwind_exception)106*c05d8e5dSAndroid Build Coastguard Worker bool __isOurExceptionClass(const _Unwind_Exception* unwind_exception) {
107*c05d8e5dSAndroid Build Coastguard Worker return (__getExceptionClass(unwind_exception) & get_vendor_and_language) ==
108*c05d8e5dSAndroid Build Coastguard Worker (kOurExceptionClass & get_vendor_and_language);
109*c05d8e5dSAndroid Build Coastguard Worker }
110*c05d8e5dSAndroid Build Coastguard Worker
isDependentException(_Unwind_Exception * unwind_exception)111*c05d8e5dSAndroid Build Coastguard Worker static bool isDependentException(_Unwind_Exception* unwind_exception) {
112*c05d8e5dSAndroid Build Coastguard Worker return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01;
113*c05d8e5dSAndroid Build Coastguard Worker }
114*c05d8e5dSAndroid Build Coastguard Worker
115*c05d8e5dSAndroid Build Coastguard Worker // This does not need to be atomic
incrementHandlerCount(__cxa_exception * exception)116*c05d8e5dSAndroid Build Coastguard Worker static inline int incrementHandlerCount(__cxa_exception *exception) {
117*c05d8e5dSAndroid Build Coastguard Worker return ++exception->handlerCount;
118*c05d8e5dSAndroid Build Coastguard Worker }
119*c05d8e5dSAndroid Build Coastguard Worker
120*c05d8e5dSAndroid Build Coastguard Worker // This does not need to be atomic
decrementHandlerCount(__cxa_exception * exception)121*c05d8e5dSAndroid Build Coastguard Worker static inline int decrementHandlerCount(__cxa_exception *exception) {
122*c05d8e5dSAndroid Build Coastguard Worker return --exception->handlerCount;
123*c05d8e5dSAndroid Build Coastguard Worker }
124*c05d8e5dSAndroid Build Coastguard Worker
125*c05d8e5dSAndroid Build Coastguard Worker /*
126*c05d8e5dSAndroid Build Coastguard Worker If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
127*c05d8e5dSAndroid Build Coastguard Worker stored in exc is called. Otherwise the exceptionDestructor stored in
128*c05d8e5dSAndroid Build Coastguard Worker exc is called, and then the memory for the exception is deallocated.
129*c05d8e5dSAndroid Build Coastguard Worker
130*c05d8e5dSAndroid Build Coastguard Worker This is never called for a __cxa_dependent_exception.
131*c05d8e5dSAndroid Build Coastguard Worker */
132*c05d8e5dSAndroid Build Coastguard Worker static
133*c05d8e5dSAndroid Build Coastguard Worker void
exception_cleanup_func(_Unwind_Reason_Code reason,_Unwind_Exception * unwind_exception)134*c05d8e5dSAndroid Build Coastguard Worker exception_cleanup_func(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception)
135*c05d8e5dSAndroid Build Coastguard Worker {
136*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = cxa_exception_from_exception_unwind_exception(unwind_exception);
137*c05d8e5dSAndroid Build Coastguard Worker if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
138*c05d8e5dSAndroid Build Coastguard Worker std::__terminate(exception_header->terminateHandler);
139*c05d8e5dSAndroid Build Coastguard Worker // Just in case there exists a dependent exception that is pointing to this,
140*c05d8e5dSAndroid Build Coastguard Worker // check the reference count and only destroy this if that count goes to zero.
141*c05d8e5dSAndroid Build Coastguard Worker __cxa_decrement_exception_refcount(unwind_exception + 1);
142*c05d8e5dSAndroid Build Coastguard Worker }
143*c05d8e5dSAndroid Build Coastguard Worker
failed_throw(__cxa_exception * exception_header)144*c05d8e5dSAndroid Build Coastguard Worker static _LIBCXXABI_NORETURN void failed_throw(__cxa_exception* exception_header) {
145*c05d8e5dSAndroid Build Coastguard Worker // Section 2.5.3 says:
146*c05d8e5dSAndroid Build Coastguard Worker // * For purposes of this ABI, several things are considered exception handlers:
147*c05d8e5dSAndroid Build Coastguard Worker // ** A terminate() call due to a throw.
148*c05d8e5dSAndroid Build Coastguard Worker // and
149*c05d8e5dSAndroid Build Coastguard Worker // * Upon entry, Following initialization of the catch parameter,
150*c05d8e5dSAndroid Build Coastguard Worker // a handler must call:
151*c05d8e5dSAndroid Build Coastguard Worker // * void *__cxa_begin_catch(void *exceptionObject );
152*c05d8e5dSAndroid Build Coastguard Worker (void) __cxa_begin_catch(&exception_header->unwindHeader);
153*c05d8e5dSAndroid Build Coastguard Worker std::__terminate(exception_header->terminateHandler);
154*c05d8e5dSAndroid Build Coastguard Worker }
155*c05d8e5dSAndroid Build Coastguard Worker
156*c05d8e5dSAndroid Build Coastguard Worker // Return the offset of the __cxa_exception header from the start of the
157*c05d8e5dSAndroid Build Coastguard Worker // allocated buffer. If __cxa_exception's alignment is smaller than the maximum
158*c05d8e5dSAndroid Build Coastguard Worker // useful alignment for the target machine, padding has to be inserted before
159*c05d8e5dSAndroid Build Coastguard Worker // the header to ensure the thrown object that follows the header is
160*c05d8e5dSAndroid Build Coastguard Worker // sufficiently aligned. This happens if _Unwind_exception isn't double-word
161*c05d8e5dSAndroid Build Coastguard Worker // aligned (on Darwin, for example).
get_cxa_exception_offset()162*c05d8e5dSAndroid Build Coastguard Worker static size_t get_cxa_exception_offset() {
163*c05d8e5dSAndroid Build Coastguard Worker struct S {
164*c05d8e5dSAndroid Build Coastguard Worker } __attribute__((aligned));
165*c05d8e5dSAndroid Build Coastguard Worker
166*c05d8e5dSAndroid Build Coastguard Worker // Compute the maximum alignment for the target machine.
167*c05d8e5dSAndroid Build Coastguard Worker constexpr size_t alignment = std::alignment_of<S>::value;
168*c05d8e5dSAndroid Build Coastguard Worker constexpr size_t excp_size = sizeof(__cxa_exception);
169*c05d8e5dSAndroid Build Coastguard Worker constexpr size_t aligned_size =
170*c05d8e5dSAndroid Build Coastguard Worker (excp_size + alignment - 1) / alignment * alignment;
171*c05d8e5dSAndroid Build Coastguard Worker constexpr size_t offset = aligned_size - excp_size;
172*c05d8e5dSAndroid Build Coastguard Worker static_assert((offset == 0 ||
173*c05d8e5dSAndroid Build Coastguard Worker std::alignment_of<_Unwind_Exception>::value < alignment),
174*c05d8e5dSAndroid Build Coastguard Worker "offset is non-zero only if _Unwind_Exception isn't aligned");
175*c05d8e5dSAndroid Build Coastguard Worker return offset;
176*c05d8e5dSAndroid Build Coastguard Worker }
177*c05d8e5dSAndroid Build Coastguard Worker
178*c05d8e5dSAndroid Build Coastguard Worker extern "C" {
179*c05d8e5dSAndroid Build Coastguard Worker
180*c05d8e5dSAndroid Build Coastguard Worker // Allocate a __cxa_exception object, and zero-fill it.
181*c05d8e5dSAndroid Build Coastguard Worker // Reserve "thrown_size" bytes on the end for the user's exception
182*c05d8e5dSAndroid Build Coastguard Worker // object. Zero-fill the object. If memory can't be allocated, call
183*c05d8e5dSAndroid Build Coastguard Worker // std::terminate. Return a pointer to the memory to be used for the
184*c05d8e5dSAndroid Build Coastguard Worker // user's exception object.
__cxa_allocate_exception(size_t thrown_size)185*c05d8e5dSAndroid Build Coastguard Worker void *__cxa_allocate_exception(size_t thrown_size) throw() {
186*c05d8e5dSAndroid Build Coastguard Worker size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size);
187*c05d8e5dSAndroid Build Coastguard Worker
188*c05d8e5dSAndroid Build Coastguard Worker // Allocate extra space before the __cxa_exception header to ensure the
189*c05d8e5dSAndroid Build Coastguard Worker // start of the thrown object is sufficiently aligned.
190*c05d8e5dSAndroid Build Coastguard Worker size_t header_offset = get_cxa_exception_offset();
191*c05d8e5dSAndroid Build Coastguard Worker char *raw_buffer =
192*c05d8e5dSAndroid Build Coastguard Worker (char *)__aligned_malloc_with_fallback(header_offset + actual_size);
193*c05d8e5dSAndroid Build Coastguard Worker if (NULL == raw_buffer)
194*c05d8e5dSAndroid Build Coastguard Worker std::terminate();
195*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception *exception_header =
196*c05d8e5dSAndroid Build Coastguard Worker static_cast<__cxa_exception *>((void *)(raw_buffer + header_offset));
197*c05d8e5dSAndroid Build Coastguard Worker std::memset(exception_header, 0, actual_size);
198*c05d8e5dSAndroid Build Coastguard Worker return thrown_object_from_cxa_exception(exception_header);
199*c05d8e5dSAndroid Build Coastguard Worker }
200*c05d8e5dSAndroid Build Coastguard Worker
201*c05d8e5dSAndroid Build Coastguard Worker
202*c05d8e5dSAndroid Build Coastguard Worker // Free a __cxa_exception object allocated with __cxa_allocate_exception.
__cxa_free_exception(void * thrown_object)203*c05d8e5dSAndroid Build Coastguard Worker void __cxa_free_exception(void *thrown_object) throw() {
204*c05d8e5dSAndroid Build Coastguard Worker // Compute the size of the padding before the header.
205*c05d8e5dSAndroid Build Coastguard Worker size_t header_offset = get_cxa_exception_offset();
206*c05d8e5dSAndroid Build Coastguard Worker char *raw_buffer =
207*c05d8e5dSAndroid Build Coastguard Worker ((char *)cxa_exception_from_thrown_object(thrown_object)) - header_offset;
208*c05d8e5dSAndroid Build Coastguard Worker __aligned_free_with_fallback((void *)raw_buffer);
209*c05d8e5dSAndroid Build Coastguard Worker }
210*c05d8e5dSAndroid Build Coastguard Worker
211*c05d8e5dSAndroid Build Coastguard Worker
212*c05d8e5dSAndroid Build Coastguard Worker // This function shall allocate a __cxa_dependent_exception and
213*c05d8e5dSAndroid Build Coastguard Worker // return a pointer to it. (Really to the object, not past its' end).
214*c05d8e5dSAndroid Build Coastguard Worker // Otherwise, it will work like __cxa_allocate_exception.
__cxa_allocate_dependent_exception()215*c05d8e5dSAndroid Build Coastguard Worker void * __cxa_allocate_dependent_exception () {
216*c05d8e5dSAndroid Build Coastguard Worker size_t actual_size = sizeof(__cxa_dependent_exception);
217*c05d8e5dSAndroid Build Coastguard Worker void *ptr = __aligned_malloc_with_fallback(actual_size);
218*c05d8e5dSAndroid Build Coastguard Worker if (NULL == ptr)
219*c05d8e5dSAndroid Build Coastguard Worker std::terminate();
220*c05d8e5dSAndroid Build Coastguard Worker std::memset(ptr, 0, actual_size);
221*c05d8e5dSAndroid Build Coastguard Worker return ptr;
222*c05d8e5dSAndroid Build Coastguard Worker }
223*c05d8e5dSAndroid Build Coastguard Worker
224*c05d8e5dSAndroid Build Coastguard Worker
225*c05d8e5dSAndroid Build Coastguard Worker // This function shall free a dependent_exception.
226*c05d8e5dSAndroid Build Coastguard Worker // It does not affect the reference count of the primary exception.
__cxa_free_dependent_exception(void * dependent_exception)227*c05d8e5dSAndroid Build Coastguard Worker void __cxa_free_dependent_exception (void * dependent_exception) {
228*c05d8e5dSAndroid Build Coastguard Worker __aligned_free_with_fallback(dependent_exception);
229*c05d8e5dSAndroid Build Coastguard Worker }
230*c05d8e5dSAndroid Build Coastguard Worker
231*c05d8e5dSAndroid Build Coastguard Worker
232*c05d8e5dSAndroid Build Coastguard Worker // 2.4.3 Throwing the Exception Object
233*c05d8e5dSAndroid Build Coastguard Worker /*
234*c05d8e5dSAndroid Build Coastguard Worker After constructing the exception object with the throw argument value,
235*c05d8e5dSAndroid Build Coastguard Worker the generated code calls the __cxa_throw runtime library routine. This
236*c05d8e5dSAndroid Build Coastguard Worker routine never returns.
237*c05d8e5dSAndroid Build Coastguard Worker
238*c05d8e5dSAndroid Build Coastguard Worker The __cxa_throw routine will do the following:
239*c05d8e5dSAndroid Build Coastguard Worker
240*c05d8e5dSAndroid Build Coastguard Worker * Obtain the __cxa_exception header from the thrown exception object address,
241*c05d8e5dSAndroid Build Coastguard Worker which can be computed as follows:
242*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1);
243*c05d8e5dSAndroid Build Coastguard Worker * Save the current unexpected_handler and terminate_handler in the __cxa_exception header.
244*c05d8e5dSAndroid Build Coastguard Worker * Save the tinfo and dest arguments in the __cxa_exception header.
245*c05d8e5dSAndroid Build Coastguard Worker * Set the exception_class field in the unwind header. This is a 64-bit value
246*c05d8e5dSAndroid Build Coastguard Worker representing the ASCII string "XXXXC++\0", where "XXXX" is a
247*c05d8e5dSAndroid Build Coastguard Worker vendor-dependent string. That is, for implementations conforming to this
248*c05d8e5dSAndroid Build Coastguard Worker ABI, the low-order 4 bytes of this 64-bit value will be "C++\0".
249*c05d8e5dSAndroid Build Coastguard Worker * Increment the uncaught_exception flag.
250*c05d8e5dSAndroid Build Coastguard Worker * Call _Unwind_RaiseException in the system unwind library, Its argument is the
251*c05d8e5dSAndroid Build Coastguard Worker pointer to the thrown exception, which __cxa_throw itself received as an argument.
252*c05d8e5dSAndroid Build Coastguard Worker __Unwind_RaiseException begins the process of stack unwinding, described
253*c05d8e5dSAndroid Build Coastguard Worker in Section 2.5. In special cases, such as an inability to find a
254*c05d8e5dSAndroid Build Coastguard Worker handler, _Unwind_RaiseException may return. In that case, __cxa_throw
255*c05d8e5dSAndroid Build Coastguard Worker will call terminate, assuming that there was no handler for the
256*c05d8e5dSAndroid Build Coastguard Worker exception.
257*c05d8e5dSAndroid Build Coastguard Worker */
258*c05d8e5dSAndroid Build Coastguard Worker void
__cxa_throw(void * thrown_object,std::type_info * tinfo,void (* dest)(void *))259*c05d8e5dSAndroid Build Coastguard Worker __cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {
260*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals *globals = __cxa_get_globals();
261*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
262*c05d8e5dSAndroid Build Coastguard Worker
263*c05d8e5dSAndroid Build Coastguard Worker exception_header->unexpectedHandler = std::get_unexpected();
264*c05d8e5dSAndroid Build Coastguard Worker exception_header->terminateHandler = std::get_terminate();
265*c05d8e5dSAndroid Build Coastguard Worker exception_header->exceptionType = tinfo;
266*c05d8e5dSAndroid Build Coastguard Worker exception_header->exceptionDestructor = dest;
267*c05d8e5dSAndroid Build Coastguard Worker setOurExceptionClass(&exception_header->unwindHeader);
268*c05d8e5dSAndroid Build Coastguard Worker exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
269*c05d8e5dSAndroid Build Coastguard Worker globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
270*c05d8e5dSAndroid Build Coastguard Worker
271*c05d8e5dSAndroid Build Coastguard Worker exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;
272*c05d8e5dSAndroid Build Coastguard Worker
273*c05d8e5dSAndroid Build Coastguard Worker #if __has_feature(address_sanitizer)
274*c05d8e5dSAndroid Build Coastguard Worker // Inform the ASan runtime that now might be a good time to clean stuff up.
275*c05d8e5dSAndroid Build Coastguard Worker __asan_handle_no_return();
276*c05d8e5dSAndroid Build Coastguard Worker #endif
277*c05d8e5dSAndroid Build Coastguard Worker
278*c05d8e5dSAndroid Build Coastguard Worker #ifdef __USING_SJLJ_EXCEPTIONS__
279*c05d8e5dSAndroid Build Coastguard Worker _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
280*c05d8e5dSAndroid Build Coastguard Worker #else
281*c05d8e5dSAndroid Build Coastguard Worker _Unwind_RaiseException(&exception_header->unwindHeader);
282*c05d8e5dSAndroid Build Coastguard Worker #endif
283*c05d8e5dSAndroid Build Coastguard Worker // This only happens when there is no handler, or some unexpected unwinding
284*c05d8e5dSAndroid Build Coastguard Worker // error happens.
285*c05d8e5dSAndroid Build Coastguard Worker failed_throw(exception_header);
286*c05d8e5dSAndroid Build Coastguard Worker }
287*c05d8e5dSAndroid Build Coastguard Worker
288*c05d8e5dSAndroid Build Coastguard Worker
289*c05d8e5dSAndroid Build Coastguard Worker // 2.5.3 Exception Handlers
290*c05d8e5dSAndroid Build Coastguard Worker /*
291*c05d8e5dSAndroid Build Coastguard Worker The adjusted pointer is computed by the personality routine during phase 1
292*c05d8e5dSAndroid Build Coastguard Worker and saved in the exception header (either __cxa_exception or
293*c05d8e5dSAndroid Build Coastguard Worker __cxa_dependent_exception).
294*c05d8e5dSAndroid Build Coastguard Worker
295*c05d8e5dSAndroid Build Coastguard Worker Requires: exception is native
296*c05d8e5dSAndroid Build Coastguard Worker */
__cxa_get_exception_ptr(void * unwind_exception)297*c05d8e5dSAndroid Build Coastguard Worker void *__cxa_get_exception_ptr(void *unwind_exception) throw() {
298*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_ARM_EHABI)
299*c05d8e5dSAndroid Build Coastguard Worker return reinterpret_cast<void*>(
300*c05d8e5dSAndroid Build Coastguard Worker static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]);
301*c05d8e5dSAndroid Build Coastguard Worker #else
302*c05d8e5dSAndroid Build Coastguard Worker return cxa_exception_from_exception_unwind_exception(
303*c05d8e5dSAndroid Build Coastguard Worker static_cast<_Unwind_Exception*>(unwind_exception))->adjustedPtr;
304*c05d8e5dSAndroid Build Coastguard Worker #endif
305*c05d8e5dSAndroid Build Coastguard Worker }
306*c05d8e5dSAndroid Build Coastguard Worker
307*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_ARM_EHABI)
308*c05d8e5dSAndroid Build Coastguard Worker /*
309*c05d8e5dSAndroid Build Coastguard Worker The routine to be called before the cleanup. This will save __cxa_exception in
310*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals, so that __cxa_end_cleanup() can recover later.
311*c05d8e5dSAndroid Build Coastguard Worker */
__cxa_begin_cleanup(void * unwind_arg)312*c05d8e5dSAndroid Build Coastguard Worker bool __cxa_begin_cleanup(void *unwind_arg) throw() {
313*c05d8e5dSAndroid Build Coastguard Worker _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
314*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals* globals = __cxa_get_globals();
315*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header =
316*c05d8e5dSAndroid Build Coastguard Worker cxa_exception_from_exception_unwind_exception(unwind_exception);
317*c05d8e5dSAndroid Build Coastguard Worker
318*c05d8e5dSAndroid Build Coastguard Worker if (__isOurExceptionClass(unwind_exception))
319*c05d8e5dSAndroid Build Coastguard Worker {
320*c05d8e5dSAndroid Build Coastguard Worker if (0 == exception_header->propagationCount)
321*c05d8e5dSAndroid Build Coastguard Worker {
322*c05d8e5dSAndroid Build Coastguard Worker exception_header->nextPropagatingException = globals->propagatingExceptions;
323*c05d8e5dSAndroid Build Coastguard Worker globals->propagatingExceptions = exception_header;
324*c05d8e5dSAndroid Build Coastguard Worker }
325*c05d8e5dSAndroid Build Coastguard Worker ++exception_header->propagationCount;
326*c05d8e5dSAndroid Build Coastguard Worker }
327*c05d8e5dSAndroid Build Coastguard Worker else
328*c05d8e5dSAndroid Build Coastguard Worker {
329*c05d8e5dSAndroid Build Coastguard Worker // If the propagatingExceptions stack is not empty, since we can't
330*c05d8e5dSAndroid Build Coastguard Worker // chain the foreign exception, terminate it.
331*c05d8e5dSAndroid Build Coastguard Worker if (NULL != globals->propagatingExceptions)
332*c05d8e5dSAndroid Build Coastguard Worker std::terminate();
333*c05d8e5dSAndroid Build Coastguard Worker globals->propagatingExceptions = exception_header;
334*c05d8e5dSAndroid Build Coastguard Worker }
335*c05d8e5dSAndroid Build Coastguard Worker return true;
336*c05d8e5dSAndroid Build Coastguard Worker }
337*c05d8e5dSAndroid Build Coastguard Worker
338*c05d8e5dSAndroid Build Coastguard Worker /*
339*c05d8e5dSAndroid Build Coastguard Worker The routine to be called after the cleanup has been performed. It will get the
340*c05d8e5dSAndroid Build Coastguard Worker propagating __cxa_exception from __cxa_eh_globals, and continue the stack
341*c05d8e5dSAndroid Build Coastguard Worker unwinding with _Unwind_Resume.
342*c05d8e5dSAndroid Build Coastguard Worker
343*c05d8e5dSAndroid Build Coastguard Worker According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any
344*c05d8e5dSAndroid Build Coastguard Worker register, thus we have to write this function in assembly so that we can save
345*c05d8e5dSAndroid Build Coastguard Worker {r1, r2, r3}. We don't have to save r0 because it is the return value and the
346*c05d8e5dSAndroid Build Coastguard Worker first argument to _Unwind_Resume(). The function also saves/restores r4 to
347*c05d8e5dSAndroid Build Coastguard Worker keep the stack aligned and to provide a temp register. _Unwind_Resume never
348*c05d8e5dSAndroid Build Coastguard Worker returns and we need to keep the original lr so just branch to it. When
349*c05d8e5dSAndroid Build Coastguard Worker targeting bare metal, the function also clobbers ip/r12 to hold the address of
350*c05d8e5dSAndroid Build Coastguard Worker _Unwind_Resume, which may be too far away for an ordinary branch.
351*c05d8e5dSAndroid Build Coastguard Worker */
352*c05d8e5dSAndroid Build Coastguard Worker __attribute__((used)) static _Unwind_Exception *
__cxa_end_cleanup_impl()353*c05d8e5dSAndroid Build Coastguard Worker __cxa_end_cleanup_impl()
354*c05d8e5dSAndroid Build Coastguard Worker {
355*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals* globals = __cxa_get_globals();
356*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = globals->propagatingExceptions;
357*c05d8e5dSAndroid Build Coastguard Worker if (NULL == exception_header)
358*c05d8e5dSAndroid Build Coastguard Worker {
359*c05d8e5dSAndroid Build Coastguard Worker // It seems that __cxa_begin_cleanup() is not called properly.
360*c05d8e5dSAndroid Build Coastguard Worker // We have no choice but terminate the program now.
361*c05d8e5dSAndroid Build Coastguard Worker std::terminate();
362*c05d8e5dSAndroid Build Coastguard Worker }
363*c05d8e5dSAndroid Build Coastguard Worker
364*c05d8e5dSAndroid Build Coastguard Worker if (__isOurExceptionClass(&exception_header->unwindHeader))
365*c05d8e5dSAndroid Build Coastguard Worker {
366*c05d8e5dSAndroid Build Coastguard Worker --exception_header->propagationCount;
367*c05d8e5dSAndroid Build Coastguard Worker if (0 == exception_header->propagationCount)
368*c05d8e5dSAndroid Build Coastguard Worker {
369*c05d8e5dSAndroid Build Coastguard Worker globals->propagatingExceptions = exception_header->nextPropagatingException;
370*c05d8e5dSAndroid Build Coastguard Worker exception_header->nextPropagatingException = NULL;
371*c05d8e5dSAndroid Build Coastguard Worker }
372*c05d8e5dSAndroid Build Coastguard Worker }
373*c05d8e5dSAndroid Build Coastguard Worker else
374*c05d8e5dSAndroid Build Coastguard Worker {
375*c05d8e5dSAndroid Build Coastguard Worker globals->propagatingExceptions = NULL;
376*c05d8e5dSAndroid Build Coastguard Worker }
377*c05d8e5dSAndroid Build Coastguard Worker return &exception_header->unwindHeader;
378*c05d8e5dSAndroid Build Coastguard Worker }
379*c05d8e5dSAndroid Build Coastguard Worker
380*c05d8e5dSAndroid Build Coastguard Worker asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
381*c05d8e5dSAndroid Build Coastguard Worker " .globl __cxa_end_cleanup\n"
382*c05d8e5dSAndroid Build Coastguard Worker " .type __cxa_end_cleanup,%function\n"
383*c05d8e5dSAndroid Build Coastguard Worker "__cxa_end_cleanup:\n"
384*c05d8e5dSAndroid Build Coastguard Worker #if defined(__ARM_FEATURE_BTI_DEFAULT)
385*c05d8e5dSAndroid Build Coastguard Worker " bti\n"
386*c05d8e5dSAndroid Build Coastguard Worker #endif
387*c05d8e5dSAndroid Build Coastguard Worker " push {r1, r2, r3, r4}\n"
388*c05d8e5dSAndroid Build Coastguard Worker " mov r4, lr\n"
389*c05d8e5dSAndroid Build Coastguard Worker " bl __cxa_end_cleanup_impl\n"
390*c05d8e5dSAndroid Build Coastguard Worker " mov lr, r4\n"
391*c05d8e5dSAndroid Build Coastguard Worker #if defined(LIBCXXABI_BAREMETAL)
392*c05d8e5dSAndroid Build Coastguard Worker " ldr r4, =_Unwind_Resume\n"
393*c05d8e5dSAndroid Build Coastguard Worker " mov ip, r4\n"
394*c05d8e5dSAndroid Build Coastguard Worker #endif
395*c05d8e5dSAndroid Build Coastguard Worker " pop {r1, r2, r3, r4}\n"
396*c05d8e5dSAndroid Build Coastguard Worker #if defined(LIBCXXABI_BAREMETAL)
397*c05d8e5dSAndroid Build Coastguard Worker " bx ip\n"
398*c05d8e5dSAndroid Build Coastguard Worker #else
399*c05d8e5dSAndroid Build Coastguard Worker " b _Unwind_Resume\n"
400*c05d8e5dSAndroid Build Coastguard Worker #endif
401*c05d8e5dSAndroid Build Coastguard Worker " .popsection");
402*c05d8e5dSAndroid Build Coastguard Worker #endif // defined(_LIBCXXABI_ARM_EHABI)
403*c05d8e5dSAndroid Build Coastguard Worker
404*c05d8e5dSAndroid Build Coastguard Worker /*
405*c05d8e5dSAndroid Build Coastguard Worker This routine can catch foreign or native exceptions. If native, the exception
406*c05d8e5dSAndroid Build Coastguard Worker can be a primary or dependent variety. This routine may remain blissfully
407*c05d8e5dSAndroid Build Coastguard Worker ignorant of whether the native exception is primary or dependent.
408*c05d8e5dSAndroid Build Coastguard Worker
409*c05d8e5dSAndroid Build Coastguard Worker If the exception is native:
410*c05d8e5dSAndroid Build Coastguard Worker * Increment's the exception's handler count.
411*c05d8e5dSAndroid Build Coastguard Worker * Push the exception on the stack of currently-caught exceptions if it is not
412*c05d8e5dSAndroid Build Coastguard Worker already there (from a rethrow).
413*c05d8e5dSAndroid Build Coastguard Worker * Decrements the uncaught_exception count.
414*c05d8e5dSAndroid Build Coastguard Worker * Returns the adjusted pointer to the exception object, which is stored in
415*c05d8e5dSAndroid Build Coastguard Worker the __cxa_exception by the personality routine.
416*c05d8e5dSAndroid Build Coastguard Worker
417*c05d8e5dSAndroid Build Coastguard Worker If the exception is foreign, this means it did not originate from one of throw
418*c05d8e5dSAndroid Build Coastguard Worker routines. The foreign exception does not necessarily have a __cxa_exception
419*c05d8e5dSAndroid Build Coastguard Worker header. However we can catch it here with a catch (...), or with a call
420*c05d8e5dSAndroid Build Coastguard Worker to terminate or unexpected during unwinding.
421*c05d8e5dSAndroid Build Coastguard Worker * Do not try to increment the exception's handler count, we don't know where
422*c05d8e5dSAndroid Build Coastguard Worker it is.
423*c05d8e5dSAndroid Build Coastguard Worker * Push the exception on the stack of currently-caught exceptions only if the
424*c05d8e5dSAndroid Build Coastguard Worker stack is empty. The foreign exception has no way to link to the current
425*c05d8e5dSAndroid Build Coastguard Worker top of stack. If the stack is not empty, call terminate. Even with an
426*c05d8e5dSAndroid Build Coastguard Worker empty stack, this is hacked in by pushing a pointer to an imaginary
427*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception block in front of the foreign exception. It would be better
428*c05d8e5dSAndroid Build Coastguard Worker if the __cxa_eh_globals structure had a stack of _Unwind_Exception, but it
429*c05d8e5dSAndroid Build Coastguard Worker doesn't. It has a stack of __cxa_exception (which has a next* in it).
430*c05d8e5dSAndroid Build Coastguard Worker * Do not decrement the uncaught_exception count because we didn't increment it
431*c05d8e5dSAndroid Build Coastguard Worker in __cxa_throw (or one of our rethrow functions).
432*c05d8e5dSAndroid Build Coastguard Worker * If we haven't terminated, assume the exception object is just past the
433*c05d8e5dSAndroid Build Coastguard Worker _Unwind_Exception and return a pointer to that.
434*c05d8e5dSAndroid Build Coastguard Worker */
435*c05d8e5dSAndroid Build Coastguard Worker void*
__cxa_begin_catch(void * unwind_arg)436*c05d8e5dSAndroid Build Coastguard Worker __cxa_begin_catch(void* unwind_arg) throw()
437*c05d8e5dSAndroid Build Coastguard Worker {
438*c05d8e5dSAndroid Build Coastguard Worker _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
439*c05d8e5dSAndroid Build Coastguard Worker bool native_exception = __isOurExceptionClass(unwind_exception);
440*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals* globals = __cxa_get_globals();
441*c05d8e5dSAndroid Build Coastguard Worker // exception_header is a hackish offset from a foreign exception, but it
442*c05d8e5dSAndroid Build Coastguard Worker // works as long as we're careful not to try to access any __cxa_exception
443*c05d8e5dSAndroid Build Coastguard Worker // parts.
444*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header =
445*c05d8e5dSAndroid Build Coastguard Worker cxa_exception_from_exception_unwind_exception
446*c05d8e5dSAndroid Build Coastguard Worker (
447*c05d8e5dSAndroid Build Coastguard Worker static_cast<_Unwind_Exception*>(unwind_exception)
448*c05d8e5dSAndroid Build Coastguard Worker );
449*c05d8e5dSAndroid Build Coastguard Worker if (native_exception)
450*c05d8e5dSAndroid Build Coastguard Worker {
451*c05d8e5dSAndroid Build Coastguard Worker // Increment the handler count, removing the flag about being rethrown
452*c05d8e5dSAndroid Build Coastguard Worker exception_header->handlerCount = exception_header->handlerCount < 0 ?
453*c05d8e5dSAndroid Build Coastguard Worker -exception_header->handlerCount + 1 : exception_header->handlerCount + 1;
454*c05d8e5dSAndroid Build Coastguard Worker // place the exception on the top of the stack if it's not already
455*c05d8e5dSAndroid Build Coastguard Worker // there by a previous rethrow
456*c05d8e5dSAndroid Build Coastguard Worker if (exception_header != globals->caughtExceptions)
457*c05d8e5dSAndroid Build Coastguard Worker {
458*c05d8e5dSAndroid Build Coastguard Worker exception_header->nextException = globals->caughtExceptions;
459*c05d8e5dSAndroid Build Coastguard Worker globals->caughtExceptions = exception_header;
460*c05d8e5dSAndroid Build Coastguard Worker }
461*c05d8e5dSAndroid Build Coastguard Worker globals->uncaughtExceptions -= 1; // Not atomically, since globals are thread-local
462*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_ARM_EHABI)
463*c05d8e5dSAndroid Build Coastguard Worker return reinterpret_cast<void*>(exception_header->unwindHeader.barrier_cache.bitpattern[0]);
464*c05d8e5dSAndroid Build Coastguard Worker #else
465*c05d8e5dSAndroid Build Coastguard Worker return exception_header->adjustedPtr;
466*c05d8e5dSAndroid Build Coastguard Worker #endif
467*c05d8e5dSAndroid Build Coastguard Worker }
468*c05d8e5dSAndroid Build Coastguard Worker // Else this is a foreign exception
469*c05d8e5dSAndroid Build Coastguard Worker // If the caughtExceptions stack is not empty, terminate
470*c05d8e5dSAndroid Build Coastguard Worker if (globals->caughtExceptions != 0)
471*c05d8e5dSAndroid Build Coastguard Worker std::terminate();
472*c05d8e5dSAndroid Build Coastguard Worker // Push the foreign exception on to the stack
473*c05d8e5dSAndroid Build Coastguard Worker globals->caughtExceptions = exception_header;
474*c05d8e5dSAndroid Build Coastguard Worker return unwind_exception + 1;
475*c05d8e5dSAndroid Build Coastguard Worker }
476*c05d8e5dSAndroid Build Coastguard Worker
477*c05d8e5dSAndroid Build Coastguard Worker
478*c05d8e5dSAndroid Build Coastguard Worker /*
479*c05d8e5dSAndroid Build Coastguard Worker Upon exit for any reason, a handler must call:
480*c05d8e5dSAndroid Build Coastguard Worker void __cxa_end_catch ();
481*c05d8e5dSAndroid Build Coastguard Worker
482*c05d8e5dSAndroid Build Coastguard Worker This routine can be called for either a native or foreign exception.
483*c05d8e5dSAndroid Build Coastguard Worker For a native exception:
484*c05d8e5dSAndroid Build Coastguard Worker * Locates the most recently caught exception and decrements its handler count.
485*c05d8e5dSAndroid Build Coastguard Worker * Removes the exception from the caught exception stack, if the handler count goes to zero.
486*c05d8e5dSAndroid Build Coastguard Worker * If the handler count goes down to zero, and the exception was not re-thrown
487*c05d8e5dSAndroid Build Coastguard Worker by throw, it locates the primary exception (which may be the same as the one
488*c05d8e5dSAndroid Build Coastguard Worker it's handling) and decrements its reference count. If that reference count
489*c05d8e5dSAndroid Build Coastguard Worker goes to zero, the function destroys the exception. In any case, if the current
490*c05d8e5dSAndroid Build Coastguard Worker exception is a dependent exception, it destroys that.
491*c05d8e5dSAndroid Build Coastguard Worker
492*c05d8e5dSAndroid Build Coastguard Worker For a foreign exception:
493*c05d8e5dSAndroid Build Coastguard Worker * If it has been rethrown, there is nothing to do.
494*c05d8e5dSAndroid Build Coastguard Worker * Otherwise delete the exception and pop the catch stack to empty.
495*c05d8e5dSAndroid Build Coastguard Worker */
__cxa_end_catch()496*c05d8e5dSAndroid Build Coastguard Worker void __cxa_end_catch() {
497*c05d8e5dSAndroid Build Coastguard Worker static_assert(sizeof(__cxa_exception) == sizeof(__cxa_dependent_exception),
498*c05d8e5dSAndroid Build Coastguard Worker "sizeof(__cxa_exception) must be equal to "
499*c05d8e5dSAndroid Build Coastguard Worker "sizeof(__cxa_dependent_exception)");
500*c05d8e5dSAndroid Build Coastguard Worker static_assert(__builtin_offsetof(__cxa_exception, referenceCount) ==
501*c05d8e5dSAndroid Build Coastguard Worker __builtin_offsetof(__cxa_dependent_exception,
502*c05d8e5dSAndroid Build Coastguard Worker primaryException),
503*c05d8e5dSAndroid Build Coastguard Worker "the layout of __cxa_exception must match the layout of "
504*c05d8e5dSAndroid Build Coastguard Worker "__cxa_dependent_exception");
505*c05d8e5dSAndroid Build Coastguard Worker static_assert(__builtin_offsetof(__cxa_exception, handlerCount) ==
506*c05d8e5dSAndroid Build Coastguard Worker __builtin_offsetof(__cxa_dependent_exception, handlerCount),
507*c05d8e5dSAndroid Build Coastguard Worker "the layout of __cxa_exception must match the layout of "
508*c05d8e5dSAndroid Build Coastguard Worker "__cxa_dependent_exception");
509*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals* globals = __cxa_get_globals_fast(); // __cxa_get_globals called in __cxa_begin_catch
510*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = globals->caughtExceptions;
511*c05d8e5dSAndroid Build Coastguard Worker // If we've rethrown a foreign exception, then globals->caughtExceptions
512*c05d8e5dSAndroid Build Coastguard Worker // will have been made an empty stack by __cxa_rethrow() and there is
513*c05d8e5dSAndroid Build Coastguard Worker // nothing more to be done. Do nothing!
514*c05d8e5dSAndroid Build Coastguard Worker if (NULL != exception_header)
515*c05d8e5dSAndroid Build Coastguard Worker {
516*c05d8e5dSAndroid Build Coastguard Worker bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader);
517*c05d8e5dSAndroid Build Coastguard Worker if (native_exception)
518*c05d8e5dSAndroid Build Coastguard Worker {
519*c05d8e5dSAndroid Build Coastguard Worker // This is a native exception
520*c05d8e5dSAndroid Build Coastguard Worker if (exception_header->handlerCount < 0)
521*c05d8e5dSAndroid Build Coastguard Worker {
522*c05d8e5dSAndroid Build Coastguard Worker // The exception has been rethrown by __cxa_rethrow, so don't delete it
523*c05d8e5dSAndroid Build Coastguard Worker if (0 == incrementHandlerCount(exception_header))
524*c05d8e5dSAndroid Build Coastguard Worker {
525*c05d8e5dSAndroid Build Coastguard Worker // Remove from the chain of uncaught exceptions
526*c05d8e5dSAndroid Build Coastguard Worker globals->caughtExceptions = exception_header->nextException;
527*c05d8e5dSAndroid Build Coastguard Worker // but don't destroy
528*c05d8e5dSAndroid Build Coastguard Worker }
529*c05d8e5dSAndroid Build Coastguard Worker // Keep handlerCount negative in case there are nested catch's
530*c05d8e5dSAndroid Build Coastguard Worker // that need to be told that this exception is rethrown. Don't
531*c05d8e5dSAndroid Build Coastguard Worker // erase this rethrow flag until the exception is recaught.
532*c05d8e5dSAndroid Build Coastguard Worker }
533*c05d8e5dSAndroid Build Coastguard Worker else
534*c05d8e5dSAndroid Build Coastguard Worker {
535*c05d8e5dSAndroid Build Coastguard Worker // The native exception has not been rethrown
536*c05d8e5dSAndroid Build Coastguard Worker if (0 == decrementHandlerCount(exception_header))
537*c05d8e5dSAndroid Build Coastguard Worker {
538*c05d8e5dSAndroid Build Coastguard Worker // Remove from the chain of uncaught exceptions
539*c05d8e5dSAndroid Build Coastguard Worker globals->caughtExceptions = exception_header->nextException;
540*c05d8e5dSAndroid Build Coastguard Worker // Destroy this exception, being careful to distinguish
541*c05d8e5dSAndroid Build Coastguard Worker // between dependent and primary exceptions
542*c05d8e5dSAndroid Build Coastguard Worker if (isDependentException(&exception_header->unwindHeader))
543*c05d8e5dSAndroid Build Coastguard Worker {
544*c05d8e5dSAndroid Build Coastguard Worker // Reset exception_header to primaryException and deallocate the dependent exception
545*c05d8e5dSAndroid Build Coastguard Worker __cxa_dependent_exception* dep_exception_header =
546*c05d8e5dSAndroid Build Coastguard Worker reinterpret_cast<__cxa_dependent_exception*>(exception_header);
547*c05d8e5dSAndroid Build Coastguard Worker exception_header =
548*c05d8e5dSAndroid Build Coastguard Worker cxa_exception_from_thrown_object(dep_exception_header->primaryException);
549*c05d8e5dSAndroid Build Coastguard Worker __cxa_free_dependent_exception(dep_exception_header);
550*c05d8e5dSAndroid Build Coastguard Worker }
551*c05d8e5dSAndroid Build Coastguard Worker // Destroy the primary exception only if its referenceCount goes to 0
552*c05d8e5dSAndroid Build Coastguard Worker // (this decrement must be atomic)
553*c05d8e5dSAndroid Build Coastguard Worker __cxa_decrement_exception_refcount(thrown_object_from_cxa_exception(exception_header));
554*c05d8e5dSAndroid Build Coastguard Worker }
555*c05d8e5dSAndroid Build Coastguard Worker }
556*c05d8e5dSAndroid Build Coastguard Worker }
557*c05d8e5dSAndroid Build Coastguard Worker else
558*c05d8e5dSAndroid Build Coastguard Worker {
559*c05d8e5dSAndroid Build Coastguard Worker // The foreign exception has not been rethrown. Pop the stack
560*c05d8e5dSAndroid Build Coastguard Worker // and delete it. If there are nested catch's and they try
561*c05d8e5dSAndroid Build Coastguard Worker // to touch a foreign exception in any way, that is undefined
562*c05d8e5dSAndroid Build Coastguard Worker // behavior. They likely can't since the only way to catch
563*c05d8e5dSAndroid Build Coastguard Worker // a foreign exception is with catch (...)!
564*c05d8e5dSAndroid Build Coastguard Worker _Unwind_DeleteException(&globals->caughtExceptions->unwindHeader);
565*c05d8e5dSAndroid Build Coastguard Worker globals->caughtExceptions = 0;
566*c05d8e5dSAndroid Build Coastguard Worker }
567*c05d8e5dSAndroid Build Coastguard Worker }
568*c05d8e5dSAndroid Build Coastguard Worker }
569*c05d8e5dSAndroid Build Coastguard Worker
570*c05d8e5dSAndroid Build Coastguard Worker // Note: exception_header may be masquerading as a __cxa_dependent_exception
571*c05d8e5dSAndroid Build Coastguard Worker // and that's ok. exceptionType is there too.
572*c05d8e5dSAndroid Build Coastguard Worker // However watch out for foreign exceptions. Return null for them.
__cxa_current_exception_type()573*c05d8e5dSAndroid Build Coastguard Worker std::type_info *__cxa_current_exception_type() {
574*c05d8e5dSAndroid Build Coastguard Worker // get the current exception
575*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals *globals = __cxa_get_globals_fast();
576*c05d8e5dSAndroid Build Coastguard Worker if (NULL == globals)
577*c05d8e5dSAndroid Build Coastguard Worker return NULL; // If there have never been any exceptions, there are none now.
578*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception *exception_header = globals->caughtExceptions;
579*c05d8e5dSAndroid Build Coastguard Worker if (NULL == exception_header)
580*c05d8e5dSAndroid Build Coastguard Worker return NULL; // No current exception
581*c05d8e5dSAndroid Build Coastguard Worker if (!__isOurExceptionClass(&exception_header->unwindHeader))
582*c05d8e5dSAndroid Build Coastguard Worker return NULL;
583*c05d8e5dSAndroid Build Coastguard Worker return exception_header->exceptionType;
584*c05d8e5dSAndroid Build Coastguard Worker }
585*c05d8e5dSAndroid Build Coastguard Worker
586*c05d8e5dSAndroid Build Coastguard Worker // 2.5.4 Rethrowing Exceptions
587*c05d8e5dSAndroid Build Coastguard Worker /* This routine can rethrow native or foreign exceptions.
588*c05d8e5dSAndroid Build Coastguard Worker If the exception is native:
589*c05d8e5dSAndroid Build Coastguard Worker * marks the exception object on top of the caughtExceptions stack
590*c05d8e5dSAndroid Build Coastguard Worker (in an implementation-defined way) as being rethrown.
591*c05d8e5dSAndroid Build Coastguard Worker * If the caughtExceptions stack is empty, it calls terminate()
592*c05d8e5dSAndroid Build Coastguard Worker (see [C++FDIS] [except.throw], 15.1.8).
593*c05d8e5dSAndroid Build Coastguard Worker * It then calls _Unwind_RaiseException which should not return
594*c05d8e5dSAndroid Build Coastguard Worker (terminate if it does).
595*c05d8e5dSAndroid Build Coastguard Worker Note: exception_header may be masquerading as a __cxa_dependent_exception
596*c05d8e5dSAndroid Build Coastguard Worker and that's ok.
597*c05d8e5dSAndroid Build Coastguard Worker */
__cxa_rethrow()598*c05d8e5dSAndroid Build Coastguard Worker void __cxa_rethrow() {
599*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals* globals = __cxa_get_globals();
600*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = globals->caughtExceptions;
601*c05d8e5dSAndroid Build Coastguard Worker if (NULL == exception_header)
602*c05d8e5dSAndroid Build Coastguard Worker std::terminate(); // throw; called outside of a exception handler
603*c05d8e5dSAndroid Build Coastguard Worker bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader);
604*c05d8e5dSAndroid Build Coastguard Worker if (native_exception)
605*c05d8e5dSAndroid Build Coastguard Worker {
606*c05d8e5dSAndroid Build Coastguard Worker // Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch)
607*c05d8e5dSAndroid Build Coastguard Worker exception_header->handlerCount = -exception_header->handlerCount;
608*c05d8e5dSAndroid Build Coastguard Worker globals->uncaughtExceptions += 1;
609*c05d8e5dSAndroid Build Coastguard Worker // __cxa_end_catch will remove this exception from the caughtExceptions stack if necessary
610*c05d8e5dSAndroid Build Coastguard Worker }
611*c05d8e5dSAndroid Build Coastguard Worker else // this is a foreign exception
612*c05d8e5dSAndroid Build Coastguard Worker {
613*c05d8e5dSAndroid Build Coastguard Worker // The only way to communicate to __cxa_end_catch that we've rethrown
614*c05d8e5dSAndroid Build Coastguard Worker // a foreign exception, so don't delete us, is to pop the stack here
615*c05d8e5dSAndroid Build Coastguard Worker // which must be empty afterwards. Then __cxa_end_catch will do
616*c05d8e5dSAndroid Build Coastguard Worker // nothing
617*c05d8e5dSAndroid Build Coastguard Worker globals->caughtExceptions = 0;
618*c05d8e5dSAndroid Build Coastguard Worker }
619*c05d8e5dSAndroid Build Coastguard Worker #ifdef __USING_SJLJ_EXCEPTIONS__
620*c05d8e5dSAndroid Build Coastguard Worker _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
621*c05d8e5dSAndroid Build Coastguard Worker #else
622*c05d8e5dSAndroid Build Coastguard Worker _Unwind_RaiseException(&exception_header->unwindHeader);
623*c05d8e5dSAndroid Build Coastguard Worker #endif
624*c05d8e5dSAndroid Build Coastguard Worker
625*c05d8e5dSAndroid Build Coastguard Worker // If we get here, some kind of unwinding error has occurred.
626*c05d8e5dSAndroid Build Coastguard Worker // There is some weird code generation bug happening with
627*c05d8e5dSAndroid Build Coastguard Worker // Apple clang version 4.0 (tags/Apple/clang-418.0.2) (based on LLVM 3.1svn)
628*c05d8e5dSAndroid Build Coastguard Worker // If we call failed_throw here. Turns up with -O2 or higher, and -Os.
629*c05d8e5dSAndroid Build Coastguard Worker __cxa_begin_catch(&exception_header->unwindHeader);
630*c05d8e5dSAndroid Build Coastguard Worker if (native_exception)
631*c05d8e5dSAndroid Build Coastguard Worker std::__terminate(exception_header->terminateHandler);
632*c05d8e5dSAndroid Build Coastguard Worker // Foreign exception: can't get exception_header->terminateHandler
633*c05d8e5dSAndroid Build Coastguard Worker std::terminate();
634*c05d8e5dSAndroid Build Coastguard Worker }
635*c05d8e5dSAndroid Build Coastguard Worker
636*c05d8e5dSAndroid Build Coastguard Worker /*
637*c05d8e5dSAndroid Build Coastguard Worker If thrown_object is not null, atomically increment the referenceCount field
638*c05d8e5dSAndroid Build Coastguard Worker of the __cxa_exception header associated with the thrown object referred to
639*c05d8e5dSAndroid Build Coastguard Worker by thrown_object.
640*c05d8e5dSAndroid Build Coastguard Worker
641*c05d8e5dSAndroid Build Coastguard Worker Requires: If thrown_object is not NULL, it is a native exception.
642*c05d8e5dSAndroid Build Coastguard Worker */
643*c05d8e5dSAndroid Build Coastguard Worker void
__cxa_increment_exception_refcount(void * thrown_object)644*c05d8e5dSAndroid Build Coastguard Worker __cxa_increment_exception_refcount(void *thrown_object) throw() {
645*c05d8e5dSAndroid Build Coastguard Worker if (thrown_object != NULL )
646*c05d8e5dSAndroid Build Coastguard Worker {
647*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
648*c05d8e5dSAndroid Build Coastguard Worker std::__libcpp_atomic_add(&exception_header->referenceCount, size_t(1));
649*c05d8e5dSAndroid Build Coastguard Worker }
650*c05d8e5dSAndroid Build Coastguard Worker }
651*c05d8e5dSAndroid Build Coastguard Worker
652*c05d8e5dSAndroid Build Coastguard Worker /*
653*c05d8e5dSAndroid Build Coastguard Worker If thrown_object is not null, atomically decrement the referenceCount field
654*c05d8e5dSAndroid Build Coastguard Worker of the __cxa_exception header associated with the thrown object referred to
655*c05d8e5dSAndroid Build Coastguard Worker by thrown_object. If the referenceCount drops to zero, destroy and
656*c05d8e5dSAndroid Build Coastguard Worker deallocate the exception.
657*c05d8e5dSAndroid Build Coastguard Worker
658*c05d8e5dSAndroid Build Coastguard Worker Requires: If thrown_object is not NULL, it is a native exception.
659*c05d8e5dSAndroid Build Coastguard Worker */
660*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_NO_CFI
__cxa_decrement_exception_refcount(void * thrown_object)661*c05d8e5dSAndroid Build Coastguard Worker void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
662*c05d8e5dSAndroid Build Coastguard Worker if (thrown_object != NULL )
663*c05d8e5dSAndroid Build Coastguard Worker {
664*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
665*c05d8e5dSAndroid Build Coastguard Worker if (std::__libcpp_atomic_add(&exception_header->referenceCount, size_t(-1)) == 0)
666*c05d8e5dSAndroid Build Coastguard Worker {
667*c05d8e5dSAndroid Build Coastguard Worker if (NULL != exception_header->exceptionDestructor)
668*c05d8e5dSAndroid Build Coastguard Worker exception_header->exceptionDestructor(thrown_object);
669*c05d8e5dSAndroid Build Coastguard Worker __cxa_free_exception(thrown_object);
670*c05d8e5dSAndroid Build Coastguard Worker }
671*c05d8e5dSAndroid Build Coastguard Worker }
672*c05d8e5dSAndroid Build Coastguard Worker }
673*c05d8e5dSAndroid Build Coastguard Worker
674*c05d8e5dSAndroid Build Coastguard Worker /*
675*c05d8e5dSAndroid Build Coastguard Worker Returns a pointer to the thrown object (if any) at the top of the
676*c05d8e5dSAndroid Build Coastguard Worker caughtExceptions stack. Atomically increment the exception's referenceCount.
677*c05d8e5dSAndroid Build Coastguard Worker If there is no such thrown object or if the thrown object is foreign,
678*c05d8e5dSAndroid Build Coastguard Worker returns null.
679*c05d8e5dSAndroid Build Coastguard Worker
680*c05d8e5dSAndroid Build Coastguard Worker We can use __cxa_get_globals_fast here to get the globals because if there have
681*c05d8e5dSAndroid Build Coastguard Worker been no exceptions thrown, ever, on this thread, we can return NULL without
682*c05d8e5dSAndroid Build Coastguard Worker the need to allocate the exception-handling globals.
683*c05d8e5dSAndroid Build Coastguard Worker */
__cxa_current_primary_exception()684*c05d8e5dSAndroid Build Coastguard Worker void *__cxa_current_primary_exception() throw() {
685*c05d8e5dSAndroid Build Coastguard Worker // get the current exception
686*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals* globals = __cxa_get_globals_fast();
687*c05d8e5dSAndroid Build Coastguard Worker if (NULL == globals)
688*c05d8e5dSAndroid Build Coastguard Worker return NULL; // If there are no globals, there is no exception
689*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = globals->caughtExceptions;
690*c05d8e5dSAndroid Build Coastguard Worker if (NULL == exception_header)
691*c05d8e5dSAndroid Build Coastguard Worker return NULL; // No current exception
692*c05d8e5dSAndroid Build Coastguard Worker if (!__isOurExceptionClass(&exception_header->unwindHeader))
693*c05d8e5dSAndroid Build Coastguard Worker return NULL; // Can't capture a foreign exception (no way to refcount it)
694*c05d8e5dSAndroid Build Coastguard Worker if (isDependentException(&exception_header->unwindHeader)) {
695*c05d8e5dSAndroid Build Coastguard Worker __cxa_dependent_exception* dep_exception_header =
696*c05d8e5dSAndroid Build Coastguard Worker reinterpret_cast<__cxa_dependent_exception*>(exception_header);
697*c05d8e5dSAndroid Build Coastguard Worker exception_header = cxa_exception_from_thrown_object(dep_exception_header->primaryException);
698*c05d8e5dSAndroid Build Coastguard Worker }
699*c05d8e5dSAndroid Build Coastguard Worker void* thrown_object = thrown_object_from_cxa_exception(exception_header);
700*c05d8e5dSAndroid Build Coastguard Worker __cxa_increment_exception_refcount(thrown_object);
701*c05d8e5dSAndroid Build Coastguard Worker return thrown_object;
702*c05d8e5dSAndroid Build Coastguard Worker }
703*c05d8e5dSAndroid Build Coastguard Worker
704*c05d8e5dSAndroid Build Coastguard Worker /*
705*c05d8e5dSAndroid Build Coastguard Worker If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
706*c05d8e5dSAndroid Build Coastguard Worker stored in exc is called. Otherwise the referenceCount stored in the
707*c05d8e5dSAndroid Build Coastguard Worker primary exception is decremented, destroying the primary if necessary.
708*c05d8e5dSAndroid Build Coastguard Worker Finally the dependent exception is destroyed.
709*c05d8e5dSAndroid Build Coastguard Worker */
710*c05d8e5dSAndroid Build Coastguard Worker static
711*c05d8e5dSAndroid Build Coastguard Worker void
dependent_exception_cleanup(_Unwind_Reason_Code reason,_Unwind_Exception * unwind_exception)712*c05d8e5dSAndroid Build Coastguard Worker dependent_exception_cleanup(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception)
713*c05d8e5dSAndroid Build Coastguard Worker {
714*c05d8e5dSAndroid Build Coastguard Worker __cxa_dependent_exception* dep_exception_header =
715*c05d8e5dSAndroid Build Coastguard Worker reinterpret_cast<__cxa_dependent_exception*>(unwind_exception + 1) - 1;
716*c05d8e5dSAndroid Build Coastguard Worker if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
717*c05d8e5dSAndroid Build Coastguard Worker std::__terminate(dep_exception_header->terminateHandler);
718*c05d8e5dSAndroid Build Coastguard Worker __cxa_decrement_exception_refcount(dep_exception_header->primaryException);
719*c05d8e5dSAndroid Build Coastguard Worker __cxa_free_dependent_exception(dep_exception_header);
720*c05d8e5dSAndroid Build Coastguard Worker }
721*c05d8e5dSAndroid Build Coastguard Worker
722*c05d8e5dSAndroid Build Coastguard Worker /*
723*c05d8e5dSAndroid Build Coastguard Worker If thrown_object is not null, allocate, initialize and throw a dependent
724*c05d8e5dSAndroid Build Coastguard Worker exception.
725*c05d8e5dSAndroid Build Coastguard Worker */
726*c05d8e5dSAndroid Build Coastguard Worker void
__cxa_rethrow_primary_exception(void * thrown_object)727*c05d8e5dSAndroid Build Coastguard Worker __cxa_rethrow_primary_exception(void* thrown_object)
728*c05d8e5dSAndroid Build Coastguard Worker {
729*c05d8e5dSAndroid Build Coastguard Worker if ( thrown_object != NULL )
730*c05d8e5dSAndroid Build Coastguard Worker {
731*c05d8e5dSAndroid Build Coastguard Worker // thrown_object guaranteed to be native because
732*c05d8e5dSAndroid Build Coastguard Worker // __cxa_current_primary_exception returns NULL for foreign exceptions
733*c05d8e5dSAndroid Build Coastguard Worker __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
734*c05d8e5dSAndroid Build Coastguard Worker __cxa_dependent_exception* dep_exception_header =
735*c05d8e5dSAndroid Build Coastguard Worker static_cast<__cxa_dependent_exception*>(__cxa_allocate_dependent_exception());
736*c05d8e5dSAndroid Build Coastguard Worker dep_exception_header->primaryException = thrown_object;
737*c05d8e5dSAndroid Build Coastguard Worker __cxa_increment_exception_refcount(thrown_object);
738*c05d8e5dSAndroid Build Coastguard Worker dep_exception_header->exceptionType = exception_header->exceptionType;
739*c05d8e5dSAndroid Build Coastguard Worker dep_exception_header->unexpectedHandler = std::get_unexpected();
740*c05d8e5dSAndroid Build Coastguard Worker dep_exception_header->terminateHandler = std::get_terminate();
741*c05d8e5dSAndroid Build Coastguard Worker setDependentExceptionClass(&dep_exception_header->unwindHeader);
742*c05d8e5dSAndroid Build Coastguard Worker __cxa_get_globals()->uncaughtExceptions += 1;
743*c05d8e5dSAndroid Build Coastguard Worker dep_exception_header->unwindHeader.exception_cleanup = dependent_exception_cleanup;
744*c05d8e5dSAndroid Build Coastguard Worker #ifdef __USING_SJLJ_EXCEPTIONS__
745*c05d8e5dSAndroid Build Coastguard Worker _Unwind_SjLj_RaiseException(&dep_exception_header->unwindHeader);
746*c05d8e5dSAndroid Build Coastguard Worker #else
747*c05d8e5dSAndroid Build Coastguard Worker _Unwind_RaiseException(&dep_exception_header->unwindHeader);
748*c05d8e5dSAndroid Build Coastguard Worker #endif
749*c05d8e5dSAndroid Build Coastguard Worker // Some sort of unwinding error. Note that terminate is a handler.
750*c05d8e5dSAndroid Build Coastguard Worker __cxa_begin_catch(&dep_exception_header->unwindHeader);
751*c05d8e5dSAndroid Build Coastguard Worker }
752*c05d8e5dSAndroid Build Coastguard Worker // If we return client will call terminate()
753*c05d8e5dSAndroid Build Coastguard Worker }
754*c05d8e5dSAndroid Build Coastguard Worker
755*c05d8e5dSAndroid Build Coastguard Worker bool
__cxa_uncaught_exception()756*c05d8e5dSAndroid Build Coastguard Worker __cxa_uncaught_exception() throw() { return __cxa_uncaught_exceptions() != 0; }
757*c05d8e5dSAndroid Build Coastguard Worker
758*c05d8e5dSAndroid Build Coastguard Worker unsigned int
__cxa_uncaught_exceptions()759*c05d8e5dSAndroid Build Coastguard Worker __cxa_uncaught_exceptions() throw()
760*c05d8e5dSAndroid Build Coastguard Worker {
761*c05d8e5dSAndroid Build Coastguard Worker // This does not report foreign exceptions in flight
762*c05d8e5dSAndroid Build Coastguard Worker __cxa_eh_globals* globals = __cxa_get_globals_fast();
763*c05d8e5dSAndroid Build Coastguard Worker if (globals == 0)
764*c05d8e5dSAndroid Build Coastguard Worker return 0;
765*c05d8e5dSAndroid Build Coastguard Worker return globals->uncaughtExceptions;
766*c05d8e5dSAndroid Build Coastguard Worker }
767*c05d8e5dSAndroid Build Coastguard Worker
768*c05d8e5dSAndroid Build Coastguard Worker } // extern "C"
769*c05d8e5dSAndroid Build Coastguard Worker
770*c05d8e5dSAndroid Build Coastguard Worker } // abi
771