summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Chisnall <dchisnall@pathscale.com>2011-11-25 12:31:23 +0000
committerDavid Chisnall <dchisnall@pathscale.com>2011-11-25 12:31:23 +0000
commitc1e126a45fd8610347d428bea3dbf038a83002db (patch)
treec8e835977018dba7c0dbb82d5dfa608edc4954c2 /src
parentc106344e1ff40b3dc46304a05f1518150b07aa53 (diff)
downloadlibcxxrt-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.h12
-rw-r--r--src/exception.cc28
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 (