[libunwind] 77e879f - [libunwind][AArch64] Support .cfi_set_ra_state (#209950)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 23 11:46:41 PDT 2026
Author: Jon Roelofs
Date: 2026-07-23T11:46:36-07:00
New Revision: 77e879f967294d76376bf7a022092a1d6f3ed583
URL: https://github.com/llvm/llvm-project/commit/77e879f967294d76376bf7a022092a1d6f3ed583
DIFF: https://github.com/llvm/llvm-project/commit/77e879f967294d76376bf7a022092a1d6f3ed583.diff
LOG: [libunwind][AArch64] Support .cfi_set_ra_state (#209950)
This new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.
1: https://github.com/ARM-software/abi-aa/pull/346
Added:
Modified:
libunwind/src/DwarfParser.hpp
libunwind/src/dwarf2.h
libunwind/test/CMakeLists.txt
libunwind/test/configs/apple-libunwind-system.cfg.in
libunwind/test/configs/llvm-libunwind-merged.cfg.in
libunwind/test/configs/llvm-libunwind-shared.cfg.in
libunwind/test/configs/llvm-libunwind-static.cfg.in
libunwind/test/ra_sign_state.pass.cpp
Removed:
################################################################################
diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp
index ba40b757ab977..d60e3e11325d3 100644
--- a/libunwind/src/DwarfParser.hpp
+++ b/libunwind/src/DwarfParser.hpp
@@ -859,6 +859,26 @@ bool CFI_Parser<A>::parseFDEInstructions(
} break;
#endif
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+ case DW_CFA_AARCH64_set_ra_state: {
+ int64_t value =
+ static_cast<int64_t>(addressSpace.getULEB128(p, instructionsEnd));
+ if (value < 0 || 2 < value) {
+ _LIBUNWIND_LOG0("malformed DW_CFA_AARCH64_set_ra_state DWARF "
+ "unwind, RA_SIGN_STATE value not recognized");
+ return false;
+ }
+ offset = addressSpace.getSLEB128(p, instructionsEnd) *
+ cieInfo.codeAlignFactor;
+ results->setRegister(UNW_AARCH64_RA_SIGN_STATE, kRegisterIsPseudo,
+ value, initialState);
+ results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset + offset;
+ _LIBUNWIND_TRACE_DWARF(
+ "DW_CFA_AARCH64_set_ra_state(state=%" PRId64 ",pc=0x%" PRIx64 ")\n",
+ value, static_cast<uint64_t>(results->ptrAuthDiversifier));
+ } break;
+#endif
+
#else
(void)arch;
#endif
diff --git a/libunwind/src/dwarf2.h b/libunwind/src/dwarf2.h
index 68ad882347203..19f6e4de3fe34 100644
--- a/libunwind/src/dwarf2.h
+++ b/libunwind/src/dwarf2.h
@@ -51,6 +51,7 @@ enum {
DW_CFA_GNU_negative_offset_extended = 0x2F,
// AARCH64 extensions
+ DW_CFA_AARCH64_set_ra_state = 0x2B,
DW_CFA_AARCH64_negate_ra_state_with_pc = 0x2C,
DW_CFA_AARCH64_negate_ra_state = 0x2D
};
diff --git a/libunwind/test/CMakeLists.txt b/libunwind/test/CMakeLists.txt
index 3a4433689051c..780be2f13b85c 100644
--- a/libunwind/test/CMakeLists.txt
+++ b/libunwind/test/CMakeLists.txt
@@ -33,6 +33,24 @@ pythonize_bool(LIBUNWIND_ENABLE_GCS)
pythonize_bool(LIBUNWIND_ENABLE_THREADS)
pythonize_bool(LIBUNWIND_USES_ARM_EHABI)
+file(WRITE "${CMAKE_BINARY_DIR}/check_cfi_set_ra_state.s" "
+ .text
+ .global _test_cfi_set_ra_state
+_test_cfi_set_ra_state:
+ .cfi_startproc
+ .cfi_set_ra_state 0, 0
+ ret
+ .cfi_endproc
+")
+set(_previous_CMAKE_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+try_compile(HAVE_CFI_SET_RA_STATE
+ "${CMAKE_BINARY_DIR}/check_cfi_set_ra_state"
+ SOURCES "${CMAKE_BINARY_DIR}/check_cfi_set_ra_state.s"
+)
+set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_previous_CMAKE_TRY_COMPILE_TARGET_TYPE})
+pythonize_bool(HAVE_CFI_SET_RA_STATE)
+
set(AUTO_GEN_COMMENT "## Autogenerated by libunwind configuration.\n# Do not edit!")
set(SERIALIZED_LIT_PARAMS "# Lit parameters serialized here for llvm-lit to pick them up\n")
diff --git a/libunwind/test/configs/apple-libunwind-system.cfg.in b/libunwind/test/configs/apple-libunwind-system.cfg.in
index 252448a756be9..2349ca394b58b 100644
--- a/libunwind/test/configs/apple-libunwind-system.cfg.in
+++ b/libunwind/test/configs/apple-libunwind-system.cfg.in
@@ -12,8 +12,13 @@ lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
config.substitutions.append(('%{flags}',
'-isysroot {}'.format('@CMAKE_OSX_SYSROOT@') if '@CMAKE_OSX_SYSROOT@' else ''
))
+
+compile_flags = ['-nostdinc++', '-I', '%{include}']
+if @HAVE_CFI_SET_RA_STATE@:
+ compile_flags.append('-DHAVE_CFI_SET_RA_STATE')
+
config.substitutions.append(('%{compile_flags}',
- '-nostdinc++ -I %{include}'
+ ' '.join(compile_flags)
))
config.substitutions.append(('%{link_flags}',
'-nostdlib++ -L %{lib} -lc++ -lunwind'
diff --git a/libunwind/test/configs/llvm-libunwind-merged.cfg.in b/libunwind/test/configs/llvm-libunwind-merged.cfg.in
index 1ae1b515bff4d..231849f5c4e56 100644
--- a/libunwind/test/configs/llvm-libunwind-merged.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-merged.cfg.in
@@ -20,6 +20,9 @@ if @LIBUNWIND_ENABLE_CET@:
if @LIBUNWIND_ENABLE_GCS@:
compile_flags.append('-mbranch-protection=standard')
+if @HAVE_CFI_SET_RA_STATE@:
+ compile_flags.append('-DHAVE_CFI_SET_RA_STATE')
+
# On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker.
if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'):
link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@')
diff --git a/libunwind/test/configs/llvm-libunwind-shared.cfg.in b/libunwind/test/configs/llvm-libunwind-shared.cfg.in
index 84af348a5c6cb..0a7a24eb08c5e 100644
--- a/libunwind/test/configs/llvm-libunwind-shared.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-shared.cfg.in
@@ -19,6 +19,9 @@ if @LIBUNWIND_ENABLE_CET@:
if @LIBUNWIND_ENABLE_GCS@:
compile_flags.append('-mbranch-protection=standard')
+if @HAVE_CFI_SET_RA_STATE@:
+ compile_flags.append('-DHAVE_CFI_SET_RA_STATE')
+
# On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker.
if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'):
link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@')
diff --git a/libunwind/test/configs/llvm-libunwind-static.cfg.in b/libunwind/test/configs/llvm-libunwind-static.cfg.in
index 7e1fb5395c57a..f831c74948579 100644
--- a/libunwind/test/configs/llvm-libunwind-static.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-static.cfg.in
@@ -22,6 +22,9 @@ if @LIBUNWIND_ENABLE_CET@:
if @LIBUNWIND_ENABLE_GCS@:
compile_flags.append('-mbranch-protection=standard')
+if @HAVE_CFI_SET_RA_STATE@:
+ compile_flags.append('-DHAVE_CFI_SET_RA_STATE')
+
# On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker.
if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'):
link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@')
diff --git a/libunwind/test/ra_sign_state.pass.cpp b/libunwind/test/ra_sign_state.pass.cpp
index 9187d039a761b..4c407890245a0 100644
--- a/libunwind/test/ra_sign_state.pass.cpp
+++ b/libunwind/test/ra_sign_state.pass.cpp
@@ -141,6 +141,34 @@ __attribute__((naked, target("pauth"))) static uint64_t check_negate() {
// clang-format on
}
+#if defined(HAVE_CFI_SET_RA_STATE)
+__attribute__((naked, target("pauth"))) uint64_t check_set() {
+ // clang-format off
+ asm(
+#if !defined(__APPLE__)
+ ".cfi_b_key_frame\n"
+#endif
+ ".cfi_set_ra_state 1, 0\n"
+ "pacibsp\n"
+
+ "stp x29, x30, [sp, #-16]!\n"
+ ".cfi_def_cfa_offset 16\n"
+ ".cfi_offset x29, -16\n"
+ ".cfi_offset x30, -8\n"
+
+ "bl " SYMBOL_NAME(get_main_ra_sign_state) "\n"
+
+ "ldp x29, x30, [sp], #16\n"
+ ".cfi_def_cfa_offset 0\n"
+ ".cfi_restore x29\n"
+ ".cfi_restore x30\n"
+
+ ".cfi_set_ra_state 0, -20\n"
+ "retab");
+ // clang-format on
+}
+#endif
+
FUNC_ATTR(main_func) int main(int, char **) {
uint64_t ret;
@@ -159,6 +187,12 @@ FUNC_ATTR(main_func) int main(int, char **) {
fprintf(stderr, "check_negate: ret = 0x%" PRIx64 "\n", ret);
assert(ret == 1);
- printf("success\n");
+#if defined(HAVE_CFI_SET_RA_STATE)
+ ret = check_set();
+ fprintf(stderr, "check_set: ret = 0x%" PRIx64 "\n", ret);
+ assert(ret == 1);
+#endif
+
+ fprintf(stderr, "success\n");
return 0;
}
More information about the cfe-commits
mailing list