Skip to content

Conversation

@sylvestre
Copy link
Collaborator

Reverts #165066
for causing
#167658

@llvmbot
Copy link
Member

llvmbot commented Nov 12, 2025

@llvm/pr-subscribers-lldb

Author: Sylvestre Ledru (sylvestre)

Changes

Reverts llvm/llvm-project#165066
for causing
#167658


Patch is 26.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/167659.diff

12 Files Affected:

  • (modified) libunwind/src/Registers.hpp (+4-12)
  • (modified) libunwind/src/UnwindCursor.hpp (+2-64)
  • (modified) libunwind/src/UnwindLevel1.c (+10-14)
  • (modified) libunwind/src/UnwindRegistersRestore.S (+1-14)
  • (modified) libunwind/src/assembly.h (-4)
  • (modified) libunwind/src/config.h (-9)
  • (modified) libunwind/src/libunwind.cpp (+1-21)
  • (modified) libunwind/src/libunwind_ext.h (+1-5)
  • (modified) lldb/packages/Python/lldbsuite/test/decorators.py (-25)
  • (removed) lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile (-6)
  • (removed) lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py (-177)
  • (removed) lldb/test/API/functionalities/unwind/libunwind_ret_injection/main.cpp (-45)
diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp
index 28649fafb23d5..9d4c8344150f6 100644
--- a/libunwind/src/Registers.hpp
+++ b/libunwind/src/Registers.hpp
@@ -1832,9 +1832,8 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
 /// Registers_arm64  holds the register state of a thread in a 64-bit arm
 /// process.
 class _LIBUNWIND_HIDDEN Registers_arm64;
+extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
 extern "C" int64_t __libunwind_Registers_arm64_za_disable();
-extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *,
-                                                   unsigned walkedFrames);
 
 #if defined(_LIBUNWIND_USE_GCS)
 extern "C" void *__libunwind_shstk_get_jump_target() {
@@ -1862,17 +1861,10 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
   static const char *getRegisterName(int num);
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  _LIBUNWIND_TRACE_NO_INLINE
-    void      returnto(unsigned walkedFrames) {
-      __libunwind_Registers_arm64_jumpto(this, walkedFrames);
-    }
-#else
-  void        jumpto() {
-      zaDisable();
-      __libunwind_Registers_arm64_jumpto(this, 0);
+  void jumpto() {
+    zaDisable();
+    __libunwind_Registers_arm64_jumpto(this);
   }
-#endif
   static constexpr int lastDwarfRegNum() {
     return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
   }
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index d7348254af07b..7ec5f9e91578a 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -472,9 +472,7 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
   virtual void getInfo(unw_proc_info_t *) {
     _LIBUNWIND_ABORT("getInfo not implemented");
   }
-  _LIBUNWIND_TRACE_NO_INLINE virtual void jumpto() {
-    _LIBUNWIND_ABORT("jumpto not implemented");
-  }
+  virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
   virtual bool isSignalFrame() {
     _LIBUNWIND_ABORT("isSignalFrame not implemented");
   }
@@ -491,12 +489,6 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
   virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
 #endif
 
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  virtual void setWalkedFrames(unsigned) {
-    _LIBUNWIND_ABORT("setWalkedFrames not implemented");
-  }
-#endif
-
 #ifdef _AIX
   virtual uintptr_t getDataRelBase() {
     _LIBUNWIND_ABORT("getDataRelBase not implemented");
@@ -973,8 +965,7 @@ class UnwindCursor : public AbstractUnwindCursor{
   virtual void        setFloatReg(int, unw_fpreg_t);
   virtual int         step(bool stage2 = false);
   virtual void        getInfo(unw_proc_info_t *);
-  _LIBUNWIND_TRACE_NO_INLINE
-    virtual void      jumpto();
+  virtual void        jumpto();
   virtual bool        isSignalFrame();
   virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
   virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
@@ -983,10 +974,6 @@ class UnwindCursor : public AbstractUnwindCursor{
   virtual void        saveVFPAsX();
 #endif
 
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  virtual void setWalkedFrames(unsigned);
-#endif
-
 #ifdef _AIX
   virtual uintptr_t getDataRelBase();
 #endif
@@ -1369,9 +1356,6 @@ class UnwindCursor : public AbstractUnwindCursor{
     defined(_LIBUNWIND_TARGET_HAIKU)
   bool             _isSigReturn = false;
 #endif
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  uint32_t _walkedFrames;
-#endif
 };
 
 
@@ -1426,46 +1410,7 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
 }
 
 template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  /*
-
-  The value of `_walkedFrames` is computed in `unwind_phase2` and represents the
-  number of frames walked starting `unwind_phase2` to get to the landing pad.
-
-  ```
-    // uc is initialized by __unw_getcontext in the parent frame.
-    // The first stack frame walked is unwind_phase2.
-    unsigned framesWalked = 1;
-  ```
-
-  To that, we need to add the number of function calls in libunwind between
-  `unwind_phase2` & `__libunwind_Registers_arm64_jumpto` which performs the long
-  jump, to rebalance the execution flow.
-
-  ```
-      frame #0: libunwind.1.dylib`__libunwind_Registers_arm64_jumpto at UnwindRegistersRestore.S:646
-      frame #1: libunwind.1.dylib`libunwind::Registers_arm64::returnto at Registers.hpp:2291:3
-      frame #2: libunwind.1.dylib`libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_arm64>::jumpto at UnwindCursor.hpp:1474:14
-      frame #3: libunwind.1.dylib`__unw_resume at libunwind.cpp:375:7
-      frame #4: libunwind.1.dylib`__unw_resume_with_frames_walked at libunwind.cpp:363:10
-      frame #5: libunwind.1.dylib`unwind_phase2 at UnwindLevel1.c:328:9
-      frame #6: libunwind.1.dylib`_Unwind_RaiseException at UnwindLevel1.c:480:10
-      frame #7: libc++abi.dylib`__cxa_throw at cxa_exception.cpp:295:5
-      ...
-  ```
-
-  If we look at the backtrace from `__libunwind_Registers_arm64_jumpto`, we see
-  there are 5 frames on the stack to reach `unwind_phase2`. However, only 4 of
-  them will never return, since `__libunwind_Registers_arm64_jumpto` returns
-  back to the landing pad, so we need to subtract 1 to the number of
-  `_EXTRA_LIBUNWIND_FRAMES_WALKED`.
-  */
-
-  static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1;
-  _registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED);
-#else
   _registers.jumpto();
-#endif
 }
 
 #ifdef __arm__
@@ -1474,13 +1419,6 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
 }
 #endif
 
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-template <typename A, typename R>
-void UnwindCursor<A, R>::setWalkedFrames(unsigned walkedFrames) {
-  _walkedFrames = walkedFrames;
-}
-#endif
-
 #ifdef _AIX
 template <typename A, typename R>
 uintptr_t UnwindCursor<A, R>::getDataRelBase() {
diff --git a/libunwind/src/UnwindLevel1.c b/libunwind/src/UnwindLevel1.c
index 79398bac8b531..b0cd60dfb9141 100644
--- a/libunwind/src/UnwindLevel1.c
+++ b/libunwind/src/UnwindLevel1.c
@@ -48,15 +48,16 @@
 // avoided when invoking the `jumpto()` function. To do this, we use inline
 // assemblies to "goto" the `jumpto()` for these architectures.
 #if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)
-#define __unw_phase2_resume(cursor, payload)                                   \
+#define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
-    __unw_resume_with_frames_walked((cursor), (payload));                      \
+    (void)fn;                                                                  \
+    __unw_resume((cursor));                                                    \
   } while (0)
 #elif defined(_LIBUNWIND_TARGET_I386)
 #define __shstk_step_size (4)
-#define __unw_phase2_resume(cursor, payload)                                   \
+#define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
-    _LIBUNWIND_POP_SHSTK_SSP((payload));                                       \
+    _LIBUNWIND_POP_SHSTK_SSP((fn));                                            \
     void *shstkRegContext = __libunwind_shstk_get_registers((cursor));         \
     void *shstkJumpAddress = __libunwind_shstk_get_jump_target();              \
     __asm__ volatile("push %%edi\n\t"                                          \
@@ -66,9 +67,9 @@
   } while (0)
 #elif defined(_LIBUNWIND_TARGET_X86_64)
 #define __shstk_step_size (8)
-#define __unw_phase2_resume(cursor, payload)                                   \
+#define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
-    _LIBUNWIND_POP_SHSTK_SSP((payload));                                       \
+    _LIBUNWIND_POP_SHSTK_SSP((fn));                                            \
     void *shstkRegContext = __libunwind_shstk_get_registers((cursor));         \
     void *shstkJumpAddress = __libunwind_shstk_get_jump_target();              \
     __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext),                 \
