diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp --- a/libcxxabi/src/cxa_personality.cpp +++ b/libcxxabi/src/cxa_personality.cpp @@ -241,10 +241,11 @@ /// @link http://dwarfstd.org/Dwarf3.pdf @unlink /// @param data reference variable holding memory pointer to decode from /// @param encoding dwarf encoding type +/// @param base for adding relative offset, default to 0 /// @returns decoded value static uintptr_t -readEncodedPointer(const uint8_t** data, uint8_t encoding) +readEncodedPointer(const uint8_t** data, uint8_t encoding, uintptr_t base = 0) { uintptr_t result = 0; if (encoding == DW_EH_PE_omit) @@ -348,7 +349,7 @@ 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) + _Unwind_Exception* unwind_exception, uintptr_t base = 0) { if (classInfo == 0) { @@ -371,7 +372,7 @@ 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) + _Unwind_Exception* unwind_exception, uintptr_t base = 0) { if (classInfo == 0) { @@ -400,7 +401,8 @@ call_terminate(native_exception, unwind_exception); } classInfo -= ttypeIndex; - return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding); + return (const __shim_type_info*)readEncodedPointer(&classInfo, + ttypeEncoding, base); } #endif // !defined(_LIBCXXABI_ARM_EHABI) @@ -418,7 +420,8 @@ 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) + void* adjustedPtr, _Unwind_Exception* unwind_exception, + uintptr_t base = 0) { if (classInfo == 0) { @@ -463,7 +466,8 @@ 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) + void* adjustedPtr, _Unwind_Exception* unwind_exception, + uintptr_t base = 0) { if (classInfo == 0) { @@ -485,7 +489,8 @@ classInfo, ttypeEncoding, true, - unwind_exception); + unwind_exception, + base); void* tempPtr = adjustedPtr; if (catchType->can_catch(excpType, tempPtr)) return false; @@ -610,6 +615,7 @@ return; } results.languageSpecificData = lsda; + uintptr_t base = 0; // Get the current instruction pointer and offset it before next // instruction in the current frame which threw the exception. uintptr_t ip = _Unwind_GetIP(context) - 1; @@ -711,7 +717,8 @@ const __shim_type_info* catchType = get_shim_type_info(static_cast(ttypeIndex), classInfo, ttypeEncoding, - native_exception, unwind_exception); + native_exception, unwind_exception, + base); if (catchType == 0) { // Found catch (...) catches everything, including @@ -772,7 +779,8 @@ } if (exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, - adjustedPtr, unwind_exception)) + adjustedPtr, + unwind_exception, base)) { // Native exception caught by exception // specification. @@ -911,6 +919,10 @@ // Jump to the handler. set_registers(unwind_exception, context, results); + // Cache base for calculating the address of ttype in + // __cxa_call_unexpected. + if (results.ttypeIndex < 0) + exception_header->catchTemp = 0; return _URC_INSTALL_CONTEXT; } @@ -940,6 +952,12 @@ assert(actions & _UA_CLEANUP_PHASE); assert(results.reason == _URC_HANDLER_FOUND); set_registers(unwind_exception, context, results); + // Cache base for calculating the address of ttype in __cxa_call_unexpected. + if (results.ttypeIndex < 0) { + __cxa_exception* exception_header = + (__cxa_exception*)(unwind_exception + 1) - 1; + exception_header->catchTemp = 0; + } return _URC_INSTALL_CONTEXT; } @@ -1114,6 +1132,8 @@ __cxa_exception* old_exception_header = 0; int64_t ttypeIndex; const uint8_t* lsda; + uintptr_t base = 0; + if (native_old_exception) { old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1; @@ -1127,6 +1147,7 @@ #else ttypeIndex = old_exception_header->handlerSwitchValue; lsda = old_exception_header->languageSpecificData; + base = (uintptr_t)old_exception_header->catchTemp; #endif } else @@ -1150,6 +1171,7 @@ // Have: // old_exception_header->languageSpecificData // old_exception_header->actionRecord + // old_exception_header->catchTemp, base for calculating ttype // Need // const uint8_t* classInfo // uint8_t ttypeEncoding @@ -1181,7 +1203,8 @@ ((__cxa_dependent_exception*)new_exception_header)->primaryException : new_exception_header + 1; if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, - excpType, adjustedPtr, unwind_exception)) + excpType, adjustedPtr, + unwind_exception, base)) { // We need to __cxa_end_catch, but for the old exception, // not the new one. This is a little tricky ... @@ -1210,7 +1233,8 @@ std::bad_exception be; adjustedPtr = &be; if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, - excpType, adjustedPtr, unwind_exception)) + excpType, adjustedPtr, + unwind_exception, base)) { // We need to __cxa_end_catch for both the old exception and the // new exception. Technically we should do it in that order.