Index: src/Unwind/Unwind-EHABI.h =================================================================== --- /dev/null +++ src/Unwind/Unwind-EHABI.h @@ -0,0 +1,45 @@ +//===------------------------- Unwind-EHABI.hpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +//===----------------------------------------------------------------------===// + +#ifndef __UNWIND_EHABI_H__ +#define __UNWIND_EHABI_H__ + +#include +#include + +// Unable to unwind in the ARM index table (section 5 EHABI). +#define UNW_EXIDX_CANTUNWIND 0x1 + +static inline uint32_t signExtendPrel31(uint32_t data) { + return data | ((data & 0x40000000u) << 1); +} + +static inline uint32_t readPrel31(const uint32_t *data) { + return (((uint32_t) data) + signExtendPrel31(*data)); +} + +#if defined(__cplusplus) +extern "C" { +#endif + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // __UNWIND_EHABI_H__ Index: src/Unwind/Unwind-EHABI.cpp =================================================================== --- src/Unwind/Unwind-EHABI.cpp +++ src/Unwind/Unwind-EHABI.cpp @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +#include "Unwind-EHABI.h" + #include #include @@ -44,10 +46,6 @@ return data + 2; } -static inline uint32_t signExtendPrel31(uint32_t data) { - return data | ((data & 0x40000000u) << 1); -} - struct Descriptor { // See # 9.2 typedef enum { @@ -162,10 +160,9 @@ return _URC_CONTINUE_UNWIND; } -_Unwind_Reason_Code unwindOneFrame( - _Unwind_State state, - _Unwind_Control_Block* ucbp, - struct _Unwind_Context* context) { +static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state, + _Unwind_Control_Block* ucbp, + struct _Unwind_Context* context) { // Read the compact model EHT entry's header # 6.3 const uint32_t* unwindingData = ucbp->pr_cache.ehtp; assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry"); @@ -216,44 +213,27 @@ */ extern "C" const uint32_t* decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { - if ((*data & 0x80000000) == 0) { - // 6.2: Generic Model - // EHT entry is a prel31 pointing to the PR, followed by data understood only - // by the personality routine. Since EHABI doesn't guarantee the location or - // availability of the unwind opcodes in the generic model, we have to check - // for them on a case-by-case basis: - _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, - uint64_t exceptionClass, - _Unwind_Exception* unwind_exception, - _Unwind_Context* context); - void *PR = (void*)signExtendPrel31(*data); - if (PR == (void*)&__gxx_personality_v0) { - *off = 1; // First byte is size data. - *len = (((data[1] >> 24) & 0xff) + 1) * 4; - } else + assert((*data & 0x80000000) != 0 && + "decode_eht_entry() does not support user-defined personality"); + + // 6.3: ARM Compact Model + // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded + // by format: + Descriptor::Format format = + static_cast((*data & 0x0f000000) >> 24); + switch (format) { + case Descriptor::SU16: + *len = 4; + *off = 1; + break; + case Descriptor::LU16: + case Descriptor::LU32: + *len = 4 + 4 * ((*data & 0x00ff0000) >> 16); + *off = 2; + break; + default: return nullptr; - data++; // Skip the first word, which is the prel31 offset. - } else { - // 6.3: ARM Compact Model - // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded - // by format: - Descriptor::Format format = - static_cast((*data & 0x0f000000) >> 24); - switch (format) { - case Descriptor::SU16: - *len = 4; - *off = 1; - break; - case Descriptor::LU16: - case Descriptor::LU32: - *len = 4 + 4 * ((*data & 0x00ff0000) >> 16); - *off = 2; - break; - default: - return nullptr; - } } - return data; } Index: src/Unwind/UnwindCursor.hpp =================================================================== --- src/Unwind/UnwindCursor.hpp +++ src/Unwind/UnwindCursor.hpp @@ -31,6 +31,10 @@ #include "CompactUnwinder.hpp" #include "config.h" +#if LIBCXXABI_ARM_EHABI +#include "Unwind-EHABI.h" +#endif + namespace libunwind { #if _LIBUNWIND_SUPPORT_DWARF_UNWIND @@ -605,20 +609,6 @@ uint32_t data; }; -// Unable to unwind in the ARM index table (section 5 EHABI). -#define UNW_EXIDX_CANTUNWIND 0x1 - -static inline uint32_t signExtendPrel31(uint32_t data) { - return data | ((data & 0x40000000u) << 1); -} - -extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr0( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); -extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr1( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); -extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr2( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); - template struct EHABISectionIterator { typedef EHABISectionIterator _Self; Index: src/Unwind/UnwindLevel1-gcc-ext.c =================================================================== --- src/Unwind/UnwindLevel1-gcc-ext.c +++ src/Unwind/UnwindLevel1-gcc-ext.c @@ -21,6 +21,10 @@ #include "libunwind_ext.h" #include "config.h" +#if LIBCXXABI_ARM_EHABI +#include "Unwind-EHABI.h" +#endif + #if _LIBUNWIND_BUILD_ZERO_COST_APIS /// Called by __cxa_rethrow(). @@ -99,7 +103,6 @@ return NULL; } - /// Walk every frame and call trace function at each one. If trace function /// returns anything other than _URC_NO_REASON, then walk is terminated. _LIBUNWIND_EXPORT _Unwind_Reason_Code @@ -132,17 +135,39 @@ } struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; - size_t off; - size_t len; const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info; - unwindInfo = decode_eht_entry(unwindInfo, &off, &len); - if (unwindInfo == NULL) { - return _URC_FAILURE; - } - - result = _Unwind_VRS_Interpret(context, unwindInfo, off, len); - if (result != _URC_CONTINUE_UNWIND) { - return _URC_END_OF_STACK; + if ((*unwindInfo & 0x80000000) == 0) { + // 6.2: Generic Model + // EHT entry is a prel31 pointing to the PR, followed by data understood + // only by the personality routine. Since EHABI doesn't guarantee the + // location or availability of the unwind opcodes in the generic model, + // we have to call personality functions with (_US_VIRTUAL_UNWIND_FRAME | + // _US_FORCE_UNWIND) state. + + // Create a mock exception object for force unwinding. + _Unwind_Exception ex; + ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0 + ex.pr_cache.fnstart = frameInfo.start_ip; + ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo; + ex.pr_cache.additional= frameInfo.flags; + + // Get and call the personality function to unwind the frame. + __personality_routine pr = (__personality_routine) readPrel31(unwindInfo); + if (pr(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) != + _URC_CONTINUE_UNWIND) { + return _URC_END_OF_STACK; + } + } else { + size_t off, len; + unwindInfo = decode_eht_entry(unwindInfo, &off, &len); + if (unwindInfo == NULL) { + return _URC_FAILURE; + } + + result = _Unwind_VRS_Interpret(context, unwindInfo, off, len); + if (result != _URC_CONTINUE_UNWIND) { + return _URC_END_OF_STACK; + } } #endif // LIBCXXABI_ARM_EHABI