@@ -76,17 +77,16 @@
   } while (0)
 #elif defined(_LIBUNWIND_TARGET_AARCH64)
 #define __shstk_step_size (8)
-#define __unw_phase2_resume(cursor, payload)                                   \
+#define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
-    _LIBUNWIND_POP_SHSTK_SSP((payload));                                       \
+    _LIBUNWIND_POP_SHSTK_SSP((fn));                                            \
     void *shstkRegContext = __libunwind_shstk_get_registers((cursor));         \
     void *shstkJumpAddress = __libunwind_shstk_get_jump_target();              \
     __asm__ volatile("mov x0, %0\n\t"                                          \
-                     "mov x1, wzr\n\t"                                         \
                      "br %1\n\t"                                               \
                      :                                                         \
                      : "r"(shstkRegContext), "r"(shstkJumpAddress)             \
-                     : "x0", "x1");                                            \
+                     : "x0");                                                  \
   } while (0)
 #endif
 
@@ -205,8 +205,6 @@ extern int __unw_step_stage2(unw_cursor_t *);
 #if defined(_LIBUNWIND_USE_GCS)
 // Enable the GCS target feature to permit gcspop instructions to be used.
 __attribute__((target("+gcs")))
-#else
-_LIBUNWIND_TRACE_NO_INLINE
 #endif
 static _Unwind_Reason_Code
 unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
@@ -351,8 +349,6 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
 #if defined(_LIBUNWIND_USE_GCS)
 // Enable the GCS target feature to permit gcspop instructions to be used.
 __attribute__((target("+gcs")))
-#else
-_LIBUNWIND_TRACE_NO_INLINE
 #endif
 static _Unwind_Reason_Code
 unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S
