diff options
Diffstat (limited to 'src/Unwind/Unwind-EHABI.cpp')
-rw-r--r-- | src/Unwind/Unwind-EHABI.cpp | 68 |
1 files changed, 24 insertions, 44 deletions
diff --git a/src/Unwind/Unwind-EHABI.cpp b/src/Unwind/Unwind-EHABI.cpp index a719b16..deed6f0 100644 --- a/src/Unwind/Unwind-EHABI.cpp +++ b/src/Unwind/Unwind-EHABI.cpp @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +#include "Unwind-EHABI.h" + #include <unwind.h> #include <stdbool.h> @@ -44,10 +46,6 @@ const char* getNextNibble(const char* data, uint32_t* out) { 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 @@ _Unwind_Reason_Code ProcessDescriptors( 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 @@ uint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) { */ 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<Descriptor::Format>((*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<Descriptor::Format>((*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; } |