summaryrefslogtreecommitdiff
path: root/src/Unwind/UnwindLevel1-gcc-ext.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Unwind/UnwindLevel1-gcc-ext.c')
-rw-r--r--src/Unwind/UnwindLevel1-gcc-ext.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/src/Unwind/UnwindLevel1-gcc-ext.c b/src/Unwind/UnwindLevel1-gcc-ext.c
index c119d57..8e2fdd6 100644
--- a/src/Unwind/UnwindLevel1-gcc-ext.c
+++ b/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 @@ _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
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 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
}
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