index 76a80344034f7..fd306ed8c5230 100644
--- a/libunwind/src/UnwindRegistersRestore.S
+++ b/libunwind/src/UnwindRegistersRestore.S
@@ -645,26 +645,13 @@ Lnovec:
 #endif
 
 //
-// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *, unsigned);
+// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
 //
 // On entry:
 //  thread_state pointer is in x0
-//  walked_frames counter is in x1
 //
   .p2align 2
 DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
-
-  #if defined(_LIBUNWIND_TRACE_RET_INJECT)
-    cbz     w1, 1f
-  0:
-    subs    w1, w1, #1
-    adr     x16, #8
-    ret     x16
-
-    b.ne    0b
-  1:
-  #endif
-
   // skip restore of x0,x1 for now
   ldp    x2, x3,  [x0, #0x010]
   ldp    x4, x5,  [x0, #0x020]
diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h
index 84c9d526f1d75..f0fcd006f2073 100644
--- a/libunwind/src/assembly.h
+++ b/libunwind/src/assembly.h
@@ -132,10 +132,6 @@
 
 #if defined(__APPLE__)
 
-#if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
-#define _LIBUNWIND_TRACE_RET_INJECT 1
-#endif
-
 #define SYMBOL_IS_FUNC(name)
 #define HIDDEN_SYMBOL(name) .private_extern name
 #if defined(_LIBUNWIND_HIDE_SYMBOLS)
diff --git a/libunwind/src/config.h b/libunwind/src/config.h
index f017403fa2234..deb5a4d4d73d4 100644
--- a/libunwind/src/config.h
+++ b/libunwind/src/config.h
@@ -28,9 +28,6 @@
     #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
   #endif
-  #if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
-    #define _LIBUNWIND_TRACE_RET_INJECT 1
-  #endif
 #elif defined(_WIN32)
   #ifdef __SEH__
     #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
@@ -64,12 +61,6 @@
   #endif
 #endif
 
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-#define _LIBUNWIND_TRACE_NO_INLINE __attribute__((noinline, disable_tail_calls))
-#else
-#define _LIBUNWIND_TRACE_NO_INLINE
-#endif
-
 #if defined(_LIBUNWIND_HIDE_SYMBOLS)
   // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility.
   #define _LIBUNWIND_EXPORT
diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp
index b3036396c379d..4f6fed1cd933a 100644
--- a/libunwind/src/libunwind.cpp
+++ b/libunwind/src/libunwind.cpp
@@ -247,27 +247,7 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor,
 }
 _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info)
 
-/// Rebalance the execution flow by injecting the right amount of `ret`
-/// instruction relatively to the amount of `walkedFrames` then resume execution
-/// at cursor position (aka longjump).
-_LIBUNWIND_HIDDEN int __unw_resume_with_frames_walked(unw_cursor_t *cursor,
-                                                      unsigned walkedFrames) {
-  _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p, walkedFrames=%u)",
-                       static_cast<void *>(cursor), walkedFrames);
-#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
-  // Inform the ASan runtime that now might be a good time to clean stuff up.
-  __asan_handle_no_return();
-#endif
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
-  co->setWalkedFrames(walkedFrames);
-#endif
-  return __unw_resume(cursor);
-}
-_LIBUNWIND_WEAK_ALIAS(__unw_resume_with_frames_walked,
-                      unw_resume_with_frames_walked)
-
-/// Legacy function. Resume execution at cursor position (aka longjump).
+/// Resume execution at cursor position (aka longjump).
 _LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) {
   _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor));
 #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
diff --git a/libunwind/src/libunwind_ext.h b/libunwind/src/libunwind_ext.h
index f5da90d7bd3b7..ed503ceb70c5a 100644
--- a/libunwind/src/libunwind_ext.h
+++ b/libunwind/src/libunwind_ext.h
@@ -30,11 +30,7 @@ extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *);
 extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
 extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t);
 extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t);
-_LIBUNWIND_TRACE_NO_INLINE
-  extern int __unw_resume_with_frames_walked(unw_cursor_t *, unsigned);
-// `__unw_resume` is a legacy function. Use `__unw_resume_with_frames_walked` instead.
-_LIBUNWIND_TRACE_NO_INLINE
-  extern int __unw_resume(unw_cursor_t *);
+extern int __unw_resume(unw_cursor_t *);
 
 #ifdef __arm__
 /* Save VFP registers in FSTMX format (instead of FSTMD). */
diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py
index 23d2165e07f7e..454196e1b0264 100644
--- a/lldb/packages/Python/lldbsuite/test/decorators.py
+++ b/lldb/packages/Python/lldbsuite/test/decorators.py
@@ -647,31 +647,6 @@ def is_out_of_tree_debugserver():
     return skipTestIfFn(is_out_of_tree_debugserver)(func)
 
 
