Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions libunwind/src/Registers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}
Expand Down
66 changes: 2 additions & 64 deletions libunwind/src/UnwindCursor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand All @@ -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");
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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
};


Expand Down Expand Up @@ -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__
Expand All @@ -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() {
Expand Down
24 changes: 10 additions & 14 deletions libunwind/src/UnwindLevel1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand All @@ -66,27 +67,26 @@
} 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), \
"d"(shstkJumpAddress)); \
} 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

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
15 changes: 1 addition & 14 deletions libunwind/src/UnwindRegistersRestore.S
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
4 changes: 0 additions & 4 deletions libunwind/src/assembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 0 additions & 9 deletions libunwind/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
22 changes: 1 addition & 21 deletions libunwind/src/libunwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
6 changes: 1 addition & 5 deletions libunwind/src/libunwind_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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). */
Expand Down
25 changes: 0 additions & 25 deletions lldb/packages/Python/lldbsuite/test/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

This file was deleted.

Loading
Loading