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; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