-def skipIfOutOfTreeLibunwind(func):
-    """Decorate the item to skip tests if libunwind was not built in-tree."""
-
-    def is_out_of_tree_libunwind():
-        if not configuration.llvm_tools_dir:
-            return "out-of-tree libunwind"
-
-        # llvm_tools_dir is typically <build>/bin, so lib is a sibling.
-        llvm_lib_dir = os.path.join(
-            os.path.dirname(configuration.llvm_tools_dir), "lib"
-        )
-
-        if not os.path.isdir(llvm_lib_dir):
-            return "out-of-tree libunwind"
-
-        # Check for libunwind library (any extension).
-        for filename in os.listdir(llvm_lib_dir):
-            if filename.startswith("libunwind.") or filename.startswith("unwind."):
-                return None
-
-        return "out-of-tree libunwind"
-
-    return skipTestIfFn(is_out_of_tree_libunwind)(func)
-
-
 def skipIfRemote(func):
     """Decorate the item to skip tests if testing remotely."""
     return unittest.skipIf(lldb.remote_platform, "skip on remote platform")(func)
diff --git a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile
deleted file mode 100644
index 4698eaa815b83..0000000000000
--- a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-CXX_SOURCES := main.cpp
-
-# Build with C++ exceptions enabled
-CXXFLAGS := -g -O0 -fexceptions
-
-include Makefile.rules
diff --git a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py
deleted file mode 100644
index e03234d1b5077..0000000000000
--- a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py
+++ /dev/null
@@ -1,177 +0,0 @@
-"""
-Test that libunwind correctly injects 'ret' instructions to rebalance execution flow
-when unwinding C++ exceptions. This is important for Apple Processor Trace analysis.
-"""
-
-import lldb
-import os
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-from lldbsuite.test import configuration
-
-
-class LibunwindRetInjectionTestCase(TestBase):
-    @skipIf(archs=no_match(["arm64", "arm64e", "aarch64"]))
-    @skipUnlessDarwin
-    @skipIfOutOfTreeLibunwind
-    def test_ret_injection_on_exception_unwind(self):
-        """Test that __libunwind_Registers_arm64_jumpto receives correct walkedFrames count and injects the right number of ret instructions."""
-        self.build()
-
-        exe = self.getBuildArtifact("a.out")
-        target = self.dbg.CreateTarget(exe)
-        self.assertTrue(target, VALID_TARGET)
-
-        # Find the just-built libunwind, not the system one.
-        # llvm_tools_dir is typically <build>/bin, so lib is a sibling.
-        self.assertIsNotNone(
-            configuration.llvm_tools_dir,
-            "llvm_tools_dir must be set to find in-tree libunwind",
-        )
-
-        llvm_lib_dir = os.path.join(
-            os.path.dirname(configuration.llvm_tools_dir), "lib"
-        )
-
-        # Find the libunwind library (platform-agnostic).
-        libunwind_path = None
-        for filename in os.listdir(llvm_lib_dir):
-            if filename.startswith("libunwind.") or filename.startswith("unwind."):
-                libunwind_path = os.path.join(llvm_lib_dir, filename)
-                break
-
-        self.assertIsNotNone(
-            libunwind_path, f"Could not find libunwind in {llvm_lib_dir}"
-        )
-
-        # Set breakpoint in __libunwind_Registers_arm64_jumpto.
-        # This is the function that performs the actual jump and ret injection.
-        bp = target.BreakpointCreateByName("__libunwind_Registers_arm64_jumpto")
-        self.assertTrue(bp.IsValid())
-        self.assertGreater(bp.GetNumLocations(), 0)
-
-        # Set up DYLD_INSERT_LIBRARIES to use the just-built libunwind.
-        launch_info = lldb.SBLaunchInfo(None)
-        env = target.GetEnvironment()
-        env.Set("DYLD_INSERT_LIBRARIES", libunwind_path, True)
-        launch_info.SetEnvironment(env, False)
-
-        # Launch the process with our custom libunwind.
-        error = lldb.SBError()
-        process = target.Launch(launch_info, error)
-        self.assertSuccess(
-            error, f"Failed to launch process with libunwind at {libunwind_path}"
-        )
-        self.assertTrue(process, PROCESS_IS_VALID)
-
-        # We should hit the breakpoint in __libunwind_Registers_arm64_jumpto
-        # during the exception unwinding phase 2.
-        threads = lldbutil.get_threads_stopped_at_breakpoint(process, bp)
-        self.assertEqual(len(threads), 1, "Should have stopped at breakpoint")
-
-        thread = threads[0]
-        frame = thread.GetFrameAtIndex(0)
-
-        # Verify we're in __libunwind_Registers_arm64_jumpto.
-        function_name = frame.GetFunctionName()
-     ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Nov 12, 2025

@llvm/pr-subscribers-libunwind

Author: Sylvestre Ledru (sylvestre)

Changes

Reverts llvm/llvm-project#165066
for causing
#167658


Patch is 26.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/167659.diff

12 Files Affected:

  • (modified) libunwind/src/Registers.hpp (+4-12)
  • (modified) libunwind/src/UnwindCursor.hpp (+2-64)
  • (modified) libunwind/src/UnwindLevel1.c (+10-14)
  • (modified) libunwind/src/UnwindRegistersRestore.S (+1-14)
  • (modified) libunwind/src/assembly.h (-4)
  • (modified) libunwind/src/config.h (-9)
  • (modified) libunwind/src/libunwind.cpp (+1-21)
  • (modified) libunwind/src/libunwind_ext.h (+1-5)
  • (modified) lldb/packages/Python/lldbsuite/test/decorators.py (-25)
  • (removed) lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile (-6)
  • (removed) lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py (-177)
  • (removed) lldb/test/API/functionalities/unwind/libunwind_ret_injection/main.cpp (-45)
diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp
index 28649fafb23d5..9d4c8344150f6 100644
--- a/libunwind/src/Registers.hpp
+++ b/libunwind/src/Registers.hpp
@@ -1832,9 +1832,8 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
 /// Registers_arm64  holds the register state of a thread in a 64-bit arm
 /// process.
 class _LIBUNWIND_HIDDEN Registers_arm64;
+extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
 extern "C" int64_t __libunwind_Registers_arm64_za_disable();
-extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *,
-                                                   unsigned walkedFrames);
 
 #if defined(_LIBUNWIND_USE_GCS)
 extern "C" void *__libunwind_shstk_get_jump_target() {
@@ -1862,17 +1861,10 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
   v128        getVectorRegister(int num) const;
   void        setVectorRegister(int num, v128 value);
   static const char *getRegisterName(int num);
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  _LIBUNWIND_TRACE_NO_INLINE
-    void      returnto(unsigned walkedFrames) {
-      __libunwind_Registers_arm64_jumpto(this, walkedFrames);
-    }
-#else
-  void        jumpto() {
-      zaDisable();
-      __libunwind_Registers_arm64_jumpto(this, 0);
+  void jumpto() {
+    zaDisable();
+    __libunwind_Registers_arm64_jumpto(this);
   }
-#endif
   static constexpr int lastDwarfRegNum() {
     return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
   }
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index d7348254af07b..7ec5f9e91578a 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -472,9 +472,7 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
   virtual void getInfo(unw_proc_info_t *) {
     _LIBUNWIND_ABORT("getInfo not implemented");
   }
-  _LIBUNWIND_TRACE_NO_INLINE virtual void jumpto() {
-    _LIBUNWIND_ABORT("jumpto not implemented");
-  }
+  virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
   virtual bool isSignalFrame() {
     _LIBUNWIND_ABORT("isSignalFrame not implemented");
   }
@@ -491,12 +489,6 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
   virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
 #endif
 
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  virtual void setWalkedFrames(unsigned) {
-    _LIBUNWIND_ABORT("setWalkedFrames not implemented");
-  }
-#endif
-
 #ifdef _AIX
   virtual uintptr_t getDataRelBase() {
     _LIBUNWIND_ABORT("getDataRelBase not implemented");
@@ -973,8 +965,7 @@ class UnwindCursor : public AbstractUnwindCursor{
   virtual void        setFloatReg(int, unw_fpreg_t);
   virtual int         step(bool stage2 = false);
   virtual void        getInfo(unw_proc_info_t *);
-  _LIBUNWIND_TRACE_NO_INLINE
-    virtual void      jumpto();
+  virtual void        jumpto();
   virtual bool        isSignalFrame();
   virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
   virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
@@ -983,10 +974,6 @@ class UnwindCursor : public AbstractUnwindCursor{
   virtual void        saveVFPAsX();
 #endif
 
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  virtual void setWalkedFrames(unsigned);
-#endif
-
 #ifdef _AIX
   virtual uintptr_t getDataRelBase();
 #endif
@@ -1369,9 +1356,6 @@ class UnwindCursor : public AbstractUnwindCursor{
     defined(_LIBUNWIND_TARGET_HAIKU)
   bool             _isSigReturn = false;
 #endif
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  uint32_t _walkedFrames;
-#endif
 };
 
 
@@ -1426,46 +1410,7 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
 }
 
 template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  /*
-
-  The value of `_walkedFrames` is computed in `unwind_phase2` and represents the
-  number of frames walked starting `unwind_phase2` to get to the landing pad.
-
-  ```
-    // uc is initialized by __unw_getcontext in the parent frame.
-    // The first stack frame walked is unwind_phase2.
-    unsigned framesWalked = 1;
-  ```
-
-  To that, we need to add the number of function calls in libunwind between
-  `unwind_phase2` & `__libunwind_Registers_arm64_jumpto` which performs the long
-  jump, to rebalance the execution flow.
-
-  ```
-      frame #0: libunwind.1.dylib`__libunwind_Registers_arm64_jumpto at UnwindRegistersRestore.S:646
-      frame #1: libunwind.1.dylib`libunwind::Registers_arm64::returnto at Registers.hpp:2291:3
-      frame #2: libunwind.1.dylib`libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_arm64>::jumpto at UnwindCursor.hpp:1474:14
-      frame #3: libunwind.1.dylib`__unw_resume at libunwind.cpp:375:7
-      frame #4: libunwind.1.dylib`__unw_resume_with_frames_walked at libunwind.cpp:363:10
-      frame #5: libunwind.1.dylib`unwind_phase2 at UnwindLevel1.c:328:9
-      frame #6: libunwind.1.dylib`_Unwind_RaiseException at UnwindLevel1.c:480:10
-      frame #7: libc++abi.dylib`__cxa_throw at cxa_exception.cpp:295:5
-      ...
-  ```
-
-  If we look at the backtrace from `__libunwind_Registers_arm64_jumpto`, we see
-  there are 5 frames on the stack to reach `unwind_phase2`. However, only 4 of
-  them will never return, since `__libunwind_Registers_arm64_jumpto` returns
-  back to the landing pad, so we need to subtract 1 to the number of
-  `_EXTRA_LIBUNWIND_FRAMES_WALKED`.
-  */
-
-  static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1;
-  _registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED);
-#else
   _registers.jumpto();
-#endif
 }
 
 #ifdef __arm__
@@ -1474,13 +1419,6 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
 }
 #endif
 
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-template <typename A, typename R>
-void UnwindCursor<A, R>::setWalkedFrames(unsigned walkedFrames) {
-  _walkedFrames = walkedFrames;
-}
-#endif
-
 #ifdef _AIX
 template <typename A, typename R>
 uintptr_t UnwindCursor<A, R>::getDataRelBase() {
diff --git a/libunwind/src/UnwindLevel1.c b/libunwind/src/UnwindLevel1.c
index 79398bac8b531..b0cd60dfb9141 100644
--- a/libunwind/src/UnwindLevel1.c
+++ b/libunwind/src/UnwindLevel1.c
@@ -48,15 +48,16 @@
 // avoided when invoking the `jumpto()` function. To do this, we use inline
 // assemblies to "goto" the `jumpto()` for these architectures.
 #if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)
-#define __unw_phase2_resume(cursor, payload)                                   \
+#define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
-    __unw_resume_with_frames_walked((cursor), (payload));                      \
+    (void)fn;                                                                  \
+    __unw_resume((cursor));                                                    \
   } while (0)
 #elif defined(_LIBUNWIND_TARGET_I386)
 #define __shstk_step_size (4)
-#define __unw_phase2_resume(cursor, payload)                                   \
+#define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
-    _LIBUNWIND_POP_SHSTK_SSP((payload));                                       \
+    _LIBUNWIND_POP_SHSTK_SSP((fn));                                            \
     void *shstkRegContext = __libunwind_shstk_get_registers((cursor));         \
     void *shstkJumpAddress = __libunwind_shstk_get_jump_target();              \
     __asm__ volatile("push %%edi\n\t"                                          \
@@ -66,9 +67,9 @@
   } while (0)
 #elif defined(_LIBUNWIND_TARGET_X86_64)
 #define __shstk_step_size (8)
-#define __unw_phase2_resume(cursor, payload)                                   \
+#define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
-    _LIBUNWIND_POP_SHSTK_SSP((payload));                                       \
+    _LIBUNWIND_POP_SHSTK_SSP((fn));                                            \
     void *shstkRegContext = __libunwind_shstk_get_registers((cursor));         \
     void *shstkJumpAddress = __libunwind_shstk_get_jump_target();              \
     __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext),                 \
