| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <assert.h> |
| | #include <stdlib.h> |
| | #include <string.h> |
| | #include <typeinfo> |
| |
|
| | #include "__cxxabi_config.h" |
| | #include "cxa_exception.h" |
| | #include "cxa_handlers.h" |
| | #include "private_typeinfo.h" |
| | #include "unwind.h" |
| |
|
| | #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) |
| | #include <windows.h> |
| | #include <winnt.h> |
| |
|
| | extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, |
| | void *, PCONTEXT, |
| | PDISPATCHER_CONTEXT, |
| | _Unwind_Personality_Fn); |
| | #endif |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | namespace __cxxabiv1 |
| | { |
| |
|
| | namespace |
| | { |
| |
|
| | template <class AsType> |
| | uintptr_t readPointerHelper(const uint8_t*& p) { |
| | AsType value; |
| | memcpy(&value, p, sizeof(AsType)); |
| | p += sizeof(AsType); |
| | return static_cast<uintptr_t>(value); |
| | } |
| |
|
| | } |
| |
|
| | extern "C" |
| | { |
| |
|
| | |
| |
|
| | |
| |
|
| | |
| | enum |
| | { |
| | DW_EH_PE_absptr = 0x00, |
| | DW_EH_PE_uleb128 = 0x01, |
| | DW_EH_PE_udata2 = 0x02, |
| | DW_EH_PE_udata4 = 0x03, |
| | DW_EH_PE_udata8 = 0x04, |
| | DW_EH_PE_sleb128 = 0x09, |
| | DW_EH_PE_sdata2 = 0x0A, |
| | DW_EH_PE_sdata4 = 0x0B, |
| | DW_EH_PE_sdata8 = 0x0C, |
| | DW_EH_PE_pcrel = 0x10, |
| | DW_EH_PE_textrel = 0x20, |
| | DW_EH_PE_datarel = 0x30, |
| | DW_EH_PE_funcrel = 0x40, |
| | DW_EH_PE_aligned = 0x50, |
| | DW_EH_PE_indirect = 0x80, |
| | DW_EH_PE_omit = 0xFF |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | static |
| | uintptr_t |
| | readULEB128(const uint8_t** data) |
| | { |
| | uintptr_t result = 0; |
| | uintptr_t shift = 0; |
| | unsigned char byte; |
| | const uint8_t *p = *data; |
| | do |
| | { |
| | byte = *p++; |
| | result |= static_cast<uintptr_t>(byte & 0x7F) << shift; |
| | shift += 7; |
| | } while (byte & 0x80); |
| | *data = p; |
| | return result; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | static |
| | intptr_t |
| | readSLEB128(const uint8_t** data) |
| | { |
| | uintptr_t result = 0; |
| | uintptr_t shift = 0; |
| | unsigned char byte; |
| | const uint8_t *p = *data; |
| | do |
| | { |
| | byte = *p++; |
| | result |= static_cast<uintptr_t>(byte & 0x7F) << shift; |
| | shift += 7; |
| | } while (byte & 0x80); |
| | *data = p; |
| | if ((byte & 0x40) && (shift < (sizeof(result) << 3))) |
| | result |= static_cast<uintptr_t>(~0) << shift; |
| | return static_cast<intptr_t>(result); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static |
| | uintptr_t |
| | readEncodedPointer(const uint8_t** data, uint8_t encoding) |
| | { |
| | uintptr_t result = 0; |
| | if (encoding == DW_EH_PE_omit) |
| | return result; |
| | const uint8_t* p = *data; |
| | |
| | switch (encoding & 0x0F) |
| | { |
| | case DW_EH_PE_absptr: |
| | result = readPointerHelper<uintptr_t>(p); |
| | break; |
| | case DW_EH_PE_uleb128: |
| | result = readULEB128(&p); |
| | break; |
| | case DW_EH_PE_sleb128: |
| | result = static_cast<uintptr_t>(readSLEB128(&p)); |
| | break; |
| | case DW_EH_PE_udata2: |
| | result = readPointerHelper<uint16_t>(p); |
| | break; |
| | case DW_EH_PE_udata4: |
| | result = readPointerHelper<uint32_t>(p); |
| | break; |
| | case DW_EH_PE_udata8: |
| | result = readPointerHelper<uint64_t>(p); |
| | break; |
| | case DW_EH_PE_sdata2: |
| | result = readPointerHelper<int16_t>(p); |
| | break; |
| | case DW_EH_PE_sdata4: |
| | result = readPointerHelper<int32_t>(p); |
| | break; |
| | case DW_EH_PE_sdata8: |
| | result = readPointerHelper<int64_t>(p); |
| | break; |
| | default: |
| | |
| | abort(); |
| | break; |
| | } |
| | |
| | switch (encoding & 0x70) |
| | { |
| | case DW_EH_PE_absptr: |
| | |
| | break; |
| | case DW_EH_PE_pcrel: |
| | if (result) |
| | result += (uintptr_t)(*data); |
| | break; |
| | case DW_EH_PE_textrel: |
| | case DW_EH_PE_datarel: |
| | case DW_EH_PE_funcrel: |
| | case DW_EH_PE_aligned: |
| | default: |
| | |
| | abort(); |
| | break; |
| | } |
| | |
| | if (result && (encoding & DW_EH_PE_indirect)) |
| | result = *((uintptr_t*)result); |
| | *data = p; |
| | return result; |
| | } |
| |
|
| | static |
| | void |
| | call_terminate(bool native_exception, _Unwind_Exception* unwind_exception) |
| | { |
| | __cxa_begin_catch(unwind_exception); |
| | if (native_exception) |
| | { |
| | |
| | __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; |
| | std::__terminate(exception_header->terminateHandler); |
| | } |
| | std::terminate(); |
| | } |
| |
|
| | #if defined(_LIBCXXABI_ARM_EHABI) |
| | static const void* read_target2_value(const void* ptr) |
| | { |
| | uintptr_t offset = *reinterpret_cast<const uintptr_t*>(ptr); |
| | if (!offset) |
| | return 0; |
| | |
| | |
| | |
| | |
| | |
| | #if defined(LIBCXXABI_BAREMETAL) |
| | return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(ptr) + |
| | offset); |
| | #else |
| | return *reinterpret_cast<const void **>(reinterpret_cast<uintptr_t>(ptr) + |
| | offset); |
| | #endif |
| | } |
| |
|
| | static const __shim_type_info* |
| | get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo, |
| | uint8_t ttypeEncoding, bool native_exception, |
| | _Unwind_Exception* unwind_exception) |
| | { |
| | if (classInfo == 0) |
| | { |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| |
|
| | assert(((ttypeEncoding == DW_EH_PE_absptr) || |
| | (ttypeEncoding == DW_EH_PE_pcrel) || |
| | (ttypeEncoding == (DW_EH_PE_pcrel | DW_EH_PE_indirect))) && |
| | "Unexpected TTypeEncoding"); |
| | (void)ttypeEncoding; |
| |
|
| | const uint8_t* ttypePtr = classInfo - ttypeIndex * sizeof(uintptr_t); |
| | return reinterpret_cast<const __shim_type_info *>( |
| | read_target2_value(ttypePtr)); |
| | } |
| | #else |
| | static |
| | const __shim_type_info* |
| | get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo, |
| | uint8_t ttypeEncoding, bool native_exception, |
| | _Unwind_Exception* unwind_exception) |
| | { |
| | if (classInfo == 0) |
| | { |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | switch (ttypeEncoding & 0x0F) |
| | { |
| | case DW_EH_PE_absptr: |
| | ttypeIndex *= sizeof(void*); |
| | break; |
| | case DW_EH_PE_udata2: |
| | case DW_EH_PE_sdata2: |
| | ttypeIndex *= 2; |
| | break; |
| | case DW_EH_PE_udata4: |
| | case DW_EH_PE_sdata4: |
| | ttypeIndex *= 4; |
| | break; |
| | case DW_EH_PE_udata8: |
| | case DW_EH_PE_sdata8: |
| | ttypeIndex *= 8; |
| | break; |
| | default: |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | classInfo -= ttypeIndex; |
| | return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding); |
| | } |
| | #endif |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #if defined(_LIBCXXABI_ARM_EHABI) |
| | static |
| | bool |
| | exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, |
| | uint8_t ttypeEncoding, const __shim_type_info* excpType, |
| | void* adjustedPtr, _Unwind_Exception* unwind_exception) |
| | { |
| | if (classInfo == 0) |
| | { |
| | |
| | call_terminate(false, unwind_exception); |
| | } |
| |
|
| | assert(((ttypeEncoding == DW_EH_PE_absptr) || |
| | (ttypeEncoding == DW_EH_PE_pcrel) || |
| | (ttypeEncoding == (DW_EH_PE_pcrel | DW_EH_PE_indirect))) && |
| | "Unexpected TTypeEncoding"); |
| | (void)ttypeEncoding; |
| |
|
| | |
| | specIndex = -specIndex; |
| | --specIndex; |
| | const void** temp = reinterpret_cast<const void**>( |
| | reinterpret_cast<uintptr_t>(classInfo) + |
| | static_cast<uintptr_t>(specIndex) * sizeof(uintptr_t)); |
| | |
| | |
| | while (true) |
| | { |
| | |
| | |
| | |
| | const void** ttypePtr = temp++; |
| | if (*ttypePtr == 0) |
| | break; |
| | |
| | |
| | const __shim_type_info* catchType = |
| | static_cast<const __shim_type_info*>(read_target2_value(ttypePtr)); |
| | void* tempPtr = adjustedPtr; |
| | if (catchType->can_catch(excpType, tempPtr)) |
| | return false; |
| | } |
| | return true; |
| | } |
| | #else |
| | static |
| | bool |
| | exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, |
| | uint8_t ttypeEncoding, const __shim_type_info* excpType, |
| | void* adjustedPtr, _Unwind_Exception* unwind_exception) |
| | { |
| | if (classInfo == 0) |
| | { |
| | |
| | call_terminate(false, unwind_exception); |
| | } |
| | |
| | specIndex = -specIndex; |
| | --specIndex; |
| | const uint8_t* temp = classInfo + specIndex; |
| | |
| | |
| | while (true) |
| | { |
| | uint64_t ttypeIndex = readULEB128(&temp); |
| | if (ttypeIndex == 0) |
| | break; |
| | const __shim_type_info* catchType = get_shim_type_info(ttypeIndex, |
| | classInfo, |
| | ttypeEncoding, |
| | true, |
| | unwind_exception); |
| | void* tempPtr = adjustedPtr; |
| | if (catchType->can_catch(excpType, tempPtr)) |
| | return false; |
| | } |
| | return true; |
| | } |
| | #endif |
| |
|
| | static |
| | void* |
| | get_thrown_object_ptr(_Unwind_Exception* unwind_exception) |
| | { |
| | |
| | |
| | void* adjustedPtr = unwind_exception + 1; |
| | if (__getExceptionClass(unwind_exception) == kOurDependentExceptionClass) |
| | adjustedPtr = ((__cxa_dependent_exception*)adjustedPtr - 1)->primaryException; |
| | return adjustedPtr; |
| | } |
| |
|
| | namespace |
| | { |
| |
|
| | struct scan_results |
| | { |
| | int64_t ttypeIndex; |
| | const uint8_t* actionRecord; |
| | const uint8_t* languageSpecificData; |
| | uintptr_t landingPad; |
| | void* adjustedPtr; |
| | _Unwind_Reason_Code reason; |
| | |
| | |
| | |
| | }; |
| |
|
| | } |
| |
|
| | static constexpr int __builtin_eh_return_data_regno(int __i) { |
| | switch (__i) { |
| | #ifdef __x86_64__ |
| | case 0: return 0; |
| | case 1: return 1; |
| | #else |
| | #error Unsupported architecture. |
| | #endif |
| | default: |
| | return -1; |
| | } |
| | } |
| |
|
| | static |
| | void |
| | set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context, |
| | const scan_results& results) |
| | { |
| | #if defined(__USING_SJLJ_EXCEPTIONS__) |
| | #define __builtin_eh_return_data_regno(regno) regno |
| | #endif |
| | _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), |
| | reinterpret_cast<uintptr_t>(unwind_exception)); |
| | _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), |
| | static_cast<uintptr_t>(results.ttypeIndex)); |
| | _Unwind_SetIP(context, results.landingPad); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | static void scan_eh_tab(scan_results &results, _Unwind_Action actions, |
| | bool native_exception, |
| | _Unwind_Exception *unwind_exception, |
| | _Unwind_Context *context) { |
| | |
| | results.ttypeIndex = 0; |
| | results.actionRecord = 0; |
| | results.languageSpecificData = 0; |
| | results.landingPad = 0; |
| | results.adjustedPtr = 0; |
| | results.reason = _URC_FATAL_PHASE1_ERROR; |
| | |
| | if (actions & _UA_SEARCH_PHASE) |
| | { |
| | |
| | if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) |
| | { |
| | |
| | |
| | results.reason = _URC_FATAL_PHASE1_ERROR; |
| | return; |
| | } |
| | } |
| | else if (actions & _UA_CLEANUP_PHASE) |
| | { |
| | if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) |
| | { |
| | |
| | |
| | |
| | results.reason = _URC_FATAL_PHASE2_ERROR; |
| | return; |
| | } |
| | } |
| | else |
| | { |
| | |
| | |
| | results.reason = _URC_FATAL_PHASE1_ERROR; |
| | return; |
| | } |
| | |
| | const uint8_t *lsda = (const uint8_t *)_Unwind_GetLanguageSpecificData(context); |
| | if (lsda == 0) |
| | { |
| | |
| | results.reason = _URC_CONTINUE_UNWIND; |
| | return; |
| | } |
| | results.languageSpecificData = lsda; |
| | |
| | |
| | uintptr_t ip = _Unwind_GetIP(context) - 1; |
| | |
| | |
| | uintptr_t funcStart = _Unwind_GetRegionStart(context); |
| | #ifdef __USING_SJLJ_EXCEPTIONS__ |
| | if (ip == uintptr_t(-1)) |
| | { |
| | |
| | results.reason = _URC_CONTINUE_UNWIND; |
| | return; |
| | } |
| | else if (ip == 0) |
| | call_terminate(native_exception, unwind_exception); |
| | |
| | #else |
| | uintptr_t ipOffset = ip - funcStart; |
| | #endif |
| | const uint8_t* classInfo = NULL; |
| | |
| | |
| | |
| | uint8_t lpStartEncoding = *lsda++; |
| | const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); |
| | if (lpStart == 0) |
| | lpStart = (const uint8_t*)funcStart; |
| | uint8_t ttypeEncoding = *lsda++; |
| | if (ttypeEncoding != DW_EH_PE_omit) |
| | { |
| | |
| | |
| | |
| | uintptr_t classInfoOffset = readULEB128(&lsda); |
| | classInfo = lsda + classInfoOffset; |
| | } |
| | |
| | |
| | uint8_t callSiteEncoding = *lsda++; |
| | #ifdef __USING_SJLJ_EXCEPTIONS__ |
| | (void)callSiteEncoding; |
| | #endif |
| | uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda)); |
| | const uint8_t* callSiteTableStart = lsda; |
| | const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; |
| | const uint8_t* actionTableStart = callSiteTableEnd; |
| | const uint8_t* callSitePtr = callSiteTableStart; |
| | while (callSitePtr < callSiteTableEnd) |
| | { |
| | |
| | #ifndef __USING_SJLJ_EXCEPTIONS__ |
| | |
| | |
| | uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); |
| | uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding); |
| | uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); |
| | uintptr_t actionEntry = readULEB128(&callSitePtr); |
| | if ((start <= ipOffset) && (ipOffset < (start + length))) |
| | #else |
| | |
| | uintptr_t landingPad = readULEB128(&callSitePtr); |
| | uintptr_t actionEntry = readULEB128(&callSitePtr); |
| | if (--ip == 0) |
| | #endif |
| | { |
| | |
| | #ifndef __USING_SJLJ_EXCEPTIONS__ |
| | if (landingPad == 0) |
| | { |
| | |
| | results.reason = _URC_CONTINUE_UNWIND; |
| | return; |
| | } |
| | landingPad = (uintptr_t)lpStart + landingPad; |
| | #else |
| | ++landingPad; |
| | #endif |
| | if (actionEntry == 0) |
| | { |
| | |
| | |
| | |
| | if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) |
| | { |
| | results.ttypeIndex = 0; |
| | results.landingPad = landingPad; |
| | results.reason = _URC_HANDLER_FOUND; |
| | return; |
| | } |
| | |
| | results.reason = _URC_CONTINUE_UNWIND; |
| | return; |
| | } |
| | |
| | const uint8_t* action = actionTableStart + (actionEntry - 1); |
| | |
| | while (true) |
| | { |
| | const uint8_t* actionRecord = action; |
| | int64_t ttypeIndex = readSLEB128(&action); |
| | if (ttypeIndex > 0) |
| | { |
| | |
| | |
| | const __shim_type_info* catchType = |
| | get_shim_type_info(static_cast<uint64_t>(ttypeIndex), |
| | classInfo, ttypeEncoding, |
| | native_exception, unwind_exception); |
| | if (catchType == 0) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) |
| | { |
| | |
| | results.ttypeIndex = ttypeIndex; |
| | results.actionRecord = actionRecord; |
| | results.landingPad = landingPad; |
| | results.adjustedPtr = get_thrown_object_ptr(unwind_exception); |
| | results.reason = _URC_HANDLER_FOUND; |
| | return; |
| | } |
| | else if (!(actions & _UA_FORCE_UNWIND)) |
| | { |
| | |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | } |
| | |
| | |
| | else if (native_exception) |
| | { |
| | __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; |
| | void* adjustedPtr = get_thrown_object_ptr(unwind_exception); |
| | const __shim_type_info* excpType = |
| | static_cast<const __shim_type_info*>(exception_header->exceptionType); |
| | if (adjustedPtr == 0 || excpType == 0) |
| | { |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | if (catchType->can_catch(excpType, adjustedPtr)) |
| | { |
| | |
| | |
| | |
| | |
| | if (actions & _UA_SEARCH_PHASE) |
| | { |
| | |
| | results.ttypeIndex = ttypeIndex; |
| | results.actionRecord = actionRecord; |
| | results.landingPad = landingPad; |
| | results.adjustedPtr = adjustedPtr; |
| | results.reason = _URC_HANDLER_FOUND; |
| | return; |
| | } |
| | else if (!(actions & _UA_FORCE_UNWIND)) |
| | { |
| | |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | } |
| | } |
| | |
| | } |
| | else if (ttypeIndex < 0) |
| | { |
| | |
| | |
| | if (native_exception) |
| | { |
| | |
| | __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; |
| | void* adjustedPtr = get_thrown_object_ptr(unwind_exception); |
| | const __shim_type_info* excpType = |
| | static_cast<const __shim_type_info*>(exception_header->exceptionType); |
| | if (adjustedPtr == 0 || excpType == 0) |
| | { |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | if (exception_spec_can_catch(ttypeIndex, classInfo, |
| | ttypeEncoding, excpType, |
| | adjustedPtr, unwind_exception)) |
| | { |
| | |
| | |
| | |
| | |
| | if (actions & _UA_SEARCH_PHASE) |
| | { |
| | |
| | results.ttypeIndex = ttypeIndex; |
| | results.actionRecord = actionRecord; |
| | results.landingPad = landingPad; |
| | results.adjustedPtr = adjustedPtr; |
| | results.reason = _URC_HANDLER_FOUND; |
| | return; |
| | } |
| | else if (!(actions & _UA_FORCE_UNWIND)) |
| | { |
| | |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | } |
| | } |
| | else |
| | { |
| | |
| | |
| | |
| | |
| | |
| | if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) |
| | { |
| | |
| | results.ttypeIndex = ttypeIndex; |
| | results.actionRecord = actionRecord; |
| | results.landingPad = landingPad; |
| | results.adjustedPtr = get_thrown_object_ptr(unwind_exception); |
| | results.reason = _URC_HANDLER_FOUND; |
| | return; |
| | } |
| | else if (!(actions & _UA_FORCE_UNWIND)) |
| | { |
| | |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | } |
| | |
| | } |
| | else |
| | { |
| | |
| | |
| | |
| | |
| | if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) |
| | { |
| | |
| | results.ttypeIndex = ttypeIndex; |
| | results.actionRecord = actionRecord; |
| | results.landingPad = landingPad; |
| | results.adjustedPtr = get_thrown_object_ptr(unwind_exception); |
| | results.reason = _URC_HANDLER_FOUND; |
| | return; |
| | } |
| | } |
| | const uint8_t* temp = action; |
| | int64_t actionOffset = readSLEB128(&temp); |
| | if (actionOffset == 0) |
| | { |
| | |
| | results.reason = _URC_CONTINUE_UNWIND; |
| | return; |
| | } |
| | |
| | action += actionOffset; |
| | } |
| | } |
| | #ifndef __USING_SJLJ_EXCEPTIONS__ |
| | else if (ipOffset < start) |
| | { |
| | |
| | |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | #endif |
| | } |
| |
|
| | |
| | |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| |
|
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #if !defined(_LIBCXXABI_ARM_EHABI) |
| | #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) |
| | static _Unwind_Reason_Code __gxx_personality_imp |
| | #else |
| | _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code |
| | #ifdef __USING_SJLJ_EXCEPTIONS__ |
| | __gxx_personality_sj0 |
| | #else |
| | __gxx_personality_v0 |
| | #endif |
| | #endif |
| | (int version, _Unwind_Action actions, uint64_t exceptionClass, |
| | _Unwind_Exception* unwind_exception, _Unwind_Context* context) |
| | { |
| | if (version != 1 || unwind_exception == 0 || context == 0) |
| | return _URC_FATAL_PHASE1_ERROR; |
| |
|
| | bool native_exception = (exceptionClass & get_vendor_and_language) == |
| | (kOurExceptionClass & get_vendor_and_language); |
| | scan_results results; |
| | if (actions & _UA_SEARCH_PHASE) |
| | { |
| | |
| | |
| | scan_eh_tab(results, actions, native_exception, unwind_exception, context); |
| | if (results.reason == _URC_HANDLER_FOUND) |
| | { |
| | |
| | if (native_exception) |
| | { |
| | __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; |
| | exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex); |
| | exception_header->actionRecord = results.actionRecord; |
| | exception_header->languageSpecificData = results.languageSpecificData; |
| | exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad); |
| | exception_header->adjustedPtr = results.adjustedPtr; |
| | } |
| | return _URC_HANDLER_FOUND; |
| | } |
| | |
| | |
| | |
| | return results.reason; |
| | } |
| | if (actions & _UA_CLEANUP_PHASE) |
| | { |
| | |
| | |
| | if (actions & _UA_HANDLER_FRAME) |
| | { |
| | |
| | |
| | if (native_exception) |
| | { |
| | |
| | __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; |
| | results.ttypeIndex = exception_header->handlerSwitchValue; |
| | results.actionRecord = exception_header->actionRecord; |
| | results.languageSpecificData = exception_header->languageSpecificData; |
| | results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp); |
| | results.adjustedPtr = exception_header->adjustedPtr; |
| | } |
| | else |
| | { |
| | |
| | scan_eh_tab(results, actions, native_exception, unwind_exception, context); |
| | |
| | |
| | if (results.reason != _URC_HANDLER_FOUND) |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| | |
| | set_registers(unwind_exception, context, results); |
| | return _URC_INSTALL_CONTEXT; |
| | } |
| | |
| | |
| | |
| | scan_eh_tab(results, actions, native_exception, unwind_exception, context); |
| | if (results.reason == _URC_HANDLER_FOUND) |
| | { |
| | |
| | set_registers(unwind_exception, context, results); |
| | return _URC_INSTALL_CONTEXT; |
| | } |
| | |
| | |
| | |
| | return results.reason; |
| | } |
| | |
| | return _URC_FATAL_PHASE1_ERROR; |
| | } |
| |
|
| | #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) |
| | extern "C" _LIBCXXABI_FUNC_VIS EXCEPTION_DISPOSITION |
| | __gxx_personality_seh0(PEXCEPTION_RECORD ms_exc, void *this_frame, |
| | PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp) |
| | { |
| | return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context, ms_disp, |
| | __gxx_personality_imp); |
| | } |
| | #endif |
| |
|
| | #else |
| |
|
| | extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*, |
| | _Unwind_Context*); |
| |
|
| | |
| | |
| | |
| | |
| | static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception, |
| | _Unwind_Context* context) |
| | { |
| | if (__gnu_unwind_frame(unwind_exception, context) != _URC_OK) |
| | return _URC_FAILURE; |
| | return _URC_CONTINUE_UNWIND; |
| | } |
| |
|
| | |
| | #if !defined(LIBCXXABI_USE_LLVM_UNWINDER) |
| | static const uint32_t REG_UCB = 12; |
| | #endif |
| | static const uint32_t REG_SP = 13; |
| |
|
| | static void save_results_to_barrier_cache(_Unwind_Exception* unwind_exception, |
| | const scan_results& results) |
| | { |
| | unwind_exception->barrier_cache.bitpattern[0] = (uint32_t)results.adjustedPtr; |
| | unwind_exception->barrier_cache.bitpattern[1] = (uint32_t)results.actionRecord; |
| | unwind_exception->barrier_cache.bitpattern[2] = (uint32_t)results.languageSpecificData; |
| | unwind_exception->barrier_cache.bitpattern[3] = (uint32_t)results.landingPad; |
| | unwind_exception->barrier_cache.bitpattern[4] = (uint32_t)results.ttypeIndex; |
| | } |
| |
|
| | static void load_results_from_barrier_cache(scan_results& results, |
| | const _Unwind_Exception* unwind_exception) |
| | { |
| | results.adjustedPtr = (void*)unwind_exception->barrier_cache.bitpattern[0]; |
| | results.actionRecord = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[1]; |
| | results.languageSpecificData = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[2]; |
| | results.landingPad = (uintptr_t)unwind_exception->barrier_cache.bitpattern[3]; |
| | results.ttypeIndex = (int64_t)(int32_t)unwind_exception->barrier_cache.bitpattern[4]; |
| | } |
| |
|
| | extern "C" _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code |
| | __gxx_personality_v0(_Unwind_State state, |
| | _Unwind_Exception* unwind_exception, |
| | _Unwind_Context* context) |
| | { |
| | if (unwind_exception == 0 || context == 0) |
| | return _URC_FATAL_PHASE1_ERROR; |
| |
|
| | bool native_exception = __isOurExceptionClass(unwind_exception); |
| |
|
| | #if !defined(LIBCXXABI_USE_LLVM_UNWINDER) |
| | |
| | |
| | |
| | _Unwind_SetGR(context, REG_UCB, reinterpret_cast<uint32_t>(unwind_exception)); |
| | #endif |
| |
|
| | |
| | bool is_force_unwinding = state & _US_FORCE_UNWIND; |
| | state &= ~_US_FORCE_UNWIND; |
| |
|
| | scan_results results; |
| | switch (state) { |
| | case _US_VIRTUAL_UNWIND_FRAME: |
| | if (is_force_unwinding) |
| | return continue_unwind(unwind_exception, context); |
| |
|
| | |
| | scan_eh_tab(results, _UA_SEARCH_PHASE, native_exception, unwind_exception, context); |
| | if (results.reason == _URC_HANDLER_FOUND) |
| | { |
| | unwind_exception->barrier_cache.sp = _Unwind_GetGR(context, REG_SP); |
| | if (native_exception) |
| | save_results_to_barrier_cache(unwind_exception, results); |
| | return _URC_HANDLER_FOUND; |
| | } |
| | |
| | if (results.reason == _URC_CONTINUE_UNWIND) |
| | return continue_unwind(unwind_exception, context); |
| | return results.reason; |
| |
|
| | case _US_UNWIND_FRAME_STARTING: |
| | |
| | |
| | |
| | |
| |
|
| | |
| | if (unwind_exception->barrier_cache.sp == _Unwind_GetGR(context, REG_SP)) |
| | { |
| | |
| | if (native_exception) |
| | { |
| | |
| | load_results_from_barrier_cache(results, unwind_exception); |
| | results.reason = _URC_HANDLER_FOUND; |
| | } |
| | else |
| | { |
| | |
| | scan_eh_tab(results, static_cast<_Unwind_Action>(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME), |
| | native_exception, unwind_exception, context); |
| | if (results.reason != _URC_HANDLER_FOUND) |
| | call_terminate(native_exception, unwind_exception); |
| | } |
| |
|
| | |
| | set_registers(unwind_exception, context, results); |
| | return _URC_INSTALL_CONTEXT; |
| | } |
| |
|
| | |
| | |
| | |
| | scan_eh_tab(results, _UA_CLEANUP_PHASE, native_exception, unwind_exception, context); |
| | if (results.reason == _URC_HANDLER_FOUND) |
| | { |
| | |
| |
|
| | |
| | |
| | |
| | __cxa_begin_cleanup(unwind_exception); |
| |
|
| | |
| | set_registers(unwind_exception, context, results); |
| | return _URC_INSTALL_CONTEXT; |
| | } |
| |
|
| | |
| | if (results.reason == _URC_CONTINUE_UNWIND) |
| | return continue_unwind(unwind_exception, context); |
| | return results.reason; |
| |
|
| | case _US_UNWIND_FRAME_RESUME: |
| | return continue_unwind(unwind_exception, context); |
| | } |
| |
|
| | |
| | return _URC_FATAL_PHASE1_ERROR; |
| | } |
| | #endif |
| |
|
| |
|
| | __attribute__((noreturn)) |
| | _LIBCXXABI_FUNC_VIS void |
| | __cxa_call_unexpected(void* arg) |
| | { |
| | _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg); |
| | if (unwind_exception == 0) |
| | call_terminate(false, unwind_exception); |
| | __cxa_begin_catch(unwind_exception); |
| | bool native_old_exception = __isOurExceptionClass(unwind_exception); |
| | std::unexpected_handler u_handler; |
| | std::terminate_handler t_handler; |
| | __cxa_exception* old_exception_header = 0; |
| | int64_t ttypeIndex; |
| | const uint8_t* lsda; |
| | if (native_old_exception) |
| | { |
| | old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1; |
| | t_handler = old_exception_header->terminateHandler; |
| | u_handler = old_exception_header->unexpectedHandler; |
| | |
| | |
| | #if defined(_LIBCXXABI_ARM_EHABI) |
| | ttypeIndex = (int64_t)(int32_t)unwind_exception->barrier_cache.bitpattern[4]; |
| | lsda = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[2]; |
| | #else |
| | ttypeIndex = old_exception_header->handlerSwitchValue; |
| | lsda = old_exception_header->languageSpecificData; |
| | #endif |
| | } |
| | else |
| | { |
| | t_handler = std::get_terminate(); |
| | u_handler = std::get_unexpected(); |
| | } |
| | try |
| | { |
| | std::__unexpected(u_handler); |
| | } |
| | catch (...) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | if (native_old_exception) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | uint8_t lpStartEncoding = *lsda++; |
| | const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); |
| | (void)lpStart; |
| | uint8_t ttypeEncoding = *lsda++; |
| | if (ttypeEncoding == DW_EH_PE_omit) |
| | std::__terminate(t_handler); |
| | uintptr_t classInfoOffset = readULEB128(&lsda); |
| | const uint8_t* classInfo = lsda + classInfoOffset; |
| | |
| | |
| | |
| | |
| | __cxa_eh_globals* globals = __cxa_get_globals_fast(); |
| | __cxa_exception* new_exception_header = globals->caughtExceptions; |
| | if (new_exception_header == 0) |
| | |
| | std::__terminate(t_handler); |
| | 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 = |
| | __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, |
| | excpType, adjustedPtr, unwind_exception)) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | new_exception_header->handlerCount = -new_exception_header->handlerCount; |
| | globals->uncaughtExceptions += 1; |
| | |
| | __cxa_end_catch(); |
| | |
| | __cxa_end_catch(); |
| | |
| | __cxa_begin_catch(&new_exception_header->unwindHeader); |
| | |
| | throw; |
| | } |
| | } |
| | |
| | |
| | |
| | |
| | const __shim_type_info* excpType = |
| | static_cast<const __shim_type_info*>(&typeid(std::bad_exception)); |
| | std::bad_exception be; |
| | adjustedPtr = &be; |
| | if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, |
| | excpType, adjustedPtr, unwind_exception)) |
| | { |
| | |
| | |
| | |
| | |
| | __cxa_end_catch(); |
| | |
| | |
| | throw be; |
| | } |
| | } |
| | } |
| | std::__terminate(t_handler); |
| | } |
| |
|
| | } |
| |
|
| | } |
| |
|