git: 6a936d939b88 - main - Merge commit 4d7292e58078 from llvm-project (by Minsoo Choo):
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 25 Oct 2026 12:12:26 UTC
The branch main has been updated by dim:
URL: https://cgit.FreeBSD.org/src/commit/?id=6a936d939b886fe3d777d33b0327987c3aa08f51
commit 6a936d939b886fe3d777d33b0327987c3aa08f51
Author: Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2026-10-25 11:34:38 +0000
Commit: Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2026-10-25 12:11:27 +0000
Merge commit 4d7292e58078 from llvm-project (by Minsoo Choo):
[libunwind] Unwind through AArch64 FreeBSD signal trampolines (#235065)
Retried from https://reviews.llvm.org/D155066.
Recognize signal trampolines using KERN_PROC_SIGTRAMP when unwind
metadata is unavailable. Restore the interrupted PC, LR, SP, general
registers, and valid floating-point registers.
Add coverage for unwinding out of an interrupted leaf function on both
regular and alternate signal stacks.
Assisted-by: GPT
MFC after: 1 week
---
.../libunwind/include/__libunwind_config.h | 3 +
.../llvm-project/libunwind/src/UnwindCursor.hpp | 77 +++++++++++++++++++++-
2 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/contrib/llvm-project/libunwind/include/__libunwind_config.h b/contrib/llvm-project/libunwind/include/__libunwind_config.h
index bb7fe4c83a3c..493910c3df51 100644
--- a/contrib/llvm-project/libunwind/include/__libunwind_config.h
+++ b/contrib/llvm-project/libunwind/include/__libunwind_config.h
@@ -36,6 +36,9 @@
# if defined(__linux__)
# define _LIBUNWIND_TARGET_LINUX 1
# endif
+# if defined(__FreeBSD__)
+# define _LIBUNWIND_TARGET_FREEBSD 1
+# endif
# if defined(__HAIKU__)
# define _LIBUNWIND_TARGET_HAIKU 1
# endif
diff --git a/contrib/llvm-project/libunwind/src/UnwindCursor.hpp b/contrib/llvm-project/libunwind/src/UnwindCursor.hpp
index 9a1afd3721f5..067a3c238245 100644
--- a/contrib/llvm-project/libunwind/src/UnwindCursor.hpp
+++ b/contrib/llvm-project/libunwind/src/UnwindCursor.hpp
@@ -41,6 +41,17 @@
#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
#endif
+#if defined(_LIBUNWIND_TARGET_FREEBSD) && defined(_LIBUNWIND_TARGET_AARCH64)
+#include <errno.h>
+#include <machine/frame.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/ucontext.h>
+#include <sys/user.h>
+#include <unistd.h>
+#define _LIBUNWIND_CHECK_FREEBSD_SIGRETURN 1
+#endif
+
#if defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)
#include <OS.h>
#include <signal.h>
@@ -1038,7 +1049,8 @@ private:
template <typename Registers> int stepThroughSigReturn(Registers &) {
return UNW_STEP_END;
}
-#elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
+#elif defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) || \
+ defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
bool setInfoForSigReturn();
int stepThroughSigReturn();
#endif
@@ -1345,6 +1357,7 @@ private:
bool _unwindInfoMissing;
bool _isSignalFrame;
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
+ defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) || \
defined(_LIBUNWIND_TARGET_HAIKU)
bool _isSigReturn = false;
#endif
@@ -2637,6 +2650,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
template <typename A, typename R>
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
+ defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) || \
defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
_isSigReturn = false;
#endif
@@ -2762,6 +2776,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
+ defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) || \
defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
if (setInfoForSigReturn())
return;
@@ -3053,6 +3068,65 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
// defined(_LIBUNWIND_TARGET_S390X)
+#if defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::setInfoForSigReturn() {
+ // Ask the kernel rather than reading instructions at a possibly invalid PC.
+ // This is only used when no unwind information was found. Keep the result
+ // local to avoid shared mutable state when unwinding from a signal handler.
+ struct kinfo_sigtramp kst = {};
+ size_t len = sizeof(kst);
+ int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP, getpid()};
+ const int savedErrno = errno;
+ const int result = sysctl(mib, 4, &kst, &len, nullptr, 0);
+ errno = savedErrno;
+ if (result != 0)
+ return false;
+
+ const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
+ const pint_t start = reinterpret_cast<pint_t>(kst.ksigtramp_start);
+ const pint_t end = reinterpret_cast<pint_t>(kst.ksigtramp_end);
+ if (pc < start || pc >= end)
+ return false;
+
+ _info = {};
+ _info.start_ip = start;
+ _info.end_ip = end;
+ _isSigReturn = true;
+ return true;
+}
+
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+template <typename A, typename R>
+int UnwindCursor<A, R>::stepThroughSigReturn() {
+ // The trampoline leaves SP pointing at the sigframe installed by sendsig().
+ const pint_t sigctx = _registers.getSP() + offsetof(struct sigframe, sf_uc) +
+ offsetof(ucontext_t, uc_mcontext);
+ const pint_t gprs = sigctx + offsetof(mcontext_t, mc_gpregs);
+ for (int i = 0; i < 30; ++i)
+ _registers.setRegister(
+ UNW_AARCH64_X0 + i,
+ _addressSpace.get64(gprs + offsetof(struct gpregs, gp_x) + i * 8));
+ _registers.setRegister(
+ UNW_AARCH64_LR,
+ _addressSpace.get64(gprs + offsetof(struct gpregs, gp_lr)));
+ _registers.setSP(_addressSpace.get64(gprs + offsetof(struct gpregs, gp_sp)));
+ _registers.setIP(_addressSpace.get64(gprs + offsetof(struct gpregs, gp_elr)));
+
+ if (_addressSpace.get32(sigctx + offsetof(mcontext_t, mc_flags)) &
+ _MC_FP_VALID) {
+ const pint_t fprs = sigctx + offsetof(mcontext_t, mc_fpregs) +
+ offsetof(struct fpregs, fp_q);
+ for (int i = 0; i < 32; ++i)
+ _registers.setFloatRegister(UNW_AARCH64_V0 + i,
+ _addressSpace.getDouble(fprs + i * 16));
+ }
+ _isSignalFrame = true;
+ return UNW_STEP_SUCCESS;
+}
+#endif // defined(_LIBUNWIND_TARGET_AARCH64)
+#endif // defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN)
+
#if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
template <typename A, typename R>
bool UnwindCursor<A, R>::setInfoForSigReturn() {
@@ -3152,6 +3226,7 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
// Use unwinding info to modify register set as if function returned.
int result;
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
+ defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) || \
defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
if (_isSigReturn) {
result = this->stepThroughSigReturn();