diff options
author | Logan Chien <tzuhsiang.chien@gmail.com> | 2014-05-10 00:42:10 +0000 |
---|---|---|
committer | Logan Chien <tzuhsiang.chien@gmail.com> | 2014-05-10 00:42:10 +0000 |
commit | 05d51bcf07d0ec1c40785b4a860fd917410b4be1 (patch) | |
tree | e77dc951692207dd7ac73c1ea60a2599b906ab8b /src/cxa_exception.cpp | |
parent | 4856a67b510b2c50b5d2f1e3afa204ae22dca554 (diff) |
Implement ARM EHABI exception handling.
This commit implements the ARM zero-cost exception handling
support for libc++abi.
git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@208466 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'src/cxa_exception.cpp')
-rw-r--r-- | src/cxa_exception.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/cxa_exception.cpp b/src/cxa_exception.cpp index 9bc6ad6..13c060c 100644 --- a/src/cxa_exception.cpp +++ b/src/cxa_exception.cpp @@ -256,11 +256,102 @@ The adjusted pointer is computed by the personality routine during phase 1 void* __cxa_get_exception_ptr(void* unwind_exception) throw() { +#if LIBCXXABI_ARM_EHABI + return reinterpret_cast<void*>( + static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]); +#else return cxa_exception_from_exception_unwind_exception ( static_cast<_Unwind_Exception*>(unwind_exception) )->adjustedPtr; +#endif +} + +#if LIBCXXABI_ARM_EHABI +/* +The routine to be called before the cleanup. This will save __cxa_exception in +__cxa_eh_globals, so that __cxa_end_cleanup() can recover later. +*/ +bool +__cxa_begin_cleanup(void* unwind_arg) throw () +{ + _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg); + __cxa_eh_globals* globals = __cxa_get_globals(); + __cxa_exception* exception_header = + cxa_exception_from_exception_unwind_exception(unwind_exception); + + if (isOurExceptionClass(unwind_exception)) + { + if (0 == exception_header->propagationCount) + { + exception_header->nextPropagatingException = globals->propagatingExceptions; + globals->propagatingExceptions = exception_header; + } + ++exception_header->propagationCount; + } + else + { + // If the propagatingExceptions stack is not empty, since we can't + // chain the foreign exception, terminate it. + if (NULL != globals->propagatingExceptions) + std::terminate(); + globals->propagatingExceptions = exception_header; + } + return true; +} + +/* +The routine to be called after the cleanup has been performed. It will get the +propagating __cxa_exception from __cxa_eh_globals, and continue the stack +unwinding with _Unwind_Resume. + +According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any +register, thus we have to write this function in assembly so that we can save +{r1, r2, r3}. We don't have to save r0 because it is the return value and the +first argument to _Unwind_Resume(). In addition, we are saving r4 in order to +align the stack to 16 bytes, even though it is a callee-save register. +*/ +__attribute__((used)) static _Unwind_Exception * +__cxa_end_cleanup_impl() +{ + __cxa_eh_globals* globals = __cxa_get_globals(); + __cxa_exception* exception_header = globals->propagatingExceptions; + if (NULL == exception_header) + { + // It seems that __cxa_begin_cleanup() is not called properly. + // We have no choice but terminate the program now. + std::terminate(); + } + + if (isOurExceptionClass(&exception_header->unwindHeader)) + { + --exception_header->propagationCount; + if (0 == exception_header->propagationCount) + { + globals->propagatingExceptions = exception_header->nextPropagatingException; + exception_header->nextPropagatingException = NULL; + } + } + else + { + globals->propagatingExceptions = NULL; + } + return &exception_header->unwindHeader; } + +asm ( + " .pushsection .text.__cxa_end_cleanup\n" + " .globl __cxa_end_cleanup\n" + " .type __cxa_end_cleanup,%function\n" + "__cxa_end_cleanup:\n" + " push {r1, r2, r3, r4}\n" + " bl __cxa_end_cleanup_impl\n" + " pop {r1, r2, r3, r4}\n" + " bl _Unwind_Resume\n" + " bl abort\n" + " .popsection" +); +#endif // LIBCXXABI_ARM_EHABI /* This routine can catch foreign or native exceptions. If native, the exception @@ -320,7 +411,11 @@ __cxa_begin_catch(void* unwind_arg) throw() globals->caughtExceptions = exception_header; } globals->uncaughtExceptions -= 1; // Not atomically, since globals are thread-local +#if LIBCXXABI_ARM_EHABI + return reinterpret_cast<void*>(exception_header->unwindHeader.barrier_cache.bitpattern[0]); +#else return exception_header->adjustedPtr; +#endif } // Else this is a foreign exception // If the caughtExceptions stack is not empty, terminate |