@@ -76,17 +77,16 @@
   } while (0)
 #elif defined(_LIBUNWIND_TARGET_AARCH64)
 #define __shstk_step_size (8)
-#define __unw_phase2_resume(cursor, payload)                                   \
+#define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
-    _LIBUNWIND_POP_SHSTK_SSP((payload));                                       \
+    _LIBUNWIND_POP_SHSTK_SSP((fn));                                            \
     void *shstkRegContext = __libunwind_shstk_get_registers((cursor));         \
     void *shstkJumpAddress = __libunwind_shstk_get_jump_target();              \
     __asm__ volatile("mov x0, %0\n\t"                                          \
-                     "mov x1, wzr\n\t"                                         \
                      "br %1\n\t"                                               \
                      :                                                         \
                      : "r"(shstkRegContext), "r"(shstkJumpAddress)             \
-                     : "x0", "x1");                                            \
+                     : "x0");                                                  \
   } while (0)
 #endif
 
@@ -205,8 +205,6 @@ extern int __unw_step_stage2(unw_cursor_t *);
 #if defined(_LIBUNWIND_USE_GCS)
 // Enable the GCS target feature to permit gcspop instructions to be used.
 __attribute__((target("+gcs")))
-#else
-_LIBUNWIND_TRACE_NO_INLINE
 #endif
 static _Unwind_Reason_Code
 unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
@@ -351,8 +349,6 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
 #if defined(_LIBUNWIND_USE_GCS)
 // Enable the GCS target feature to permit gcspop instructions to be used.
 __attribute__((target("+gcs")))
-#else
-_LIBUNWIND_TRACE_NO_INLINE
 #endif
 static _Unwind_Reason_Code
 unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S
index 76a80344034f7..fd306ed8c5230 100644
--- a/libunwind/src/UnwindRegistersRestore.S
+++ b/libunwind/src/UnwindRegistersRestore.S
@@ -645,26 +645,13 @@ Lnovec:
 #endif
 
 //
-// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *, unsigned);
+// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
 //
 // On entry:
 //  thread_state pointer is in x0
-//  walked_frames counter is in x1
 //
   .p2align 2
 DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
