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) @@ -295,8 +296,12 @@ if (result) result += (uintptr_t)(*data); break; - case DW_EH_PE_textrel: case DW_EH_PE_datarel: + assert((base != 0) && "DW_EH_PE_datarel is invalid with a base of 0"); + if (result) + result += base; + break; + case DW_EH_PE_textrel: case DW_EH_PE_funcrel: case DW_EH_PE_aligned: default: @@ -348,7 +353,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 +376,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 +405,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 +424,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 +470,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 +493,8 @@ classInfo, ttypeEncoding, true, - unwind_exception); + unwind_exception, + base); void* tempPtr = adjustedPtr; if (catchType->can_catch(excpType, tempPtr)) return false; @@ -531,6 +540,9 @@ { #if defined(__USING_SJLJ_EXCEPTIONS__) #define __builtin_eh_return_data_regno(regno) regno +#elif defined(__ibmxl__) +// IBM xlclang++ compiler does not support __builtin_eh_return_data_regno. +#define __builtin_eh_return_data_regno(regno) regno + 3 #endif _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), reinterpret_cast(unwind_exception)); @@ -610,6 +622,11 @@ return; } results.languageSpecificData = lsda; +#if defined(_AIX) + uintptr_t base = _Unwind_GetDataRelBase(context); +#else + uintptr_t base = 0; +#endif // 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 +728,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 +790,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 +930,13 @@ // Jump to the handler. set_registers(unwind_exception, context, results); +#if defined(_AIX) + // Cache base for calculating the address of ttype in + // __cxa_call_unexpected. + if (results.ttypeIndex < 0) { + exception_header->catchTemp = (void *)_Unwind_GetDataRelBase(context); + } +#endif return _URC_INSTALL_CONTEXT; } @@ -940,6 +966,14 @@ assert(actions & _UA_CLEANUP_PHASE); assert(results.reason == _URC_HANDLER_FOUND); set_registers(unwind_exception, context, results); +#if defined(_AIX) + // 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 = (void *)_Unwind_GetDataRelBase(context); + } +#endif return _URC_INSTALL_CONTEXT; } @@ -1114,6 +1148,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 +1163,7 @@ #else ttypeIndex = old_exception_header->handlerSwitchValue; lsda = old_exception_header->languageSpecificData; + base = (uintptr_t)old_exception_header->catchTemp; #endif } else @@ -1150,6 +1187,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 +1219,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 +1249,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.