aboutsummaryrefslogtreecommitdiff
path: root/libcxxabi
diff options
context:
space:
mode:
authorMarshall Clow <mclow.lists@gmail.com>2018-10-10 16:18:37 +0000
committerMarshall Clow <mclow.lists@gmail.com>2018-10-10 16:18:37 +0000
commit611a55a084b44423f99e1009a71cdb0daf54312d (patch)
treeb6076c0fc2626622c20df14da7c56f4ae2d463dd /libcxxabi
parentf33b60258e412d80f6d9832feb1d32c8af1bcb3a (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.cpp7
-rw-r--r--libcxxabi/src/cxa_exception.cpp45
-rw-r--r--libcxxabi/src/cxa_exception.hpp4
-rw-r--r--libcxxabi/src/cxa_handlers.cpp5
-rw-r--r--libcxxabi/src/cxa_personality.cpp15
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,