Skip to content

Commit 611a55a

Browse files
committed
Make libc++abi work better with gcc's ARM unwind library. Reviewed as https://reviews.llvm.org/D42242
llvm-svn: 344152
1 parent f33b602 commit 611a55a

5 files changed

+42
-34
lines changed

libcxxabi/src/cxa_default_handlers.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,10 @@ static void demangling_terminate_handler()
3737
{
3838
_Unwind_Exception* unwind_exception =
3939
reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
40-
bool native_exception =
41-
(unwind_exception->exception_class & get_vendor_and_language) ==
42-
(kOurExceptionClass & get_vendor_and_language);
43-
if (native_exception)
40+
if (__isOurExceptionClass(unwind_exception))
4441
{
4542
void* thrown_object =
46-
unwind_exception->exception_class == kOurDependentExceptionClass ?
43+
__getExceptionClass(unwind_exception) == kOurDependentExceptionClass ?
4744
((__cxa_dependent_exception*)exception_header)->primaryException :
4845
exception_header + 1;
4946
const __shim_type_info* thrown_type =

libcxxabi/src/cxa_exception.cpp

+30-15
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,37 @@ size_t cxa_exception_size_from_exception_thrown_size(size_t size) {
7979
alignof(__cxa_exception));
8080
}
8181

82-
static void setExceptionClass(_Unwind_Exception* unwind_exception) {
83-
unwind_exception->exception_class = kOurExceptionClass;
82+
void __setExceptionClass(_Unwind_Exception* unwind_exception, uint64_t newValue) {
83+
::memcpy(&unwind_exception->exception_class, &newValue, sizeof(newValue));
84+
}
85+
86+
87+
static void setOurExceptionClass(_Unwind_Exception* unwind_exception) {
88+
__setExceptionClass(unwind_exception, kOurExceptionClass);
8489
}
8590

8691
static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) {
87-
unwind_exception->exception_class = kOurDependentExceptionClass;
92+
__setExceptionClass(unwind_exception, kOurDependentExceptionClass);
8893
}
8994

9095
// Is it one of ours?
91-
static bool isOurExceptionClass(const _Unwind_Exception* unwind_exception) {
92-
return (unwind_exception->exception_class & get_vendor_and_language) ==
93-
(kOurExceptionClass & get_vendor_and_language);
96+
uint64_t __getExceptionClass(const _Unwind_Exception* unwind_exception) {
97+
// On x86 and some ARM unwinders, unwind_exception->exception_class is
98+
// a uint64_t. On other ARM unwinders, it is a char[8]
99+
// See: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
100+
// So we just copy it into a uint64_t to be sure.
101+
uint64_t exClass;
102+
::memcpy(&exClass, &unwind_exception->exception_class, sizeof(exClass));
103+
return exClass;
104+
}
105+
106+
bool __isOurExceptionClass(const _Unwind_Exception* unwind_exception) {
107+
return (__getExceptionClass(unwind_exception) & get_vendor_and_language) ==
108+
(kOurExceptionClass & get_vendor_and_language);
94109
}
95110

96111
static bool isDependentException(_Unwind_Exception* unwind_exception) {
97-
return (unwind_exception->exception_class & 0xFF) == 0x01;
112+
return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01;
98113
}
99114

100115
// This does not need to be atomic
@@ -249,7 +264,7 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {
249264
exception_header->terminateHandler = std::get_terminate();
250265
exception_header->exceptionType = tinfo;
251266
exception_header->exceptionDestructor = dest;
252-
setExceptionClass(&exception_header->unwindHeader);
267+
setOurExceptionClass(&exception_header->unwindHeader);
253268
exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
254269
globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
255270

@@ -300,7 +315,7 @@ bool __cxa_begin_cleanup(void *unwind_arg) throw() {
300315
__cxa_exception* exception_header =
301316
cxa_exception_from_exception_unwind_exception(unwind_exception);
302317

303-
if (isOurExceptionClass(unwind_exception))
318+
if (__isOurExceptionClass(unwind_exception))
304319
{
305320
if (0 == exception_header->propagationCount)
306321
{
@@ -343,7 +358,7 @@ __cxa_end_cleanup_impl()
343358
std::terminate();
344359
}
345360

346-
if (isOurExceptionClass(&exception_header->unwindHeader))
361+
if (__isOurExceptionClass(&exception_header->unwindHeader))
347362
{
348363
--exception_header->propagationCount;
349364
if (0 == exception_header->propagationCount)
@@ -408,7 +423,7 @@ void*
408423
__cxa_begin_catch(void* unwind_arg) throw()
409424
{
410425
_Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg);
411-
bool native_exception = isOurExceptionClass(unwind_exception);
426+
bool native_exception = __isOurExceptionClass(unwind_exception);
412427
__cxa_eh_globals* globals = __cxa_get_globals();
413428
// exception_header is a hackish offset from a foreign exception, but it
414429
// works as long as we're careful not to try to access any __cxa_exception
@@ -485,7 +500,7 @@ void __cxa_end_catch() {
485500
// nothing more to be done. Do nothing!
486501
if (NULL != exception_header)
487502
{
488-
bool native_exception = isOurExceptionClass(&exception_header->unwindHeader);
503+
bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader);
489504
if (native_exception)
490505
{
491506
// This is a native exception
@@ -550,7 +565,7 @@ std::type_info *__cxa_current_exception_type() {
550565
__cxa_exception *exception_header = globals->caughtExceptions;
551566
if (NULL == exception_header)
552567
return NULL; // No current exception
553-
if (!isOurExceptionClass(&exception_header->unwindHeader))
568+
if (!__isOurExceptionClass(&exception_header->unwindHeader))
554569
return NULL;
555570
return exception_header->exceptionType;
556571
}
@@ -572,7 +587,7 @@ void __cxa_rethrow() {
572587
__cxa_exception* exception_header = globals->caughtExceptions;
573588
if (NULL == exception_header)
574589
std::terminate(); // throw; called outside of a exception handler
575-
bool native_exception = isOurExceptionClass(&exception_header->unwindHeader);
590+
bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader);
576591
if (native_exception)
577592
{
578593
// Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch)
@@ -661,7 +676,7 @@ void *__cxa_current_primary_exception() throw() {
661676
__cxa_exception* exception_header = globals->caughtExceptions;
662677
if (NULL == exception_header)
663678
return NULL; // No current exception
664-
if (!isOurExceptionClass(&exception_header->unwindHeader))
679+
if (!__isOurExceptionClass(&exception_header->unwindHeader))
665680
return NULL; // Can't capture a foreign exception (no way to refcount it)
666681
if (isDependentException(&exception_header->unwindHeader)) {
667682
__cxa_dependent_exception* dep_exception_header =

libcxxabi/src/cxa_exception.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC
2424
static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
2525
static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++
2626

27+
uint64_t __getExceptionClass (const _Unwind_Exception*);
28+
void __setExceptionClass ( _Unwind_Exception*, uint64_t);
29+
bool __isOurExceptionClass(const _Unwind_Exception*);
30+
2731
struct _LIBCXXABI_HIDDEN __cxa_exception {
2832
#if defined(__LP64__) || defined(_LIBCXXABI_ARM_EHABI)
2933
// This is a new field to support C++ 0x exception_ptr.

libcxxabi/src/cxa_handlers.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,7 @@ terminate() _NOEXCEPT
8484
{
8585
_Unwind_Exception* unwind_exception =
8686
reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
87-
bool native_exception =
88-
(unwind_exception->exception_class & get_vendor_and_language) ==
89-
(kOurExceptionClass & get_vendor_and_language);
90-
if (native_exception)
87+
if (__isOurExceptionClass(unwind_exception))
9188
__terminate(exception_header->terminateHandler);
9289
}
9390
}

libcxxabi/src/cxa_personality.cpp

+5-10
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
502502
// Even for foreign exceptions, the exception object is *probably* at unwind_exception + 1
503503
// Regardless, this library is prohibited from touching a foreign exception
504504
void* adjustedPtr = unwind_exception + 1;
505-
if (unwind_exception->exception_class == kOurDependentExceptionClass)
505+
if (__getExceptionClass(unwind_exception) == kOurDependentExceptionClass)
506506
adjustedPtr = ((__cxa_dependent_exception*)adjustedPtr - 1)->primaryException;
507507
return adjustedPtr;
508508
}
@@ -1098,8 +1098,7 @@ __gxx_personality_v0(_Unwind_State state,
10981098
if (unwind_exception == 0 || context == 0)
10991099
return _URC_FATAL_PHASE1_ERROR;
11001100

1101-
bool native_exception = (unwind_exception->exception_class & get_vendor_and_language) ==
1102-
(kOurExceptionClass & get_vendor_and_language);
1101+
bool native_exception = __isOurExceptionClass(unwind_exception);
11031102

11041103
#if !defined(LIBCXXABI_USE_LLVM_UNWINDER)
11051104
// Copy the address of _Unwind_Control_Block to r12 so that
@@ -1203,9 +1202,7 @@ __cxa_call_unexpected(void* arg)
12031202
if (unwind_exception == 0)
12041203
call_terminate(false, unwind_exception);
12051204
__cxa_begin_catch(unwind_exception);
1206-
bool native_old_exception =
1207-
(unwind_exception->exception_class & get_vendor_and_language) ==
1208-
(kOurExceptionClass & get_vendor_and_language);
1205+
bool native_old_exception = __isOurExceptionClass(unwind_exception);
12091206
std::unexpected_handler u_handler;
12101207
std::terminate_handler t_handler;
12111208
__cxa_exception* old_exception_header = 0;
@@ -1267,16 +1264,14 @@ __cxa_call_unexpected(void* arg)
12671264
if (new_exception_header == 0)
12681265
// This shouldn't be able to happen!
12691266
std::__terminate(t_handler);
1270-
bool native_new_exception =
1271-
(new_exception_header->unwindHeader.exception_class & get_vendor_and_language) ==
1272-
(kOurExceptionClass & get_vendor_and_language);
1267+
bool native_new_exception = __isOurExceptionClass(&new_exception_header->unwindHeader);
12731268
void* adjustedPtr;
12741269
if (native_new_exception && (new_exception_header != old_exception_header))
12751270
{
12761271
const __shim_type_info* excpType =
12771272
static_cast<const __shim_type_info*>(new_exception_header->exceptionType);
12781273
adjustedPtr =
1279-
new_exception_header->unwindHeader.exception_class == kOurDependentExceptionClass ?
1274+
__getExceptionClass(&new_exception_header->unwindHeader) == kOurDependentExceptionClass ?
12801275
((__cxa_dependent_exception*)new_exception_header)->primaryException :
12811276
new_exception_header + 1;
12821277
if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,

0 commit comments

Comments
 (0)