From c1e126a45fd8610347d428bea3dbf038a83002db Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Fri, 25 Nov 2011 12:31:23 +0000 Subject: And add support for nesting cleanups. --- src/cxxabi.h | 12 ++++++++++++ src/exception.cc | 28 +++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/cxxabi.h b/src/cxxabi.h index b081806..040d28d 100644 --- a/src/cxxabi.h +++ b/src/cxxabi.h @@ -87,6 +87,18 @@ struct __cxa_exception * handler count reaches 0 (which it doesn't with the top bit set). */ int handlerCount; +#ifdef __arm__ + /** + * The ARM EH ABI requires the unwind library to keep track of exceptions + * during cleanups. These support nesting, so we need to keep a list of + * them. + */ + _Unwind_Exception *nextCleanup; + /** + * The number of cleanups that are currently being run on this exception. + */ + int cleanupCount; +#endif /** * The selector value to be returned when installing the catch handler. * Used at the call site to determine which catch() block should execute. diff --git a/src/exception.cc b/src/exception.cc index 64e78a7..d53d997 100644 --- a/src/exception.cc +++ b/src/exception.cc @@ -143,6 +143,10 @@ struct __cxa_dependent_exception terminate_handler terminateHandler; __cxa_exception *nextException; int handlerCount; +#ifdef __arm__ + _Unwind_Exception *nextCleanup; + int cleanupCount; +#endif int handlerSwitchValue; const char *actionRecord; const char *languageSpecificData; @@ -942,6 +946,19 @@ static handler_type check_action_record(_Unwind_Context *context, return found; } +static void pushCleanupException(_Unwind_Exception *exceptionObject, + __cxa_exception *ex) +{ +#ifdef __arm__ + __cxa_thread_info *info = thread_info_fast(); + if (ex) + { + ex->nextCleanup = info->currentCleanup; + } + info->currentCleanup = exceptionObject; +#endif +} + /** * The exception personality function. This is referenced in the unwinding * DWARF metadata and is called by the unwind library for each C++ stack frame @@ -1045,8 +1062,7 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) action.action_record, realEx, &selector, ex->adjustedPtr); // Ignore handlers this time. if (found_handler != handler_cleanup) { return continueUnwinding(exceptionObject, context); } - __cxa_thread_info *info = thread_info_fast(); - info->currentCleanup = exceptionObject; + pushCleanupException(exceptionObject, ex); } else if (foreignException) { @@ -1366,7 +1382,13 @@ namespace std extern "C" _Unwind_Exception *__cxa_get_cleanup(void) { __cxa_thread_info *info = thread_info_fast(); - return info->currentCleanup; + _Unwind_Exception *exceptionObject = info->currentCleanup; + if (isCXXException(exceptionObject->exception_class)) + { + __cxa_exception *ex = exceptionFromPointer(exceptionObject); + info->currentCleanup = ex->nextCleanup; + } + return exceptionObject; } asm ( -- cgit v1.2.3