Lines 79-100
size_t cxa_exception_size_from_exception_thrown_size(size_t size) {
Link Here
|
79 |
alignof(__cxa_exception)); |
79 |
alignof(__cxa_exception)); |
80 |
} |
80 |
} |
81 |
|
81 |
|
82 |
static void setExceptionClass(_Unwind_Exception* unwind_exception) { |
82 |
void __setExceptionClass(_Unwind_Exception* unwind_exception, uint64_t newValue) { |
83 |
unwind_exception->exception_class = kOurExceptionClass; |
83 |
::memcpy(&unwind_exception->exception_class, &newValue, sizeof(newValue)); |
|
|
84 |
} |
85 |
|
86 |
static void setOurExceptionClass(_Unwind_Exception* unwind_exception) { |
87 |
__setExceptionClass(unwind_exception, kOurExceptionClass); |
84 |
} |
88 |
} |
85 |
|
89 |
|
86 |
static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) { |
90 |
static void setDependentExceptionClass(_Unwind_Exception* unwind_exception) { |
87 |
unwind_exception->exception_class = kOurDependentExceptionClass; |
91 |
__setExceptionClass(unwind_exception, kOurDependentExceptionClass); |
88 |
} |
92 |
} |
89 |
|
93 |
|
90 |
// Is it one of ours? |
94 |
// Is it one of ours? |
91 |
static bool isOurExceptionClass(const _Unwind_Exception* unwind_exception) { |
95 |
uint64_t __getExceptionClass(const _Unwind_Exception* unwind_exception) { |
92 |
return (unwind_exception->exception_class & get_vendor_and_language) == |
96 |
// On x86 and some ARM unwinders, unwind_exception->exception_class is |
93 |
(kOurExceptionClass & get_vendor_and_language); |
97 |
// a uint64_t. On other ARM unwinders, it is a char[8] |
|
|
98 |
// See: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf |
99 |
// So we just copy it into a uint64_t to be sure. |
100 |
uint64_t exClass; |
101 |
::memcpy(&exClass, &unwind_exception->exception_class, sizeof(exClass)); |
102 |
return exClass; |
103 |
} |
104 |
|
105 |
bool __isOurExceptionClass(const _Unwind_Exception* unwind_exception) { |
106 |
return (__getExceptionClass(unwind_exception) & get_vendor_and_language) == |
107 |
(kOurExceptionClass & get_vendor_and_language); |
94 |
} |
108 |
} |
95 |
|
109 |
|
96 |
static bool isDependentException(_Unwind_Exception* unwind_exception) { |
110 |
static bool isDependentException(_Unwind_Exception* unwind_exception) { |
97 |
return (unwind_exception->exception_class & 0xFF) == 0x01; |
111 |
return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01; |
98 |
} |
112 |
} |
99 |
|
113 |
|
100 |
// This does not need to be atomic |
114 |
// This does not need to be atomic |
Lines 249-255
__cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) {
Link Here
|
249 |
exception_header->terminateHandler = std::get_terminate(); |
263 |
exception_header->terminateHandler = std::get_terminate(); |
250 |
exception_header->exceptionType = tinfo; |
264 |
exception_header->exceptionType = tinfo; |
251 |
exception_header->exceptionDestructor = dest; |
265 |
exception_header->exceptionDestructor = dest; |
252 |
setExceptionClass(&exception_header->unwindHeader); |
266 |
setOurExceptionClass(&exception_header->unwindHeader); |
253 |
exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety. |
267 |
exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety. |
254 |
globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local |
268 |
globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local |
255 |
|
269 |
|
Lines 300-306
bool __cxa_begin_cleanup(void *unwind_arg) throw() {
Link Here
|
300 |
__cxa_exception* exception_header = |
314 |
__cxa_exception* exception_header = |
301 |
cxa_exception_from_exception_unwind_exception(unwind_exception); |
315 |
cxa_exception_from_exception_unwind_exception(unwind_exception); |
302 |
|
316 |
|
303 |
if (isOurExceptionClass(unwind_exception)) |
317 |
if (__isOurExceptionClass(unwind_exception)) |
304 |
{ |
318 |
{ |
305 |
if (0 == exception_header->propagationCount) |
319 |
if (0 == exception_header->propagationCount) |
306 |
{ |
320 |
{ |
Lines 343-349
__cxa_end_cleanup_impl()
Link Here
|
343 |
std::terminate(); |
357 |
std::terminate(); |
344 |
} |
358 |
} |
345 |
|
359 |
|
346 |
if (isOurExceptionClass(&exception_header->unwindHeader)) |
360 |
if (__isOurExceptionClass(&exception_header->unwindHeader)) |
347 |
{ |
361 |
{ |
348 |
--exception_header->propagationCount; |
362 |
--exception_header->propagationCount; |
349 |
if (0 == exception_header->propagationCount) |
363 |
if (0 == exception_header->propagationCount) |
Lines 408-414
void*
Link Here
|
408 |
__cxa_begin_catch(void* unwind_arg) throw() |
422 |
__cxa_begin_catch(void* unwind_arg) throw() |
409 |
{ |
423 |
{ |
410 |
_Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg); |
424 |
_Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg); |
411 |
bool native_exception = isOurExceptionClass(unwind_exception); |
425 |
bool native_exception = __isOurExceptionClass(unwind_exception); |
412 |
__cxa_eh_globals* globals = __cxa_get_globals(); |
426 |
__cxa_eh_globals* globals = __cxa_get_globals(); |
413 |
// exception_header is a hackish offset from a foreign exception, but it |
427 |
// exception_header is a hackish offset from a foreign exception, but it |
414 |
// works as long as we're careful not to try to access any __cxa_exception |
428 |
// works as long as we're careful not to try to access any __cxa_exception |
Lines 485-491
void __cxa_end_catch() {
Link Here
|
485 |
// nothing more to be done. Do nothing! |
499 |
// nothing more to be done. Do nothing! |
486 |
if (NULL != exception_header) |
500 |
if (NULL != exception_header) |
487 |
{ |
501 |
{ |
488 |
bool native_exception = isOurExceptionClass(&exception_header->unwindHeader); |
502 |
bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader); |
489 |
if (native_exception) |
503 |
if (native_exception) |
490 |
{ |
504 |
{ |
491 |
// This is a native exception |
505 |
// This is a native exception |
Lines 550-556
std::type_info *__cxa_current_exception_type() {
Link Here
|
550 |
__cxa_exception *exception_header = globals->caughtExceptions; |
564 |
__cxa_exception *exception_header = globals->caughtExceptions; |
551 |
if (NULL == exception_header) |
565 |
if (NULL == exception_header) |
552 |
return NULL; // No current exception |
566 |
return NULL; // No current exception |
553 |
if (!isOurExceptionClass(&exception_header->unwindHeader)) |
567 |
if (!__isOurExceptionClass(&exception_header->unwindHeader)) |
554 |
return NULL; |
568 |
return NULL; |
555 |
return exception_header->exceptionType; |
569 |
return exception_header->exceptionType; |
556 |
} |
570 |
} |
Lines 572-578
void __cxa_rethrow() {
Link Here
|
572 |
__cxa_exception* exception_header = globals->caughtExceptions; |
586 |
__cxa_exception* exception_header = globals->caughtExceptions; |
573 |
if (NULL == exception_header) |
587 |
if (NULL == exception_header) |
574 |
std::terminate(); // throw; called outside of a exception handler |
588 |
std::terminate(); // throw; called outside of a exception handler |
575 |
bool native_exception = isOurExceptionClass(&exception_header->unwindHeader); |
589 |
bool native_exception = __isOurExceptionClass(&exception_header->unwindHeader); |
576 |
if (native_exception) |
590 |
if (native_exception) |
577 |
{ |
591 |
{ |
578 |
// Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch) |
592 |
// Mark the exception as being rethrown (reverse the effects of __cxa_begin_catch) |
Lines 661-667
void *__cxa_current_primary_exception() throw() {
Link Here
|
661 |
__cxa_exception* exception_header = globals->caughtExceptions; |
675 |
__cxa_exception* exception_header = globals->caughtExceptions; |
662 |
if (NULL == exception_header) |
676 |
if (NULL == exception_header) |
663 |
return NULL; // No current exception |
677 |
return NULL; // No current exception |
664 |
if (!isOurExceptionClass(&exception_header->unwindHeader)) |
678 |
if (!__isOurExceptionClass(&exception_header->unwindHeader)) |
665 |
return NULL; // Can't capture a foreign exception (no way to refcount it) |
679 |
return NULL; // Can't capture a foreign exception (no way to refcount it) |
666 |
if (isDependentException(&exception_header->unwindHeader)) { |
680 |
if (isDependentException(&exception_header->unwindHeader)) { |
667 |
__cxa_dependent_exception* dep_exception_header = |
681 |
__cxa_dependent_exception* dep_exception_header = |