-
-  #if defined(_LIBUNWIND_TRACE_RET_INJECT)
-    cbz     w1, 1f
-  0:
-    subs    w1, w1, #1
-    adr     x16, #8
-    ret     x16
-
-    b.ne    0b
-  1:
-  #endif
-
   // skip restore of x0,x1 for now
   ldp    x2, x3,  [x0, #0x010]
   ldp    x4, x5,  [x0, #0x020]
diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h
index 84c9d526f1d75..f0fcd006f2073 100644
--- a/libunwind/src/assembly.h
+++ b/libunwind/src/assembly.h
@@ -132,10 +132,6 @@
 
 #if defined(__APPLE__)
 
-#if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
-#define _LIBUNWIND_TRACE_RET_INJECT 1
-#endif
-
 #define SYMBOL_IS_FUNC(name)
 #define HIDDEN_SYMBOL(name) .private_extern name
 #if defined(_LIBUNWIND_HIDE_SYMBOLS)
diff --git a/libunwind/src/config.h b/libunwind/src/config.h
index f017403fa2234..deb5a4d4d73d4 100644
--- a/libunwind/src/config.h
+++ b/libunwind/src/config.h
@@ -28,9 +28,6 @@
     #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
   #endif
-  #if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
-    #define _LIBUNWIND_TRACE_RET_INJECT 1
-  #endif
 #elif defined(_WIN32)
   #ifdef __SEH__
     #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
@@ -64,12 +61,6 @@
   #endif
 #endif
 
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-#define _LIBUNWIND_TRACE_NO_INLINE __attribute__((noinline, disable_tail_calls))
-#else
-#define _LIBUNWIND_TRACE_NO_INLINE
-#endif
-
 #if defined(_LIBUNWIND_HIDE_SYMBOLS)
   // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility.
   #define _LIBUNWIND_EXPORT
diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp
index b3036396c379d..4f6fed1cd933a 100644
--- a/libunwind/src/libunwind.cpp
+++ b/libunwind/src/libunwind.cpp
@@ -247,27 +247,7 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor,
 }
 _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info)
 
-/// Rebalance the execution flow by injecting the right amount of `ret`
-/// instruction relatively to the amount of `walkedFrames` then resume execution
-/// at cursor position (aka longjump).
-_LIBUNWIND_HIDDEN int __unw_resume_with_frames_walked(unw_cursor_t *cursor,
-                                                      unsigned walkedFrames) {
-  _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p, walkedFrames=%u)",
-                       static_cast<void *>(cursor), walkedFrames);
-#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
-  // Inform the ASan runtime that now might be a good time to clean stuff up.
-  __asan_handle_no_return();
-#endif
-#ifdef _LIBUNWIND_TRACE_RET_INJECT
-  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
-  co->setWalkedFrames(walkedFrames);
-#endif
-  return __unw_resume(cursor);
-}
-_LIBUNWIND_WEAK_ALIAS(__unw_resume_with_frames_walked,
-                      unw_resume_with_frames_walked)
-
-/// Legacy function. Resume execution at cursor position (aka longjump).
+/// Resume execution at cursor position (aka longjump).
 _LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) {
   _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor));
 #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
diff --git a/libunwind/src/libunwind_ext.h b/libunwind/src/libunwind_ext.h
index f5da90d7bd3b7..ed503ceb70c5a 100644
--- a/libunwind/src/libunwind_ext.h
+++ b/libunwind/src/libunwind_ext.h
@@ -30,11 +30,7 @@ extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *);
 extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
 extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t);
 extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t);
-_LIBUNWIND_TRACE_NO_INLINE
-  extern int __unw_resume_with_frames_walked(unw_cursor_t *, unsigned);
-// `__unw_resume` is a legacy function. Use `__unw_resume_with_frames_walked` instead.
-_LIBUNWIND_TRACE_NO_INLINE
-  extern int __unw_resume(unw_cursor_t *);
+extern int __unw_resume(unw_cursor_t *);
 
 #ifdef __arm__
 /* Save VFP registers in FSTMX format (instead of FSTMD). */
diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py
index 23d2165e07f7e..454196e1b0264 100644
--- a/lldb/packages/Python/lldbsuite/test/decorators.py
+++ b/lldb/packages/Python/lldbsuite/test/decorators.py
@@ -647,31 +647,6 @@ def is_out_of_tree_debugserver():
     return skipTestIfFn(is_out_of_tree_debugserver)(func)
 
 
-def skipIfOutOfTreeLibunwind(func):
-    """Decorate the item to skip tests if libunwind was not built in-tree."""
-
-    def is_out_of_tree_libunwind():
-        if not configuration.llvm_tools_dir:
-            return "out-of-tree libunwind"
-
-        # llvm_tools_dir is typically <build>/bin, so lib is a sibling.
-        llvm_lib_dir = os.path.join(
-            os.path.dirname(configuration.llvm_tools_dir), "lib"
-        )
-
-        if not os.path.isdir(llvm_lib_dir):
-            return "out-of-tree libunwind"
-
-        # Check for libunwind library (any extension).
-        for filename in os.listdir(llvm_lib_dir):
-            if filename.startswith("libunwind.") or filename.startswith("unwind."):
-                return None
-
-        return "out-of-tree libunwind"
-
-    return skipTestIfFn(is_out_of_tree_libunwind)(func)
-
-
 def skipIfRemote(func):
     """Decorate the item to skip tests if testing remotely."""
     return unittest.skipIf(lldb.remote_platform, "skip on remote platform")(func)
