@@ -472,7 +472,9 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
472472 virtual void getInfo (unw_proc_info_t *) {
473473 _LIBUNWIND_ABORT (" getInfo not implemented" );
474474 }
475- virtual void jumpto () { _LIBUNWIND_ABORT (" jumpto not implemented" ); }
475+ _LIBUNWIND_TRACE_NO_INLINE virtual void jumpto () {
476+ _LIBUNWIND_ABORT (" jumpto not implemented" );
477+ }
476478 virtual bool isSignalFrame () {
477479 _LIBUNWIND_ABORT (" isSignalFrame not implemented" );
478480 }
@@ -489,6 +491,12 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
489491 virtual void saveVFPAsX () { _LIBUNWIND_ABORT (" saveVFPAsX not implemented" ); }
490492#endif
491493
494+ #ifdef _LIBUNWIND_TRACE_RET_INJECT
495+ virtual void setWalkedFrames (unsigned ) {
496+ _LIBUNWIND_ABORT (" setWalkedFrames not implemented" );
497+ }
498+ #endif
499+
492500#ifdef _AIX
493501 virtual uintptr_t getDataRelBase () {
494502 _LIBUNWIND_ABORT (" getDataRelBase not implemented" );
@@ -965,7 +973,8 @@ class UnwindCursor : public AbstractUnwindCursor{
965973 virtual void setFloatReg (int , unw_fpreg_t );
966974 virtual int step (bool stage2 = false );
967975 virtual void getInfo (unw_proc_info_t *);
968- virtual void jumpto ();
976+ _LIBUNWIND_TRACE_NO_INLINE
977+ virtual void jumpto ();
969978 virtual bool isSignalFrame ();
970979 virtual bool getFunctionName (char *buf, size_t len, unw_word_t *off);
971980 virtual void setInfoBasedOnIPRegister (bool isReturnAddress = false );
@@ -974,6 +983,10 @@ class UnwindCursor : public AbstractUnwindCursor{
974983 virtual void saveVFPAsX ();
975984#endif
976985
986+ #ifdef _LIBUNWIND_TRACE_RET_INJECT
987+ virtual void setWalkedFrames (unsigned );
988+ #endif
989+
977990#ifdef _AIX
978991 virtual uintptr_t getDataRelBase ();
979992#endif
@@ -1356,6 +1369,9 @@ class UnwindCursor : public AbstractUnwindCursor{
13561369 defined (_LIBUNWIND_TARGET_HAIKU)
13571370 bool _isSigReturn = false;
13581371#endif
1372+ #ifdef _LIBUNWIND_TRACE_RET_INJECT
1373+ uint32_t _walkedFrames;
1374+ #endif
13591375};
13601376
13611377
@@ -1410,7 +1426,46 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
14101426}
14111427
14121428template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
1429+ #ifdef _LIBUNWIND_TRACE_RET_INJECT
1430+ /*
1431+
1432+ The value of `_walkedFrames` is computed in `unwind_phase2` and represents the
1433+ number of frames walked starting `unwind_phase2` to get to the landing pad.
1434+
1435+ ```
1436+ // uc is initialized by __unw_getcontext in the parent frame.
1437+ // The first stack frame walked is unwind_phase2.
1438+ unsigned framesWalked = 1;
1439+ ```
1440+
1441+ To that, we need to add the number of function calls in libunwind between
1442+ `unwind_phase2` & `__libunwind_Registers_arm64_jumpto` which performs the long
1443+ jump, to rebalance the execution flow.
1444+
1445+ ```
1446+ frame #0: libunwind.1.dylib`__libunwind_Registers_arm64_jumpto at UnwindRegistersRestore.S:646
1447+ frame #1: libunwind.1.dylib`libunwind::Registers_arm64::returnto at Registers.hpp:2291:3
1448+ frame #2: libunwind.1.dylib`libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_arm64>::jumpto at UnwindCursor.hpp:1474:14
1449+ frame #3: libunwind.1.dylib`__unw_resume at libunwind.cpp:375:7
1450+ frame #4: libunwind.1.dylib`__unw_resume_with_frames_walked at libunwind.cpp:363:10
1451+ frame #5: libunwind.1.dylib`unwind_phase2 at UnwindLevel1.c:328:9
1452+ frame #6: libunwind.1.dylib`_Unwind_RaiseException at UnwindLevel1.c:480:10
1453+ frame #7: libc++abi.dylib`__cxa_throw at cxa_exception.cpp:295:5
1454+ ...
1455+ ```
1456+
1457+ If we look at the backtrace from `__libunwind_Registers_arm64_jumpto`, we see
1458+ there are 5 frames on the stack to reach `unwind_phase2`. However, only 4 of
1459+ them will never return, since `__libunwind_Registers_arm64_jumpto` returns
1460+ back to the landing pad, so we need to subtract 1 to the number of
1461+ `_EXTRA_LIBUNWIND_FRAMES_WALKED`.
1462+ */
1463+
1464+ static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1 ;
1465+ _registers.returnto (_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED);
1466+ #else
14131467 _registers.jumpto ();
1468+ #endif
14141469}
14151470
14161471#ifdef __arm__
@@ -1419,6 +1474,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
14191474}
14201475#endif
14211476
1477+ #ifdef _LIBUNWIND_TRACE_RET_INJECT
1478+ template <typename A, typename R>
1479+ void UnwindCursor<A, R>::setWalkedFrames(unsigned walkedFrames) {
1480+ _walkedFrames = walkedFrames;
1481+ }
1482+ #endif
1483+
14221484#ifdef _AIX
14231485template <typename A, typename R>
14241486uintptr_t UnwindCursor<A, R>::getDataRelBase() {
0 commit comments