blob: ed2d7d1f8ccb3cb36b8fe70ae2c8e25bef8f2e40 [file] [log] [blame]
Marshall Clowe2dcb752011-07-20 15:04:39 +00001//===------------------------- cxa_exception.cpp --------------------------===//
2//
Chandler Carruth57b08b02019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Marshall Clowe2dcb752011-07-20 15:04:39 +00006//
7//
8// This file implements the "Exception Handling APIs"
Jonathan Roelofsc5f7e6f2014-02-12 04:49:09 +00009// http://mentorembedded.github.io/cxx-abi/abi-eh.html
Marshall Clowe2dcb752011-07-20 15:04:39 +000010//
11//===----------------------------------------------------------------------===//
12
13#include "cxxabi.h"
14
15#include <exception> // for std::terminate
Howard Hinnant862c4a02013-06-17 18:10:34 +000016#include <cstring> // for memset
Marshall Clowe2dcb752011-07-20 15:04:39 +000017#include "cxa_exception.hpp"
Howard Hinnant5ec91832011-12-07 21:16:40 +000018#include "cxa_handlers.hpp"
Igor Kudrind9edde42016-10-07 08:48:28 +000019#include "fallback_malloc.h"
Eli Friedman17a47b92018-04-16 22:00:14 +000020#include "include/atomic_support.h"
Marshall Clowe2dcb752011-07-20 15:04:39 +000021
Petr Hosek229e0852017-09-13 23:35:07 +000022#if __has_feature(address_sanitizer)
Eric Fiselierc4600cc2017-09-14 22:37:34 +000023extern "C" void __asan_handle_no_return(void);
Petr Hosek229e0852017-09-13 23:35:07 +000024#endif
25
Howard Hinnantafcf7ac2012-01-22 19:14:27 +000026// +---------------------------+-----------------------------+---------------+
27// | __cxa_exception | _Unwind_Exception CLNGC++\0 | thrown object |
28// +---------------------------+-----------------------------+---------------+
29// ^
30// |
31// +-------------------------------------------------------+
32// |
33// +---------------------------+-----------------------------+
34// | __cxa_dependent_exception | _Unwind_Exception CLNGC++\1 |
35// +---------------------------+-----------------------------+
36
Marshall Clowe2dcb752011-07-20 15:04:39 +000037namespace __cxxabiv1 {
Howard Hinnant6830b2a2012-01-24 18:15:20 +000038
Marshall Clowe2dcb752011-07-20 15:04:39 +000039// Utility routines
Howard Hinnantafcf7ac2012-01-22 19:14:27 +000040static
41inline
42__cxa_exception*
Howard Hinnant47cb85482012-01-30 16:07:00 +000043cxa_exception_from_thrown_object(void* thrown_object)
Howard Hinnantafcf7ac2012-01-22 19:14:27 +000044{
45 return static_cast<__cxa_exception*>(thrown_object) - 1;
Marshall Clow9b454bc2011-08-15 18:06:47 +000046}
Marshall Clowe2dcb752011-07-20 15:04:39 +000047
Howard Hinnantafcf7ac2012-01-22 19:14:27 +000048// Note: This is never called when exception_header is masquerading as a
49// __cxa_dependent_exception.
50static
51inline
52void*
Howard Hinnant47cb85482012-01-30 16:07:00 +000053thrown_object_from_cxa_exception(__cxa_exception* exception_header)
Howard Hinnantafcf7ac2012-01-22 19:14:27 +000054{
55 return static_cast<void*>(exception_header + 1);
Marshall Clow9b454bc2011-08-15 18:06:47 +000056}
Marshall Clowe2dcb752011-07-20 15:04:39 +000057
Marshall Clow87694492011-08-09 15:09:41 +000058// Get the exception object from the unwind pointer.
59// Relies on the structure layout, where the unwind pointer is right in
60// front of the user's exception object
Howard Hinnantafcf7ac2012-01-22 19:14:27 +000061static
62inline
63__cxa_exception*
Howard Hinnant47cb85482012-01-30 16:07:00 +000064cxa_exception_from_exception_unwind_exception(_Unwind_Exception* unwind_exception)
Howard Hinnantafcf7ac2012-01-22 19:14:27 +000065{
66 return cxa_exception_from_thrown_object(unwind_exception + 1 );
Marshall Clow9b454bc2011-08-15 18:06:47 +000067}
Marshall Clow87694492011-08-09 15:09:41 +000068
Eric Fiselierc74a2e12017-03-04 02:04:45 +000069// Round s up to next multiple of a.
70static inline
71size_t aligned_allocation_size(size_t s, size_t a) {
72 return (s + a - 1) & ~(a - 1);
73}
74
75static inline
76size_t cxa_exception_size_from_exception_thrown_size(size_t size) {
77 return aligned_allocation_size(size + sizeof (__cxa_exception),
78 alignof(__cxa_exception));
Marshall Clow9b454bc2011-08-15 18:06:47 +000079}
Marshall Clow87694492011-08-09 15:09:41 +000080
Marshall Clow611a55a2018-10-10 16:18:37 +000081void __setExceptionClass(_Unwind_Exception* unwind_exception, uint64_t newValue) {
82 ::memcpy(&unwind_exception->exception_class, &newValue, sizeof(newValue));
83 }
84
85
86static void setOurExceptionClass(_Unwind_Exception* unwind_exception) {
87 __setExceptionClass(unwind_exception, kOurExceptionClass);
Howard Hinnantafcf7ac2012-01-22 19:14:27 +000088}
89
Howard Hinnant47cb85482012-01-30 16:07:00 +000090static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) {
Marshall Clow611a55a2018-10-10 16:18:37 +000091 __setExceptionClass(unwind_exception, kOurDependentExceptionClass);
Marshall Clow9b454bc2011-08-15 18:06:47 +000092}
Marshall Clow87694492011-08-09 15:09:41 +000093
94// Is it one of ours?
Marshall Clow611a55a2018-10-10 16:18:37 +000095uint64_t __getExceptionClass(const _Unwind_Exception* unwind_exception) {
96// On x86 and some ARM unwinders, unwind_exception->exception_class is
97// a uint64_t. On other ARM unwinders, it is a char[8]
98// See: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
99// So we just copy it into a uint64_t to be sure.
100 uint64_t exClass;
101 ::memcpy(&exClass, &unwind_exception->exception_class, sizeof(exClass));
102 return exClass;
103}
104
105bool __isOurExceptionClass(const _Unwind_Exception* unwind_exception) {
106 return (__getExceptionClass(unwind_exception) & get_vendor_and_language) ==
107 (kOurExceptionClass & get_vendor_and_language);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000108}
Marshall Clow87694492011-08-09 15:09:41 +0000109
Howard Hinnant47cb85482012-01-30 16:07:00 +0000110static bool isDependentException(_Unwind_Exception* unwind_exception) {
Marshall Clow611a55a2018-10-10 16:18:37 +0000111 return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01;
Marshall Clow9b454bc2011-08-15 18:06:47 +0000112}
113
Howard Hinnant6ccae152011-12-08 19:35:18 +0000114// This does not need to be atomic
Howard Hinnant47cb85482012-01-30 16:07:00 +0000115static inline int incrementHandlerCount(__cxa_exception *exception) {
Howard Hinnant6ccae152011-12-08 19:35:18 +0000116 return ++exception->handlerCount;
Marshall Clow9b454bc2011-08-15 18:06:47 +0000117}
118
Howard Hinnant6ccae152011-12-08 19:35:18 +0000119// This does not need to be atomic
Howard Hinnant47cb85482012-01-30 16:07:00 +0000120static inline int decrementHandlerCount(__cxa_exception *exception) {
Howard Hinnant6ccae152011-12-08 19:35:18 +0000121 return --exception->handlerCount;
Marshall Clow9b454bc2011-08-15 18:06:47 +0000122}
Marshall Clow87694492011-08-09 15:09:41 +0000123
Howard Hinnant5ec91832011-12-07 21:16:40 +0000124/*
Marshall Clow87694492011-08-09 15:09:41 +0000125 If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
126 stored in exc is called. Otherwise the exceptionDestructor stored in
127 exc is called, and then the memory for the exception is deallocated.
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000128
129 This is never called for a __cxa_dependent_exception.
Marshall Clow87694492011-08-09 15:09:41 +0000130*/
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000131static
132void
133exception_cleanup_func(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception)
134{
135 __cxa_exception* exception_header = cxa_exception_from_exception_unwind_exception(unwind_exception);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000136 if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000137 std::__terminate(exception_header->terminateHandler);
Howard Hinnantd0bfbb32012-02-01 18:44:21 +0000138 // Just in case there exists a dependent exception that is pointing to this,
139 // check the reference count and only destroy this if that count goes to zero.
140 __cxa_decrement_exception_refcount(unwind_exception + 1);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000141}
Marshall Clow87694492011-08-09 15:09:41 +0000142
Eric Fiselier71e32922017-03-01 02:23:54 +0000143static _LIBCXXABI_NORETURN void failed_throw(__cxa_exception* exception_header) {
Marshall Clow87694492011-08-09 15:09:41 +0000144// Section 2.5.3 says:
145// * For purposes of this ABI, several things are considered exception handlers:
146// ** A terminate() call due to a throw.
147// and
148// * Upon entry, Following initialization of the catch parameter,
149// a handler must call:
Marshall Clow9b454bc2011-08-15 18:06:47 +0000150// * void *__cxa_begin_catch(void *exceptionObject );
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000151 (void) __cxa_begin_catch(&exception_header->unwindHeader);
152 std::__terminate(exception_header->terminateHandler);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000153}
Marshall Clowe2dcb752011-07-20 15:04:39 +0000154
Akira Hatanaka9ef1daa2017-11-28 00:36:29 +0000155// Return the offset of the __cxa_exception header from the start of the
156// allocated buffer. If __cxa_exception's alignment is smaller than the maximum
157// useful alignment for the target machine, padding has to be inserted before
158// the header to ensure the thrown object that follows the header is
159// sufficiently aligned. This happens if _Unwind_exception isn't double-word
160// aligned (on Darwin, for example).
161static size_t get_cxa_exception_offset() {
162 struct S {
163 } __attribute__((aligned));
164
165 // Compute the maximum alignment for the target machine.
166 constexpr size_t alignment = std::alignment_of<S>::value;
167 constexpr size_t excp_size = sizeof(__cxa_exception);
168 constexpr size_t aligned_size =
169 (excp_size + alignment - 1) / alignment * alignment;
170 constexpr size_t offset = aligned_size - excp_size;
171 static_assert((offset == 0 ||
172 std::alignment_of<_Unwind_Exception>::value < alignment),
173 "offset is non-zero only if _Unwind_Exception isn't aligned");
174 return offset;
175}
176
Marshall Clowe2dcb752011-07-20 15:04:39 +0000177extern "C" {
178
179// Allocate a __cxa_exception object, and zero-fill it.
180// Reserve "thrown_size" bytes on the end for the user's exception
181// object. Zero-fill the object. If memory can't be allocated, call
182// std::terminate. Return a pointer to the memory to be used for the
183// user's exception object.
Shoaib Meenaife989a92017-03-01 03:55:57 +0000184void *__cxa_allocate_exception(size_t thrown_size) throw() {
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000185 size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size);
Akira Hatanaka9ef1daa2017-11-28 00:36:29 +0000186
187 // Allocate extra space before the __cxa_exception header to ensure the
188 // start of the thrown object is sufficiently aligned.
189 size_t header_offset = get_cxa_exception_offset();
190 char *raw_buffer =
191 (char *)__aligned_malloc_with_fallback(header_offset + actual_size);
192 if (NULL == raw_buffer)
Marshall Clow9b454bc2011-08-15 18:06:47 +0000193 std::terminate();
Akira Hatanaka9ef1daa2017-11-28 00:36:29 +0000194 __cxa_exception *exception_header =
195 static_cast<__cxa_exception *>((void *)(raw_buffer + header_offset));
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000196 std::memset(exception_header, 0, actual_size);
197 return thrown_object_from_cxa_exception(exception_header);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000198}
Marshall Clowe2dcb752011-07-20 15:04:39 +0000199
200
201// Free a __cxa_exception object allocated with __cxa_allocate_exception.
Shoaib Meenaife989a92017-03-01 03:55:57 +0000202void __cxa_free_exception(void *thrown_object) throw() {
Akira Hatanaka9ef1daa2017-11-28 00:36:29 +0000203 // Compute the size of the padding before the header.
204 size_t header_offset = get_cxa_exception_offset();
205 char *raw_buffer =
206 ((char *)cxa_exception_from_thrown_object(thrown_object)) - header_offset;
207 __aligned_free_with_fallback((void *)raw_buffer);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000208}
Marshall Clowe2dcb752011-07-20 15:04:39 +0000209
210
211// This function shall allocate a __cxa_dependent_exception and
212// return a pointer to it. (Really to the object, not past its' end).
213// Otherwise, it will work like __cxa_allocate_exception.
Howard Hinnant47cb85482012-01-30 16:07:00 +0000214void * __cxa_allocate_dependent_exception () {
Marshall Clow9b454bc2011-08-15 18:06:47 +0000215 size_t actual_size = sizeof(__cxa_dependent_exception);
Eric Fiselierc74a2e12017-03-04 02:04:45 +0000216 void *ptr = __aligned_malloc_with_fallback(actual_size);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000217 if (NULL == ptr)
218 std::terminate();
219 std::memset(ptr, 0, actual_size);
Marshall Clowe2dcb752011-07-20 15:04:39 +0000220 return ptr;
Marshall Clow9b454bc2011-08-15 18:06:47 +0000221}
Marshall Clowe2dcb752011-07-20 15:04:39 +0000222
223
224// This function shall free a dependent_exception.
225// It does not affect the reference count of the primary exception.
Howard Hinnant47cb85482012-01-30 16:07:00 +0000226void __cxa_free_dependent_exception (void * dependent_exception) {
Eric Fiselierc74a2e12017-03-04 02:04:45 +0000227 __aligned_free_with_fallback(dependent_exception);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000228}
Marshall Clowe2dcb752011-07-20 15:04:39 +0000229
Marshall Clow87694492011-08-09 15:09:41 +0000230
231// 2.4.3 Throwing the Exception Object
232/*
233After constructing the exception object with the throw argument value,
234the generated code calls the __cxa_throw runtime library routine. This
235routine never returns.
236
237The __cxa_throw routine will do the following:
238
239* Obtain the __cxa_exception header from the thrown exception object address,
240which can be computed as follows:
241 __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1);
242* Save the current unexpected_handler and terminate_handler in the __cxa_exception header.
243* Save the tinfo and dest arguments in the __cxa_exception header.
244* Set the exception_class field in the unwind header. This is a 64-bit value
245representing the ASCII string "XXXXC++\0", where "XXXX" is a
246vendor-dependent string. That is, for implementations conforming to this
247ABI, the low-order 4 bytes of this 64-bit value will be "C++\0".
248* Increment the uncaught_exception flag.
249* Call _Unwind_RaiseException in the system unwind library, Its argument is the
250pointer to the thrown exception, which __cxa_throw itself received as an argument.
251__Unwind_RaiseException begins the process of stack unwinding, described
252in Section 2.5. In special cases, such as an inability to find a
253handler, _Unwind_RaiseException may return. In that case, __cxa_throw
254will call terminate, assuming that there was no handler for the
255exception.
256*/
Shoaib Meenaife989a92017-03-01 03:55:57 +0000257void
Saleem Abdulrasool12315ed2015-12-04 02:14:58 +0000258__cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {
Marshall Clow9b454bc2011-08-15 18:06:47 +0000259 __cxa_eh_globals *globals = __cxa_get_globals();
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000260 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
Howard Hinnant6ccae152011-12-08 19:35:18 +0000261
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000262 exception_header->unexpectedHandler = std::get_unexpected();
263 exception_header->terminateHandler = std::get_terminate();
264 exception_header->exceptionType = tinfo;
265 exception_header->exceptionDestructor = dest;
Marshall Clow611a55a2018-10-10 16:18:37 +0000266 setOurExceptionClass(&exception_header->unwindHeader);
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000267 exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
Marshall Clow87694492011-08-09 15:09:41 +0000268 globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
269
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000270 exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;
Petr Hosek229e0852017-09-13 23:35:07 +0000271
Eric Fiselierc4600cc2017-09-14 22:37:34 +0000272#if __has_feature(address_sanitizer)
Petr Hosek229e0852017-09-13 23:35:07 +0000273 // Inform the ASan runtime that now might be a good time to clean stuff up.
274 __asan_handle_no_return();
275#endif
276
Dan Albert3bd13ca2015-02-05 01:33:15 +0000277#ifdef __USING_SJLJ_EXCEPTIONS__
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000278 _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
Howard Hinnant6ccae152011-12-08 19:35:18 +0000279#else
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000280 _Unwind_RaiseException(&exception_header->unwindHeader);
Howard Hinnant6ccae152011-12-08 19:35:18 +0000281#endif
Howard Hinnant9aa46842012-01-28 00:34:46 +0000282 // This only happens when there is no handler, or some unexpected unwinding
283 // error happens.
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000284 failed_throw(exception_header);
Marshall Clow9b454bc2011-08-15 18:06:47 +0000285}
Marshall Clow87694492011-08-09 15:09:41 +0000286
287
288// 2.5.3 Exception Handlers
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000289/*
290The adjusted pointer is computed by the personality routine during phase 1
291 and saved in the exception header (either __cxa_exception or
292 __cxa_dependent_exception).
Howard Hinnant47cb85482012-01-30 16:07:00 +0000293
294 Requires: exception is native
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000295*/
Saleem Abdulrasool242d67b2015-12-04 02:14:41 +0000296void *__cxa_get_exception_ptr(void *unwind_exception) throw() {
Ranjeet Singhef6e6722017-03-01 11:42:01 +0000297#if defined(_LIBCXXABI_ARM_EHABI)
Logan Chiendc65ab42014-05-10 00:42:10 +0000298 return reinterpret_cast<void*>(
Dan Albertb98c20c2015-02-05 23:48:06 +0000299 static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]);
Logan Chiendc65ab42014-05-10 00:42:10 +0000300#else
Dan Albertb98c20c2015-02-05 23:48:06 +0000301 return cxa_exception_from_exception_unwind_exception(
302 static_cast<_Unwind_Exception*>(unwind_exception))->adjustedPtr;
Logan Chiendc65ab42014-05-10 00:42:10 +0000303#endif
Marshall Clow9b454bc2011-08-15 18:06:47 +0000304}
Logan Chiendc65ab42014-05-10 00:42:10 +0000305
Ranjeet Singhef6e6722017-03-01 11:42:01 +0000306#if defined(_LIBCXXABI_ARM_EHABI)
Logan Chiendc65ab42014-05-10 00:42:10 +0000307/*
308The routine to be called before the cleanup. This will save __cxa_exception in
309__cxa_eh_globals, so that __cxa_end_cleanup() can recover later.
310*/
Saleem Abdulrasool242d67b2015-12-04 02:14:41 +0000311bool __cxa_begin_cleanup(void *unwind_arg) throw() {
Logan Chiendc65ab42014-05-10 00:42:10 +0000312 _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
313 __cxa_eh_globals* globals = __cxa_get_globals();
314 __cxa_exception* exception_header =
315 cxa_exception_from_exception_unwind_exception(unwind_exception);
316
Marshall Clow611a55a2018-10-10 16:18:37 +0000317 if (__isOurExceptionClass(unwind_exception))
Logan Chiendc65ab42014-05-10 00:42:10 +0000318 {
319 if (0 == exception_header->propagationCount)
320 {
321 exception_header->nextPropagatingException = globals->propagatingExceptions;
322 globals->propagatingExceptions = exception_header;
323 }
324 ++exception_header->propagationCount;
325 }
326 else
327 {
328 // If the propagatingExceptions stack is not empty, since we can't
329 // chain the foreign exception, terminate it.
330 if (NULL != globals->propagatingExceptions)
331 std::terminate();
332 globals->propagatingExceptions = exception_header;
333 }
334 return true;
335}
336
337/*
338The routine to be called after the cleanup has been performed. It will get the
339propagating __cxa_exception from __cxa_eh_globals, and continue the stack
340unwinding with _Unwind_Resume.
341
342According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any
343register, thus we have to write this function in assembly so that we can save
344{r1, r2, r3}. We don't have to save r0 because it is the return value and the
345first argument to _Unwind_Resume(). In addition, we are saving r4 in order to
346align the stack to 16 bytes, even though it is a callee-save register.
347*/
348__attribute__((used)) static _Unwind_Exception *
349__cxa_end_cleanup_impl()
350{
351 __cxa_eh_globals* globals = __cxa_get_globals();
352 __cxa_exception* exception_header = globals->propagatingExceptions;
353 if (NULL == exception_header)
354 {
355 // It seems that __cxa_begin_cleanup() is not called properly.
356 // We have no choice but terminate the program now.
357 std::terminate();
358 }
359
Marshall Clow611a55a2018-10-10 16:18:37 +0000360 if (__isOurExceptionClass(&exception_header->unwindHeader))
Logan Chiendc65ab42014-05-10 00:42:10 +0000361 {
362 --exception_header->propagationCount;
363 if (0 == exception_header->propagationCount)
364 {
365 globals->propagatingExceptions = exception_header->nextPropagatingException;
366 exception_header->nextPropagatingException = NULL;
367 }
368 }
369 else
370 {
371 globals->propagatingExceptions = NULL;
372 }
373 return &exception_header->unwindHeader;
374}
375
376asm (
Logan Chien338d6de2015-12-22 14:38:30 +0000377 " .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
Logan Chiendc65ab42014-05-10 00:42:10 +0000378 " .globl __cxa_end_cleanup\n"
379 " .type __cxa_end_cleanup,%function\n"
380 "__cxa_end_cleanup:\n"
381 " push {r1, r2, r3, r4}\n"
382 " bl __cxa_end_cleanup_impl\n"
383 " pop {r1, r2, r3, r4}\n"
384 " bl _Unwind_Resume\n"
385 " bl abort\n"
386 " .popsection"
387);
Ranjeet Singhef6e6722017-03-01 11:42:01 +0000388#endif // defined(_LIBCXXABI_ARM_EHABI)
Marshall Clow87694492011-08-09 15:09:41 +0000389
Marshall Clow87694492011-08-09 15:09:41 +0000390/*
Howard Hinnant47cb85482012-01-30 16:07:00 +0000391This routine can catch foreign or native exceptions. If native, the exception
392can be a primary or dependent variety. This routine may remain blissfully
393ignorant of whether the native exception is primary or dependent.
394
395If the exception is native:
Marshall Clow87694492011-08-09 15:09:41 +0000396* Increment's the exception's handler count.
Howard Hinnant47cb85482012-01-30 16:07:00 +0000397* Push the exception on the stack of currently-caught exceptions if it is not
398 already there (from a rethrow).
Marshall Clow87694492011-08-09 15:09:41 +0000399* Decrements the uncaught_exception count.
Howard Hinnant47cb85482012-01-30 16:07:00 +0000400* Returns the adjusted pointer to the exception object, which is stored in
401 the __cxa_exception by the personality routine.
402
403If the exception is foreign, this means it did not originate from one of throw
404routines. The foreign exception does not necessarily have a __cxa_exception
405header. However we can catch it here with a catch (...), or with a call
406to terminate or unexpected during unwinding.
407* Do not try to increment the exception's handler count, we don't know where
408 it is.
409* Push the exception on the stack of currently-caught exceptions only if the
410 stack is empty. The foreign exception has no way to link to the current
411 top of stack. If the stack is not empty, call terminate. Even with an
412 empty stack, this is hacked in by pushing a pointer to an imaginary
413 __cxa_exception block in front of the foreign exception. It would be better
414 if the __cxa_eh_globals structure had a stack of _Unwind_Exception, but it
415 doesn't. It has a stack of __cxa_exception (which has a next* in it).
416* Do not decrement the uncaught_exception count because we didn't increment it
417 in __cxa_throw (or one of our rethrow functions).
418* If we haven't terminated, assume the exception object is just past the
419 _Unwind_Exception and return a pointer to that.
Marshall Clow87694492011-08-09 15:09:41 +0000420*/
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000421void*
Howard Hinnant47cb85482012-01-30 16:07:00 +0000422__cxa_begin_catch(void* unwind_arg) throw()
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000423{
Howard Hinnant47cb85482012-01-30 16:07:00 +0000424 _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
Marshall Clow611a55a2018-10-10 16:18:37 +0000425 bool native_exception = __isOurExceptionClass(unwind_exception);
Howard Hinnant47cb85482012-01-30 16:07:00 +0000426 __cxa_eh_globals* globals = __cxa_get_globals();
427 // exception_header is a hackish offset from a foreign exception, but it
428 // works as long as we're careful not to try to access any __cxa_exception
429 // parts.
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000430 __cxa_exception* exception_header =
431 cxa_exception_from_exception_unwind_exception
432 (
433 static_cast<_Unwind_Exception*>(unwind_exception)
434 );
Howard Hinnant47cb85482012-01-30 16:07:00 +0000435 if (native_exception)
436 {
437 // Increment the handler count, removing the flag about being rethrown
438 exception_header->handlerCount = exception_header->handlerCount < 0 ?
439 -exception_header->handlerCount + 1 : exception_header->handlerCount + 1;
440 // place the exception on the top of the stack if it's not already
441 // there by a previous rethrow
442 if (exception_header != globals->caughtExceptions)
443 {
444 exception_header->nextException = globals->caughtExceptions;
445 globals->caughtExceptions = exception_header;
446 }
447 globals->uncaughtExceptions -= 1; // Not atomically, since globals are thread-local
Ranjeet Singhef6e6722017-03-01 11:42:01 +0000448#if defined(_LIBCXXABI_ARM_EHABI)
Logan Chiendc65ab42014-05-10 00:42:10 +0000449 return reinterpret_cast<void*>(exception_header->unwindHeader.barrier_cache.bitpattern[0]);
450#else
Howard Hinnant47cb85482012-01-30 16:07:00 +0000451 return exception_header->adjustedPtr;
Logan Chiendc65ab42014-05-10 00:42:10 +0000452#endif
Marshall Clow9b454bc2011-08-15 18:06:47 +0000453 }
Howard Hinnant47cb85482012-01-30 16:07:00 +0000454 // Else this is a foreign exception
455 // If the caughtExceptions stack is not empty, terminate
456 if (globals->caughtExceptions != 0)
457 std::terminate();
458 // Push the foreign exception on to the stack
459 globals->caughtExceptions = exception_header;
460 return unwind_exception + 1;
Marshall Clow9b454bc2011-08-15 18:06:47 +0000461}
Marshall Clow87694492011-08-09 15:09:41 +0000462
463
464/*
465Upon exit for any reason, a handler must call:
466 void __cxa_end_catch ();
467
Howard Hinnant47cb85482012-01-30 16:07:00 +0000468This routine can be called for either a native or foreign exception.
469For a native exception:
Marshall Clow87694492011-08-09 15:09:41 +0000470* Locates the most recently caught exception and decrements its handler count.
471* Removes the exception from the caught exception stack, if the handler count goes to zero.
Howard Hinnant6ccae152011-12-08 19:35:18 +0000472* If the handler count goes down to zero, and the exception was not re-thrown
473 by throw, it locates the primary exception (which may be the same as the one
474 it's handling) and decrements its reference count. If that reference count
475 goes to zero, the function destroys the exception. In any case, if the current
476 exception is a dependent exception, it destroys that.
Howard Hinnant47cb85482012-01-30 16:07:00 +0000477
478For a foreign exception:
479* If it has been rethrown, there is nothing to do.
480* Otherwise delete the exception and pop the catch stack to empty.
Marshall Clow87694492011-08-09 15:09:41 +0000481*/
Shoaib Meenaife989a92017-03-01 03:55:57 +0000482void __cxa_end_catch() {
Nico Weberae543872014-06-25 23:52:07 +0000483 static_assert(sizeof(__cxa_exception) == sizeof(__cxa_dependent_exception),
484 "sizeof(__cxa_exception) must be equal to "
485 "sizeof(__cxa_dependent_exception)");
Saleem Abdulrasoole113b5e2015-11-18 05:33:38 +0000486 static_assert(__builtin_offsetof(__cxa_exception, referenceCount) ==
487 __builtin_offsetof(__cxa_dependent_exception,
488 primaryException),
489 "the layout of __cxa_exception must match the layout of "
490 "__cxa_dependent_exception");
491 static_assert(__builtin_offsetof(__cxa_exception, handlerCount) ==
492 __builtin_offsetof(__cxa_dependent_exception, handlerCount),
493 "the layout of __cxa_exception must match the layout of "
494 "__cxa_dependent_exception");
Howard Hinnant47cb85482012-01-30 16:07:00 +0000495 __cxa_eh_globals* globals = __cxa_get_globals_fast(); // __cxa_get_globals called in __cxa_begin_catch
496 __cxa_exception* exception_header = globals->caughtExceptions;
497 // If we've rethrown a foreign exception, then globals->caughtExceptions
498 // will have been made an empty stack by __cxa_rethrow() and there is
499 // nothing more to be done. Do nothing!
500 if (NULL != exception_header)
501 {
Marshall Clow611a55a2018-10-10 16:18:37 +0000502 bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader);
Howard Hinnant47cb85482012-01-30 16:07:00 +0000503 if (native_exception)
504 {
505 // This is a native exception
506 if (exception_header->handlerCount < 0)
507 {
508 // The exception has been rethrown by __cxa_rethrow, so don't delete it
509 if (0 == incrementHandlerCount(exception_header))
510 {
511 // Remove from the chain of uncaught exceptions
512 globals->caughtExceptions = exception_header->nextException;
513 // but don't destroy
Howard Hinnant6ccae152011-12-08 19:35:18 +0000514 }
Howard Hinnant47cb85482012-01-30 16:07:00 +0000515 // Keep handlerCount negative in case there are nested catch's
516 // that need to be told that this exception is rethrown. Don't
517 // erase this rethrow flag until the exception is recaught.
518 }
519 else
520 {
521 // The native exception has not been rethrown
522 if (0 == decrementHandlerCount(exception_header))
523 {
524 // Remove from the chain of uncaught exceptions
525 globals->caughtExceptions = exception_header->nextException;
526 // Destroy this exception, being careful to distinguish
527 // between dependent and primary exceptions
528 if (isDependentException(&exception_header->unwindHeader))
529 {
530 // Reset exception_header to primaryException and deallocate the dependent exception
531 __cxa_dependent_exception* dep_exception_header =
532 reinterpret_cast<__cxa_dependent_exception*>(exception_header);
533 exception_header =
534 cxa_exception_from_thrown_object(dep_exception_header->primaryException);
535 __cxa_free_dependent_exception(dep_exception_header);
536 }
537 // Destroy the primary exception only if its referenceCount goes to 0
538 // (this decrement must be atomic)
539 __cxa_decrement_exception_refcount(thrown_object_from_cxa_exception(exception_header));
540 }
Marshall Clow9b454bc2011-08-15 18:06:47 +0000541 }
542 }
Howard Hinnant47cb85482012-01-30 16:07:00 +0000543 else
544 {
545 // The foreign exception has not been rethrown. Pop the stack
546 // and delete it. If there are nested catch's and they try
547 // to touch a foreign exception in any way, that is undefined
548 // behavior. They likely can't since the only way to catch
549 // a foreign exception is with catch (...)!
550 _Unwind_DeleteException(&globals->caughtExceptions->unwindHeader);
551 globals->caughtExceptions = 0;
552 }
Marshall Clow87694492011-08-09 15:09:41 +0000553 }
Marshall Clow9b454bc2011-08-15 18:06:47 +0000554}
Marshall Clow87694492011-08-09 15:09:41 +0000555
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000556// Note: exception_header may be masquerading as a __cxa_dependent_exception
557// and that's ok. exceptionType is there too.
Howard Hinnant47cb85482012-01-30 16:07:00 +0000558// However watch out for foreign exceptions. Return null for them.
Shoaib Meenaife989a92017-03-01 03:55:57 +0000559std::type_info *__cxa_current_exception_type() {
Marshall Clow87694492011-08-09 15:09:41 +0000560// get the current exception
Marshall Clow1de4fc02011-12-22 15:45:05 +0000561 __cxa_eh_globals *globals = __cxa_get_globals_fast();
562 if (NULL == globals)
563 return NULL; // If there have never been any exceptions, there are none now.
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000564 __cxa_exception *exception_header = globals->caughtExceptions;
565 if (NULL == exception_header)
Marshall Clow87694492011-08-09 15:09:41 +0000566 return NULL; // No current exception
Marshall Clow611a55a2018-10-10 16:18:37 +0000567 if (!__isOurExceptionClass(&exception_header->unwindHeader))
Howard Hinnant47cb85482012-01-30 16:07:00 +0000568 return NULL;
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000569 return exception_header->exceptionType;
Marshall Clow9b454bc2011-08-15 18:06:47 +0000570}
Marshall Clow87694492011-08-09 15:09:41 +0000571
572// 2.5.4 Rethrowing Exceptions
Howard Hinnant47cb85482012-01-30 16:07:00 +0000573/* This routine can rethrow native or foreign exceptions.
574If the exception is native:
Marshall Clow87694492011-08-09 15:09:41 +0000575* marks the exception object on top of the caughtExceptions stack
576 (in an implementation-defined way) as being rethrown.
577* If the caughtExceptions stack is empty, it calls terminate()
578 (see [C++FDIS] [except.throw], 15.1.8).
Howard Hinnant47cb85482012-01-30 16:07:00 +0000579* It then calls _Unwind_RaiseException which should not return
Howard Hinnant58926c92011-12-12 19:11:42 +0000580 (terminate if it does).
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000581 Note: exception_header may be masquerading as a __cxa_dependent_exception
582 and that's ok.
Marshall Clow87694492011-08-09 15:09:41 +0000583*/
Shoaib Meenaife989a92017-03-01 03:55:57 +0000584void __cxa_rethrow() {
Howard Hinnant47cb85482012-01-30 16:07:00 +0000585 __cxa_eh_globals* globals = __cxa_get_globals();
Howard Hinnant47cb85482012-01-30 16:07:00 +0000586 __cxa_exception* exception_header = globals->caughtExceptions;
587 if (NULL == exception_header)
588 std::terminate(); // throw; called outside of a exception handler
Marshall Clow611a55a2018-10-10 16:18:37 +0000589 bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader);
Howard Hinnant47cb85482012-01-30 16:07:00 +0000590 if (native_exception)
591 {
Howard Hinnant47cb85482012-01-30 16:07:00 +0000592 // Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch)
593 exception_header->handlerCount = -exception_header->handlerCount;
594 globals->uncaughtExceptions += 1;
595 // __cxa_end_catch will remove this exception from the caughtExceptions stack if necessary
596 }
597 else // this is a foreign exception
598 {
599 // The only way to communicate to __cxa_end_catch that we've rethrown
600 // a foreign exception, so don't delete us, is to pop the stack here
601 // which must be empty afterwards. Then __cxa_end_catch will do
602 // nothing
603 globals->caughtExceptions = 0;
604 }
Dan Albert3bd13ca2015-02-05 01:33:15 +0000605#ifdef __USING_SJLJ_EXCEPTIONS__
Howard Hinnant20d6c142012-02-29 22:14:19 +0000606 _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
Marshall Clow87694492011-08-09 15:09:41 +0000607#else
Howard Hinnant20d6c142012-02-29 22:14:19 +0000608 _Unwind_RaiseException(&exception_header->unwindHeader);
Marshall Clow87694492011-08-09 15:09:41 +0000609#endif
610
Howard Hinnant47cb85482012-01-30 16:07:00 +0000611 // If we get here, some kind of unwinding error has occurred.
612 // There is some weird code generation bug happening with
613 // Apple clang version 4.0 (tags/Apple/clang-418.0.2) (based on LLVM 3.1svn)
614 // If we call failed_throw here. Turns up with -O2 or higher, and -Os.
615 __cxa_begin_catch(&exception_header->unwindHeader);
616 if (native_exception)
617 std::__terminate(exception_header->terminateHandler);
618 // Foreign exception: can't get exception_header->terminateHandler
619 std::terminate();
Marshall Clow9b454bc2011-08-15 18:06:47 +0000620}
Marshall Clow87694492011-08-09 15:09:41 +0000621
Howard Hinnante04f5162011-12-21 23:32:11 +0000622/*
Howard Hinnant47cb85482012-01-30 16:07:00 +0000623 If thrown_object is not null, atomically increment the referenceCount field
624 of the __cxa_exception header associated with the thrown object referred to
625 by thrown_object.
626
627 Requires: If thrown_object is not NULL, it is a native exception.
Howard Hinnante04f5162011-12-21 23:32:11 +0000628*/
Shoaib Meenaife989a92017-03-01 03:55:57 +0000629void
Saleem Abdulrasool12315ed2015-12-04 02:14:58 +0000630__cxa_increment_exception_refcount(void *thrown_object) throw() {
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000631 if (thrown_object != NULL )
Howard Hinnante04f5162011-12-21 23:32:11 +0000632 {
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000633 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
Eli Friedman17a47b92018-04-16 22:00:14 +0000634 std::__libcpp_atomic_add(&exception_header->referenceCount, size_t(1));
Howard Hinnante04f5162011-12-21 23:32:11 +0000635 }
636}
637
638/*
Howard Hinnant47cb85482012-01-30 16:07:00 +0000639 If thrown_object is not null, atomically decrement the referenceCount field
640 of the __cxa_exception header associated with the thrown object referred to
641 by thrown_object. If the referenceCount drops to zero, destroy and
642 deallocate the exception.
643
644 Requires: If thrown_object is not NULL, it is a native exception.
Howard Hinnante04f5162011-12-21 23:32:11 +0000645*/
Vlad Tsyrklevichb89e9b52018-04-09 22:11:28 +0000646_LIBCXXABI_NO_CFI
647void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
Howard Hinnante04f5162011-12-21 23:32:11 +0000648 if (thrown_object != NULL )
649 {
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000650 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
Eli Friedman17a47b92018-04-16 22:00:14 +0000651 if (std::__libcpp_atomic_add(&exception_header->referenceCount, size_t(-1)) == 0)
Howard Hinnante04f5162011-12-21 23:32:11 +0000652 {
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000653 if (NULL != exception_header->exceptionDestructor)
654 exception_header->exceptionDestructor(thrown_object);
Howard Hinnante04f5162011-12-21 23:32:11 +0000655 __cxa_free_exception(thrown_object);
656 }
657 }
658}
659
660/*
661 Returns a pointer to the thrown object (if any) at the top of the
Howard Hinnantbe2eced2013-02-15 15:48:49 +0000662 caughtExceptions stack. Atomically increment the exception's referenceCount.
Howard Hinnant47cb85482012-01-30 16:07:00 +0000663 If there is no such thrown object or if the thrown object is foreign,
664 returns null.
Marshall Clowd2bab352012-01-04 22:18:10 +0000665
666 We can use __cxa_get_globals_fast here to get the globals because if there have
667 been no exceptions thrown, ever, on this thread, we can return NULL without
668 the need to allocate the exception-handling globals.
Howard Hinnante04f5162011-12-21 23:32:11 +0000669*/
Shoaib Meenaife989a92017-03-01 03:55:57 +0000670void *__cxa_current_primary_exception() throw() {
Howard Hinnante04f5162011-12-21 23:32:11 +0000671// get the current exception
Marshall Clowf83663a2012-01-03 23:26:09 +0000672 __cxa_eh_globals* globals = __cxa_get_globals_fast();
Marshall Clow3e417e72012-01-03 23:10:20 +0000673 if (NULL == globals)
Marshall Clowf3684862012-01-04 14:56:09 +0000674 return NULL; // If there are no globals, there is no exception
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000675 __cxa_exception* exception_header = globals->caughtExceptions;
676 if (NULL == exception_header)
Howard Hinnante04f5162011-12-21 23:32:11 +0000677 return NULL; // No current exception
Marshall Clow611a55a2018-10-10 16:18:37 +0000678 if (!__isOurExceptionClass(&exception_header->unwindHeader))
Howard Hinnant47cb85482012-01-30 16:07:00 +0000679 return NULL; // Can't capture a foreign exception (no way to refcount it)
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000680 if (isDependentException(&exception_header->unwindHeader)) {
681 __cxa_dependent_exception* dep_exception_header =
682 reinterpret_cast<__cxa_dependent_exception*>(exception_header);
683 exception_header = cxa_exception_from_thrown_object(dep_exception_header->primaryException);
Howard Hinnante04f5162011-12-21 23:32:11 +0000684 }
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000685 void* thrown_object = thrown_object_from_cxa_exception(exception_header);
Howard Hinnante04f5162011-12-21 23:32:11 +0000686 __cxa_increment_exception_refcount(thrown_object);
687 return thrown_object;
688}
689
690/*
691 If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
692 stored in exc is called. Otherwise the referenceCount stored in the
693 primary exception is decremented, destroying the primary if necessary.
694 Finally the dependent exception is destroyed.
695*/
696static
697void
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000698dependent_exception_cleanup(_Unwind_Reason_Code reason, _Unwind_Exception* unwind_exception)
Howard Hinnante04f5162011-12-21 23:32:11 +0000699{
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000700 __cxa_dependent_exception* dep_exception_header =
701 reinterpret_cast<__cxa_dependent_exception*>(unwind_exception + 1) - 1;
Howard Hinnante04f5162011-12-21 23:32:11 +0000702 if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000703 std::__terminate(dep_exception_header->terminateHandler);
704 __cxa_decrement_exception_refcount(dep_exception_header->primaryException);
705 __cxa_free_dependent_exception(dep_exception_header);
Howard Hinnante04f5162011-12-21 23:32:11 +0000706}
707
708/*
Howard Hinnantbe2eced2013-02-15 15:48:49 +0000709 If thrown_object is not null, allocate, initialize and throw a dependent
Howard Hinnante04f5162011-12-21 23:32:11 +0000710 exception.
711*/
712void
713__cxa_rethrow_primary_exception(void* thrown_object)
714{
715 if ( thrown_object != NULL )
716 {
Howard Hinnant47cb85482012-01-30 16:07:00 +0000717 // thrown_object guaranteed to be native because
718 // __cxa_current_primary_exception returns NULL for foreign exceptions
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000719 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
720 __cxa_dependent_exception* dep_exception_header =
721 static_cast<__cxa_dependent_exception*>(__cxa_allocate_dependent_exception());
722 dep_exception_header->primaryException = thrown_object;
Howard Hinnante04f5162011-12-21 23:32:11 +0000723 __cxa_increment_exception_refcount(thrown_object);
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000724 dep_exception_header->exceptionType = exception_header->exceptionType;
725 dep_exception_header->unexpectedHandler = std::get_unexpected();
726 dep_exception_header->terminateHandler = std::get_terminate();
727 setDependentExceptionClass(&dep_exception_header->unwindHeader);
Howard Hinnant22f28b22011-12-21 23:48:05 +0000728 __cxa_get_globals()->uncaughtExceptions += 1;
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000729 dep_exception_header->unwindHeader.exception_cleanup = dependent_exception_cleanup;
Dan Albert3bd13ca2015-02-05 01:33:15 +0000730#ifdef __USING_SJLJ_EXCEPTIONS__
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000731 _Unwind_SjLj_RaiseException(&dep_exception_header->unwindHeader);
Howard Hinnante04f5162011-12-21 23:32:11 +0000732#else
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000733 _Unwind_RaiseException(&dep_exception_header->unwindHeader);
Howard Hinnante04f5162011-12-21 23:32:11 +0000734#endif
735 // Some sort of unwinding error. Note that terminate is a handler.
Howard Hinnantafcf7ac2012-01-22 19:14:27 +0000736 __cxa_begin_catch(&dep_exception_header->unwindHeader);
Howard Hinnante04f5162011-12-21 23:32:11 +0000737 }
738 // If we return client will call terminate()
739}
740
Howard Hinnante33b2f52012-01-24 00:01:31 +0000741bool
Marshall Clow604de5c2015-06-02 13:03:17 +0000742__cxa_uncaught_exception() throw() { return __cxa_uncaught_exceptions() != 0; }
743
744unsigned int
745__cxa_uncaught_exceptions() throw()
Howard Hinnante33b2f52012-01-24 00:01:31 +0000746{
Howard Hinnant47cb85482012-01-30 16:07:00 +0000747 // This does not report foreign exceptions in flight
Howard Hinnante33b2f52012-01-24 00:01:31 +0000748 __cxa_eh_globals* globals = __cxa_get_globals_fast();
749 if (globals == 0)
Marshall Clow604de5c2015-06-02 13:03:17 +0000750 return 0;
751 return globals->uncaughtExceptions;
Howard Hinnante33b2f52012-01-24 00:01:31 +0000752}
753
Marshall Clowe2dcb752011-07-20 15:04:39 +0000754} // extern "C"
755
Marshall Clowe2dcb752011-07-20 15:04:39 +0000756} // abi