diff --git a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile
deleted file mode 100644
index 4698eaa815b83..0000000000000
--- a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-CXX_SOURCES := main.cpp
-
-# Build with C++ exceptions enabled
-CXXFLAGS := -g -O0 -fexceptions
-
-include Makefile.rules
diff --git a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py
deleted file mode 100644
index e03234d1b5077..0000000000000
--- a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py
+++ /dev/null
@@ -1,177 +0,0 @@
-"""
-Test that libunwind correctly injects 'ret' instructions to rebalance execution flow
-when unwinding C++ exceptions. This is important for Apple Processor Trace analysis.
-"""
-
-import lldb
-import os
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-from lldbsuite.test import configuration
-
-
-class LibunwindRetInjectionTestCase(TestBase):
-    @skipIf(archs=no_match(["arm64", "arm64e", "aarch64"]))
-    @skipUnlessDarwin
-    @skipIfOutOfTreeLibunwind
-    def test_ret_injection_on_exception_unwind(self):
-        """Test that __libunwind_Registers_arm64_jumpto receives correct walkedFrames count and injects the right number of ret instructions."""
-        self.build()
-
-        exe = self.getBuildArtifact("a.out")
-        target = self.dbg.CreateTarget(exe)
-        self.assertTrue(target, VALID_TARGET)
-
-        # Find the just-built libunwind, not the system one.
-        # llvm_tools_dir is typically <build>/bin, so lib is a sibling.
-        self.assertIsNotNone(
-            configuration.llvm_tools_dir,
-            "llvm_tools_dir must be set to find in-tree libunwind",
-        )
-
-        llvm_lib_dir = os.path.join(
-            os.path.dirname(configuration.llvm_tools_dir), "lib"
-        )
-
-        # Find the libunwind library (platform-agnostic).
-        libunwind_path = None
-        for filename in os.listdir(llvm_lib_dir):
-            if filename.startswith("libunwind.") or filename.startswith("unwind."):
-                libunwind_path = os.path.join(llvm_lib_dir, filename)
-                break
-
-        self.assertIsNotNone(
-            libunwind_path, f"Could not find libunwind in {llvm_lib_dir}"
-        )
-
-        # Set breakpoint in __libunwind_Registers_arm64_jumpto.
-        # This is the function that performs the actual jump and ret injection.
-        bp = target.BreakpointCreateByName("__libunwind_Registers_arm64_jumpto")
-        self.assertTrue(bp.IsValid())
-        self.assertGreater(bp.GetNumLocations(), 0)
-
-        # Set up DYLD_INSERT_LIBRARIES to use the just-built libunwind.
-        launch_info = lldb.SBLaunchInfo(None)
-        env = target.GetEnvironment()
-        env.Set("DYLD_INSERT_LIBRARIES", libunwind_path, True)
-        launch_info.SetEnvironment(env, False)
-
-        # Launch the process with our custom libunwind.
-        error = lldb.SBError()
-        process = target.Launch(launch_info, error)
-        self.assertSuccess(
-            error, f"Failed to launch process with libunwind at {libunwind_path}"
-        )
-        self.assertTrue(process, PROCESS_IS_VALID)
-
-        # We should hit the breakpoint in __libunwind_Registers_arm64_jumpto
-        # during the exception unwinding phase 2.
-        threads = lldbutil.get_threads_stopped_at_breakpoint(process, bp)
-        self.assertEqual(len(threads), 1, "Should have stopped at breakpoint")
-
-        thread = threads[0]
-        frame = thread.GetFrameAtIndex(0)
-
-        # Verify we're in __libunwind_Registers_arm64_jumpto.
-        function_name = frame.GetFunctionName()
-     ...
[truncated]

@github-actions
Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions hpp,cpp,h,c -- libunwind/src/Registers.hpp libunwind/src/UnwindCursor.hpp libunwind/src/UnwindLevel1.c libunwind/src/assembly.h libunwind/src/config.h libunwind/src/libunwind.cpp libunwind/src/libunwind_ext.h --diff_from_common_commit

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 7ec5f9e91..b4c5bbcaf 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -965,7 +965,7 @@ public:
   virtual void        setFloatReg(int, unw_fpreg_t);
   virtual int         step(bool stage2 = false);
   virtual void        getInfo(unw_proc_info_t *);
-  virtual void        jumpto();
+  virtual void jumpto();
   virtual bool        isSignalFrame();
   virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
   virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
diff --git a/libunwind/src/UnwindLevel1.c b/libunwind/src/UnwindLevel1.c
index b0cd60dfb..3887d6c51 100644
--- a/libunwind/src/UnwindLevel1.c
+++ b/libunwind/src/UnwindLevel1.c
@@ -206,9 +206,9 @@ extern int __unw_step_stage2(unw_cursor_t *);
 // Enable the GCS target feature to permit gcspop instructions to be used.
 __attribute__((target("+gcs")))
 #endif
-static _Unwind_Reason_Code
-unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
-              _Unwind_Exception *exception_object) {
+static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
+                                         unw_cursor_t *cursor,
+                                         _Unwind_Exception *exception_object) {
   __unw_init_local(cursor, uc);
 
   _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
diff --git a/libunwind/src/config.h b/libunwind/src/config.h
index deb5a4d4d..bcf9173d9 100644
--- a/libunwind/src/config.h
+++ b/libunwind/src/config.h
@@ -27,7 +27,7 @@
   #else
     #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
-  #endif
+#endif
 #elif defined(_WIN32)
   #ifdef __SEH__
     #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1

@medismailben
Copy link
Member

@sylvestre #167743 should fix the issue. Merging it as soon as it passes the PR testing.

@sylvestre sylvestre closed this Nov 12, 2025
@sylvestre
Copy link
Collaborator Author

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants