diff options
author | Marshall Clow <mclow.lists@gmail.com> | 2018-10-10 16:18:37 +0000 |
---|---|---|
committer | Marshall Clow <mclow.lists@gmail.com> | 2018-10-10 16:18:37 +0000 |
commit | 611a55a084b44423f99e1009a71cdb0daf54312d (patch) | |
tree | b6076c0fc2626622c20df14da7c56f4ae2d463dd /libcxxabi | |
parent | f33b60258e412d80f6d9832feb1d32c8af1bcb3a (diff) |
Make libc++abi work better with gcc's ARM unwind library. Reviewed as https://reviews.llvm.org/D42242
llvm-svn: 344152
Diffstat (limited to 'libcxxabi')
-rw-r--r-- | libcxxabi/src/cxa_default_handlers.cpp | 7 | ||||
-rw-r--r-- | libcxxabi/src/cxa_exception.cpp | 45 | ||||
-rw-r--r-- | libcxxabi/src/cxa_exception.hpp | 4 | ||||
-rw-r--r-- | libcxxabi/src/cxa_handlers.cpp | 5 | ||||
-rw-r--r-- | libcxxabi/src/cxa_personality.cpp | 15 |
5 files changed, 42 insertions, 34 deletions
diff --git a/libcxxabi/src/cxa_default_handlers.cpp b/libcxxabi/src/cxa_default_handlers.cpp index 0fa169f06405..f00e95929b94 100644 --- a/libcxxabi/src/cxa_default_handlers.cpp +++ b/libcxxabi/src/cxa_default_handlers.cpp @@ -37,13 +37,10 @@ static void demangling_terminate_handler() { _Unwind_Exception* unwind_exception = reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; - bool native_exception = - (unwind_exception->exception_class & get_vendor_and_language) == - (kOurExceptionClass & get_vendor_and_language); - if (native_exception) + if (__isOurExceptionClass(unwind_exception)) { void* thrown_object = - unwind_exception->exception_class == kOurDependentExceptionClass ? + __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ? ((__cxa_dependent_exception*)exception_header)->primaryException : exception_header + 1; const __shim_type_info* thrown_type = diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp index 397427a02996..8d30e5ce429a 100644 --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -79,22 +79,37 @@ size_t cxa_exception_size_from_exception_thrown_size(size_t size) { alignof(__cxa_exception)); } -static void setExceptionClass(_Unwind_Exception* unwind_exception) { - unwind_exception->exception_class = kOurExceptionClass; +void __setExceptionClass(_Unwind_Exception* unwind_exception, uint64_t newValue) { + ::memcpy(&unwind_exception->exception_class, &newValue, sizeof(newValue)); + } + + +static void setOurExceptionClass(_Unwind_Exception* unwind_exception) { + __setExceptionClass(unwind_exception, kOurExceptionClass); } static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) { - unwind_exception->exception_class = kOurDependentExceptionClass; + __setExceptionClass(unwind_exception, kOurDependentExceptionClass); } // Is it one of ours? -static bool isOurExceptionClass(const _Unwind_Exception* unwind_exception) { - return (unwind_exception->exception_class & get_vendor_and_language) == - (kOurExceptionClass & get_vendor_and_language); +uint64_t __getExceptionClass(const _Unwind_Exception* unwind_exception) { +// On x86 and some ARM unwinders, unwind_exception->exception_class is +// a uint64_t. On other ARM unwinders, it is a char[8] +// See: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf +// So we just copy it into a uint64_t to be sure. + uint64_t exClass; + ::memcpy(&exClass, &unwind_exception->exception_class, sizeof(exClass)); + return exClass; +} + +bool __isOurExceptionClass(const _Unwind_Exception* unwind_exception) { + return (__getExceptionClass(unwind_exception) & get_vendor_and_language) == + (kOurExceptionClass & get_vendor_and_language); } static bool isDependentException(_Unwind_Exception* unwind_exception) { - return (unwind_exception->exception_class & 0xFF) == 0x01; + return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01; } // This does not need to be atomic @@ -249,7 +264,7 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) { exception_header->terminateHandler = std::get_terminate(); exception_header->exceptionType = tinfo; exception_header->exceptionDestructor = dest; - setExceptionClass(&exception_header->unwindHeader); + setOurExceptionClass(&exception_header->unwindHeader); exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety. globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local @@ -300,7 +315,7 @@ bool __cxa_begin_cleanup(void *unwind_arg) throw() { __cxa_exception* exception_header = cxa_exception_from_exception_unwind_exception(unwind_exception); - if (isOurExceptionClass(unwind_exception)) + if (__isOurExceptionClass(unwind_exception)) { if (0 == exception_header->propagationCount) { @@ -343,7 +358,7 @@ __cxa_end_cleanup_impl() std::terminate(); } - if (isOurExceptionClass(&exception_header->unwindHeader)) + if (__isOurExceptionClass(&exception_header->unwindHeader)) { --exception_header->propagationCount; if (0 == exception_header->propagationCount) @@ -408,7 +423,7 @@ void* __cxa_begin_catch(void* unwind_arg) throw() { _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg); - bool native_exception = isOurExceptionClass(unwind_exception); + bool native_exception = __isOurExceptionClass(unwind_exception); __cxa_eh_globals* globals = __cxa_get_globals(); // exception_header is a hackish offset from a foreign exception, but it // works as long as we're careful not to try to access any __cxa_exception @@ -485,7 +500,7 @@ void __cxa_end_catch() { // nothing more to be done. Do nothing! if (NULL != exception_header) { - bool native_exception = isOurExceptionClass(&exception_header->unwindHeader); + bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader); if (native_exception) { // This is a native exception @@ -550,7 +565,7 @@ std::type_info *__cxa_current_exception_type() { __cxa_exception *exception_header = globals->caughtExceptions; if (NULL == exception_header) return NULL; // No current exception - if (!isOurExceptionClass(&exception_header->unwindHeader)) + if (!__isOurExceptionClass(&exception_header->unwindHeader)) return NULL; return exception_header->exceptionType; } @@ -572,7 +587,7 @@ void __cxa_rethrow() { __cxa_exception* exception_header = globals->caughtExceptions; if (NULL == exception_header) std::terminate(); // throw; called outside of a exception handler - bool native_exception = isOurExceptionClass(&exception_header->unwindHeader); + bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader); if (native_exception) { // Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch) @@ -661,7 +676,7 @@ void *__cxa_current_primary_exception() throw() { __cxa_exception* exception_header = globals->caughtExceptions; if (NULL == exception_header) return NULL; // No current exception - if (!isOurExceptionClass(&exception_header->unwindHeader)) + if (!__isOurExceptionClass(&exception_header->unwindHeader)) return NULL; // Can't capture a foreign exception (no way to refcount it) if (isDependentException(&exception_header->unwindHeader)) { __cxa_dependent_exception* dep_exception_header = diff --git a/libcxxabi/src/cxa_exception.hpp b/libcxxabi/src/cxa_exception.hpp index c8b0fb1678ef..6d98e11a6238 100644 --- a/libcxxabi/src/cxa_exception.hpp +++ b/libcxxabi/src/cxa_exception.hpp @@ -24,6 +24,10 @@ static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1 static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++ +uint64_t __getExceptionClass (const _Unwind_Exception*); +void __setExceptionClass ( _Unwind_Exception*, uint64_t); +bool __isOurExceptionClass(const _Unwind_Exception*); + struct _LIBCXXABI_HIDDEN __cxa_exception { #if defined(__LP64__) || defined(_LIBCXXABI_ARM_EHABI) // This is a new field to support C++ 0x exception_ptr. diff --git a/libcxxabi/src/cxa_handlers.cpp b/libcxxabi/src/cxa_handlers.cpp index 622e93c354e6..8c26bd0b1a6b 100644 --- a/libcxxabi/src/cxa_handlers.cpp +++ b/libcxxabi/src/cxa_handlers.cpp @@ -84,10 +84,7 @@ terminate() _NOEXCEPT { _Unwind_Exception* unwind_exception = reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; - bool native_exception = - (unwind_exception->exception_class & get_vendor_and_language) == - (kOurExceptionClass & get_vendor_and_language); - if (native_exception) + if (__isOurExceptionClass(unwind_exception)) __terminate(exception_header->terminateHandler); } } diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp index ec3d98186dea..468461df54a3 100644 --- a/libcxxabi/src/cxa_personality.cpp +++ b/libcxxabi/src/cxa_personality.cpp @@ -502,7 +502,7 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception) // Even for foreign exceptions, the exception object is *probably* at unwind_exception + 1 // Regardless, this library is prohibited from touching a foreign exception void* adjustedPtr = unwind_exception + 1; - if (unwind_exception->exception_class == kOurDependentExceptionClass) + if (__getExceptionClass(unwind_exception) == kOurDependentExceptionClass) adjustedPtr = ((__cxa_dependent_exception*)adjustedPtr - 1)->primaryException; return adjustedPtr; } @@ -1098,8 +1098,7 @@ __gxx_personality_v0(_Unwind_State state, if (unwind_exception == 0 || context == 0) return _URC_FATAL_PHASE1_ERROR; - bool native_exception = (unwind_exception->exception_class & get_vendor_and_language) == - (kOurExceptionClass & get_vendor_and_language); + bool native_exception = __isOurExceptionClass(unwind_exception); #if !defined(LIBCXXABI_USE_LLVM_UNWINDER) // Copy the address of _Unwind_Control_Block to r12 so that @@ -1203,9 +1202,7 @@ __cxa_call_unexpected(void* arg) if (unwind_exception == 0) call_terminate(false, unwind_exception); __cxa_begin_catch(unwind_exception); - bool native_old_exception = - (unwind_exception->exception_class & get_vendor_and_language) == - (kOurExceptionClass & get_vendor_and_language); + bool native_old_exception = __isOurExceptionClass(unwind_exception); std::unexpected_handler u_handler; std::terminate_handler t_handler; __cxa_exception* old_exception_header = 0; @@ -1267,16 +1264,14 @@ __cxa_call_unexpected(void* arg) if (new_exception_header == 0) // This shouldn't be able to happen! std::__terminate(t_handler); - bool native_new_exception = - (new_exception_header->unwindHeader.exception_class & get_vendor_and_language) == - (kOurExceptionClass & get_vendor_and_language); + bool native_new_exception = __isOurExceptionClass(&new_exception_header->unwindHeader); void* adjustedPtr; if (native_new_exception && (new_exception_header != old_exception_header)) { const __shim_type_info* excpType = static_cast<const __shim_type_info*>(new_exception_header->exceptionType); adjustedPtr = - new_exception_header->unwindHeader.exception_class == kOurDependentExceptionClass ? + __getExceptionClass(&new_exception_header->unwindHeader) == kOurDependentExceptionClass ? ((__cxa_dependent_exception*)new_exception_header)->primaryException : new_exception_header + 1; if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, |