diff options
author | David Chisnall <dchisnall@pathscale.com> | 2011-11-25 12:31:23 +0000 |
---|---|---|
committer | David Chisnall <dchisnall@pathscale.com> | 2011-11-25 12:31:23 +0000 |
commit | c1e126a45fd8610347d428bea3dbf038a83002db (patch) | |
tree | c8e835977018dba7c0dbb82d5dfa608edc4954c2 /src | |
parent | c106344e1ff40b3dc46304a05f1518150b07aa53 (diff) | |
download | libcxxrt-c1e126a45fd8610347d428bea3dbf038a83002db.tar.gz libcxxrt-c1e126a45fd8610347d428bea3dbf038a83002db.tar.bz2 libcxxrt-c1e126a45fd8610347d428bea3dbf038a83002db.tar.xz |
And add support for nesting cleanups.
Diffstat (limited to 'src')
-rw-r--r-- | src/cxxabi.h | 12 | ||||
-rw-r--r-- | 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 ( |