[libcxxabi] [libunwind] [libunwind][AIX] Handle VAPI-based return addresses in stack unwinding for LLU (PR #209280)
Xing Xue via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 16 03:40:47 PDT 2026
https://github.com/xingxue-ibm updated https://github.com/llvm/llvm-project/pull/209280
>From 6b69974ca040d85a14a898c242f60c425b190c49 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 13 Jul 2026 15:04:04 -0400
Subject: [PATCH 1/5] Update the unwinder to accommodate AIX changes required
for LLU (Live Library Update).
---
libcxxabi/test/aix_unwind_vapi.pass.cpp | 66 +++++++++++++++++
libunwind/src/UnwindCursor.hpp | 98 ++++++++++++++++++++++++-
2 files changed, 160 insertions(+), 4 deletions(-)
create mode 100644 libcxxabi/test/aix_unwind_vapi.pass.cpp
diff --git a/libcxxabi/test/aix_unwind_vapi.pass.cpp b/libcxxabi/test/aix_unwind_vapi.pass.cpp
new file mode 100644
index 0000000000000..bafb02f366ab4
--- /dev/null
+++ b/libcxxabi/test/aix_unwind_vapi.pass.cpp
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Test unwinding through a frame whose return address points to the VAPI
+// glue for the Live Library Update feature.
+
+// REQUIRES: target={{.+}}-aix{{.*}}
+
+#include <stdlib.h>
+#include <stdio.h>
+
+// VAPI glue addresses
+constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8B80;
+constexpr uintptr_t vapi_addr_64 = 0x8e00;
+constexpr uintptr_t vapi_size_64 = 0x0200;
+constexpr uintptr_t vapi_glue_addr_begin = vapi_glue_addr_ext_32; // Start address in 32-bit
+constexpr uintptr_t vapi_glue_addr_end = vapi_addr_64 + vapi_size_64; // End address in 64-bit
+
+struct FunctionDescriptor {
+ uintptr_t entry;
+ uintptr_t toc;
+ uintptr_t env;
+};
+
+struct Tracker {
+ const char* name;
+ Tracker(const char* n) : name(n) { printf("Construct %s\n", name); }
+ ~Tracker() { printf("Destruct %s\n", name); }
+};
+
+int comp(const void*, const void*) {
+ printf("comp()\n");
+ throw 42;
+}
+
+static void do_search() {
+ Tracker t("do_search-local");
+ char buf[1];
+ char key = 0;
+ printf("calling bsearch()\n");
+ // bsearch uses VAPI and sets the return address to the VAPI glue when LLU
+ // is on.
+ bsearch(&key, buf, 1, 1, comp);
+ printf("after bsearch\n");
+}
+
+int main() {
+ FunctionDescriptor* fd = reinterpret_cast<FunctionDescriptor*>(bsearch);
+
+ if (vapi_glue_addr_begin <= fd->entry && fd->entry < vapi_glue_addr_end) {
+ printf("!!! Live Library Update is enabled !!!\n");
+ } else {
+ printf("!!! Live Library Update is NOT enabled !!!\n");
+ }
+
+ try {
+ do_search();
+ } catch (...) {
+ printf("caught ...\n");
+ }
+}
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index ff92c9e0a844a..f59384af81b5e 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -1363,6 +1363,10 @@ class UnwindCursor : public AbstractUnwindCursor {
reinterpret_cast<tbtable *>(_info.unwind_info),
_registers, _isSignalFrame);
}
+ bool isKnownVapiNotActive() const { return _isKnownVapiNotActive; }
+ void setIsKnownVapiNotActive(bool val) { _isKnownVapiNotActive = val; }
+ static pint_t getVAPILR();
+
#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
A &_addressSpace;
@@ -1377,13 +1381,15 @@ class UnwindCursor : public AbstractUnwindCursor {
#ifdef _LIBUNWIND_TRACE_RET_INJECT
uint32_t _walkedFrames;
#endif
+#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ bool _isKnownVapiNotActive;
+#endif
};
-
template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
: _addressSpace(as), _registers(context), _unwindInfoMissing(false),
- _isSignalFrame(false) {
+ _isSignalFrame(false), _isKnownVapiNotActive(false) {
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
"UnwindCursor<> does not fit in unw_cursor_t");
static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
@@ -1393,13 +1399,13 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(A &as, void *)
- : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
+ : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false),
+ _isKnownVapiNotActive(false) {
memset(static_cast<void *>(&_info), 0, sizeof(_info));
// FIXME
// fill in _registers from thread arg
}
-
template <typename A, typename R>
bool UnwindCursor<A, R>::validReg(int regNum) {
return _registers.validRegister(regNum);
@@ -1469,6 +1475,30 @@ template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1;
_registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED);
#else
+#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ if (isKnownVapiNotActive()) {
+ // If the current frame is known VAPI not active , execute the VAPI return
+ // glue to clear the VAPI control block. The VAPI return glue is used by
+ // AIX longjmp based on the VAPI active status recorded by setjmp in the
+ // jmp_buf, which means that the VAPI return glue can be called solely on
+ // the basis of the VAPI active status of the target context.
+
+ // VAPI return glue address is the VAPI glue address - 4.
+#ifdef __64BIT__
+ constexpr pint_t VAPIReturnGlue = 0x8e40 - 4;
+#else
+ constexpr pint_t VAPIReturnGlue = 0x8c40 - 4;
+#endif
+
+ _LIBUNWIND_TRACE_UNWINDING("VAPI: executing return glue %p\n",
+ reinterpret_cast<void *>(VAPIReturnGlue));
+ register auto *registers __asm__("r30") = &_registers;
+ __asm__ __volatile__("bla %[retglue]"
+ : "+r"(registers)
+ : [retglue] "i"(VAPIReturnGlue));
+ registers->jumpto();
+ }
+#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
_registers.jumpto();
#endif
}
@@ -2459,6 +2489,45 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R ®isters) {
return true;
}
+// VAPI glue addresses
+constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8B80;
+constexpr uintptr_t vapi_addr_64 = 0x8e00;
+constexpr uintptr_t vapi_size_64 = 0x0200;
+constexpr uintptr_t vapi_glue_addr_begin =
+ vapi_glue_addr_ext_32; // Start address in 32-bit
+constexpr uintptr_t vapi_glue_addr_end =
+ vapi_addr_64 + vapi_size_64; // End address in 64-bit
+
+#ifdef __64BIT__
+constexpr uintptr_t VAPI_CB_SIZE = 256;
+constexpr uintptr_t TLS_POINTER_OFFSET = 30 * 1024;
+constexpr uintptr_t TLSCB_BASE_SIZE = 256;
+
+static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
+ char *result;
+ __asm__("mr %0, 13" : "=r"(result));
+ return result;
+}
+#else // 32-bit
+constexpr uintptr_t VAPI_CB_SIZE = 128;
+constexpr uintptr_t TLS_POINTER_OFFSET = 31 * 1024;
+constexpr uintptr_t TLSCB_BASE_SIZE = 128;
+
+static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
+ char *result;
+ __asm__("mfspr %0, 259" : "=r"(result));
+ return result;
+}
+#endif
+
+constexpr int VAPI_CB_OFFSET =
+ TLS_POINTER_OFFSET + VAPI_CB_SIZE + TLSCB_BASE_SIZE;
+
+template <typename A, typename R>
+typename UnwindCursor<A, R>::pint_t UnwindCursor<A, R>::getVAPILR() {
+ return *reinterpret_cast<pint_t *>(tptr() - VAPI_CB_OFFSET + 8);
+}
+
// Step back up the stack following the frame back link.
template <typename A, typename R>
int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
@@ -2579,6 +2648,17 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
} else {
// Otherwise, use the LR value in the stack link area.
returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
+
+ if (vapi_glue_addr_begin <= returnAddress &&
+ returnAddress < vapi_glue_addr_end) {
+ _LIBUNWIND_TRACE_UNWINDING(
+ "The return address=%p is within the range of VAPI address, ",
+ reinterpret_cast<void *>(returnAddress));
+ setIsKnownVapiNotActive(true);
+ returnAddress = getVAPILR();
+ _LIBUNWIND_TRACE_UNWINDING("return address=%p from VAPI\n",
+ reinterpret_cast<void *>(returnAddress));
+ }
}
// Reset LR in the current context.
@@ -2709,6 +2789,16 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
// Return address is the address after call site instruction.
pint_t nextReturnAddress = reinterpret_cast<pint_t *>(nextStack)[2];
+ if (vapi_glue_addr_begin <= nextReturnAddress &&
+ nextReturnAddress < vapi_glue_addr_end) {
+ _LIBUNWIND_TRACE_UNWINDING(
+ "The next return address=%p is within the range of VAPI address, ",
+ reinterpret_cast<void *>(nextReturnAddress));
+ nextReturnAddress = getVAPILR();
+ _LIBUNWIND_TRACE_UNWINDING("the next return address=%p from VAPI\n",
+ reinterpret_cast<void *>(nextReturnAddress));
+ }
+
if (nextReturnAddress > 0x01 && nextReturnAddress < 0x10000) {
_LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
"nextStack=%p, next return address=%p\n",
>From 578ab2193990e1954f302654d3f17fa40e639f0e Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 13 Jul 2026 15:47:23 -0400
Subject: [PATCH 2/5] Guard _isKnownVapiNotActive(false) initializers with #if
defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND).
---
libunwind/src/UnwindCursor.hpp | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index f59384af81b5e..7b400964defc8 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -1389,7 +1389,11 @@ class UnwindCursor : public AbstractUnwindCursor {
template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
: _addressSpace(as), _registers(context), _unwindInfoMissing(false),
- _isSignalFrame(false), _isKnownVapiNotActive(false) {
+ _isSignalFrame(false)
+#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ , _isKnownVapiNotActive(false)
+#endif
+ {
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
"UnwindCursor<> does not fit in unw_cursor_t");
static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
@@ -1399,8 +1403,11 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(A &as, void *)
- : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false),
- _isKnownVapiNotActive(false) {
+ : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false)
+#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ , _isKnownVapiNotActive(false)
+#endif
+ {
memset(static_cast<void *>(&_info), 0, sizeof(_info));
// FIXME
// fill in _registers from thread arg
>From 6b571a1a2099194a52e7db94c4fcd9adf5b39bde Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 13 Jul 2026 18:18:53 -0400
Subject: [PATCH 3/5] Address comments and fix formatting. - correct variable
types - add a comment for TODO
---
libcxxabi/test/aix_unwind_vapi.pass.cpp | 66 -------------------------
libunwind/src/UnwindCursor.hpp | 37 ++++++++------
2 files changed, 21 insertions(+), 82 deletions(-)
delete mode 100644 libcxxabi/test/aix_unwind_vapi.pass.cpp
diff --git a/libcxxabi/test/aix_unwind_vapi.pass.cpp b/libcxxabi/test/aix_unwind_vapi.pass.cpp
deleted file mode 100644
index bafb02f366ab4..0000000000000
--- a/libcxxabi/test/aix_unwind_vapi.pass.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// Test unwinding through a frame whose return address points to the VAPI
-// glue for the Live Library Update feature.
-
-// REQUIRES: target={{.+}}-aix{{.*}}
-
-#include <stdlib.h>
-#include <stdio.h>
-
-// VAPI glue addresses
-constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8B80;
-constexpr uintptr_t vapi_addr_64 = 0x8e00;
-constexpr uintptr_t vapi_size_64 = 0x0200;
-constexpr uintptr_t vapi_glue_addr_begin = vapi_glue_addr_ext_32; // Start address in 32-bit
-constexpr uintptr_t vapi_glue_addr_end = vapi_addr_64 + vapi_size_64; // End address in 64-bit
-
-struct FunctionDescriptor {
- uintptr_t entry;
- uintptr_t toc;
- uintptr_t env;
-};
-
-struct Tracker {
- const char* name;
- Tracker(const char* n) : name(n) { printf("Construct %s\n", name); }
- ~Tracker() { printf("Destruct %s\n", name); }
-};
-
-int comp(const void*, const void*) {
- printf("comp()\n");
- throw 42;
-}
-
-static void do_search() {
- Tracker t("do_search-local");
- char buf[1];
- char key = 0;
- printf("calling bsearch()\n");
- // bsearch uses VAPI and sets the return address to the VAPI glue when LLU
- // is on.
- bsearch(&key, buf, 1, 1, comp);
- printf("after bsearch\n");
-}
-
-int main() {
- FunctionDescriptor* fd = reinterpret_cast<FunctionDescriptor*>(bsearch);
-
- if (vapi_glue_addr_begin <= fd->entry && fd->entry < vapi_glue_addr_end) {
- printf("!!! Live Library Update is enabled !!!\n");
- } else {
- printf("!!! Live Library Update is NOT enabled !!!\n");
- }
-
- try {
- do_search();
- } catch (...) {
- printf("caught ...\n");
- }
-}
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 7b400964defc8..1f147dc4e920e 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -1382,6 +1382,9 @@ class UnwindCursor : public AbstractUnwindCursor {
uint32_t _walkedFrames;
#endif
#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ // TODO: this will need to be recorded in the unw_context_t by unw_getcontext
+ // to support cases where the cursor is retrieved prior to invocation of the
+ // Virtual API.
bool _isKnownVapiNotActive;
#endif
};
@@ -1391,9 +1394,10 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
: _addressSpace(as), _registers(context), _unwindInfoMissing(false),
_isSignalFrame(false)
#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
- , _isKnownVapiNotActive(false)
+ ,
+ _isKnownVapiNotActive(false)
#endif
- {
+{
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
"UnwindCursor<> does not fit in unw_cursor_t");
static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
@@ -1405,9 +1409,10 @@ template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(A &as, void *)
: _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false)
#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
- , _isKnownVapiNotActive(false)
+ ,
+ _isKnownVapiNotActive(false)
#endif
- {
+{
memset(static_cast<void *>(&_info), 0, sizeof(_info));
// FIXME
// fill in _registers from thread arg
@@ -1484,7 +1489,7 @@ template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
#else
#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
if (isKnownVapiNotActive()) {
- // If the current frame is known VAPI not active , execute the VAPI return
+ // If the current frame is known VAPI not active, execute the VAPI return
// glue to clear the VAPI control block. The VAPI return glue is used by
// AIX longjmp based on the VAPI active status recorded by setjmp in the
// jmp_buf, which means that the VAPI return glue can be called solely on
@@ -2497,18 +2502,18 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R ®isters) {
}
// VAPI glue addresses
-constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8B80;
+constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8b80;
constexpr uintptr_t vapi_addr_64 = 0x8e00;
-constexpr uintptr_t vapi_size_64 = 0x0200;
+constexpr size_t vapi_size_64 = 0x0200;
constexpr uintptr_t vapi_glue_addr_begin =
vapi_glue_addr_ext_32; // Start address in 32-bit
constexpr uintptr_t vapi_glue_addr_end =
vapi_addr_64 + vapi_size_64; // End address in 64-bit
#ifdef __64BIT__
-constexpr uintptr_t VAPI_CB_SIZE = 256;
-constexpr uintptr_t TLS_POINTER_OFFSET = 30 * 1024;
-constexpr uintptr_t TLSCB_BASE_SIZE = 256;
+constexpr size_t VAPI_CB_SIZE = 256;
+constexpr ptrdiff_t TLS_POINTER_OFFSET = 30 * 1024;
+constexpr size_t TLSCB_BASE_SIZE = 256;
static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
char *result;
@@ -2516,9 +2521,9 @@ static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
return result;
}
#else // 32-bit
-constexpr uintptr_t VAPI_CB_SIZE = 128;
-constexpr uintptr_t TLS_POINTER_OFFSET = 31 * 1024;
-constexpr uintptr_t TLSCB_BASE_SIZE = 128;
+constexpr size_t VAPI_CB_SIZE = 128;
+constexpr ptrdiff_t TLS_POINTER_OFFSET = 31 * 1024;
+constexpr size_t TLSCB_BASE_SIZE = 128;
static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
char *result;
@@ -2527,7 +2532,7 @@ static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
}
#endif
-constexpr int VAPI_CB_OFFSET =
+constexpr ptrdiff_t VAPI_CB_OFFSET =
TLS_POINTER_OFFSET + VAPI_CB_SIZE + TLSCB_BASE_SIZE;
template <typename A, typename R>
@@ -2659,7 +2664,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
if (vapi_glue_addr_begin <= returnAddress &&
returnAddress < vapi_glue_addr_end) {
_LIBUNWIND_TRACE_UNWINDING(
- "The return address=%p is within the range of VAPI address, ",
+ "The return address=%p is within the range of VAPI address;",
reinterpret_cast<void *>(returnAddress));
setIsKnownVapiNotActive(true);
returnAddress = getVAPILR();
@@ -2799,7 +2804,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
if (vapi_glue_addr_begin <= nextReturnAddress &&
nextReturnAddress < vapi_glue_addr_end) {
_LIBUNWIND_TRACE_UNWINDING(
- "The next return address=%p is within the range of VAPI address, ",
+ "The next return address=%p is within the range of VAPI address;",
reinterpret_cast<void *>(nextReturnAddress));
nextReturnAddress = getVAPILR();
_LIBUNWIND_TRACE_UNWINDING("the next return address=%p from VAPI\n",
>From cceca093ab4e38ce33b6fe7457158c52b8688ee4 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Wed, 15 Jul 2026 10:50:09 -0400
Subject: [PATCH 4/5] If the return address in a signal handling trampoline
frame is a VAPI glue return address, set isKnownVapiNotActive flag to true.
---
libunwind/src/UnwindCursor.hpp | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 1f147dc4e920e..03ea96b2e4451 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -2592,6 +2592,16 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
_LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
reinterpret_cast<void *>(lastStack));
+ pint_t returnAddressInStack = reinterpret_cast<pint_t *>(lastStack)[2];
+ if (vapi_glue_addr_begin <= returnAddressInStack &&
+ returnAddressInStack < vapi_glue_addr_end) {
+ _LIBUNWIND_TRACE_UNWINDING(
+ "The return address in stack %p is within the range of VAPI address,"
+ " set isKnownVapiNotActive to true\n",
+ reinterpret_cast<void *>(returnAddressInStack));
+ setIsKnownVapiNotActive(true);
+ }
+
sigcontext *sigContext = reinterpret_cast<sigcontext *>(
reinterpret_cast<char *>(lastStack) + STKMINALIGN);
returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
>From f2a6772a578c51da6ea39fc2bf7483bf331ae3d4 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Thu, 16 Jul 2026 06:40:35 -0400
Subject: [PATCH 5/5] Apply suggestion: ',' -> ';'.
Co-authored-by: Hubert Tong <hubert.reinterpretcast at gmail.com>
---
libunwind/src/UnwindCursor.hpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 03ea96b2e4451..537dbd83f4f74 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -2596,7 +2596,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
if (vapi_glue_addr_begin <= returnAddressInStack &&
returnAddressInStack < vapi_glue_addr_end) {
_LIBUNWIND_TRACE_UNWINDING(
- "The return address in stack %p is within the range of VAPI address,"
+ "The return address in stack %p is within the range of VAPI address;"
" set isKnownVapiNotActive to true\n",
reinterpret_cast<void *>(returnAddressInStack));
setIsKnownVapiNotActive(true);
More information about the cfe-commits
mailing list