https://github.com/jroelofs updated 
https://github.com/llvm/llvm-project/pull/209947

>From 04044544f626a36d836f1b21529a0004f7153ac7 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <[email protected]>
Date: Wed, 15 Jul 2026 20:32:54 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7
---
 libunwind/src/DwarfInstructions.hpp   |   8 ++
 libunwind/src/DwarfParser.hpp         |  11 +-
 libunwind/test/ra_sign_state.pass.cpp | 164 ++++++++++++++++++++++++++
 3 files changed, 178 insertions(+), 5 deletions(-)
 create mode 100644 libunwind/test/ra_sign_state.pass.cpp

diff --git a/libunwind/src/DwarfInstructions.hpp 
b/libunwind/src/DwarfInstructions.hpp
index 56220c327a7fa..267ee6ab4693d 100644
--- a/libunwind/src/DwarfInstructions.hpp
+++ b/libunwind/src/DwarfInstructions.hpp
@@ -117,8 +117,14 @@ typename A::pint_t DwarfInstructions<A, 
R>::getSavedRegister(
 
   case CFI_Parser<A>::kRegisterInRegister:
     return registers.getRegister((int)savedReg.value);
+
   case CFI_Parser<A>::kRegisterUndefined:
     return 0;
+
+  case CFI_Parser<A>::kRegisterIsPseudo:
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+    return savedReg.value;
+#endif
   case CFI_Parser<A>::kRegisterUnused:
   case CFI_Parser<A>::kRegisterOffsetFromCFA:
     // FIX ME
@@ -145,6 +151,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister(
 #ifndef _LIBUNWIND_TARGET_ARM
     return registers.getFloatRegister((int)savedReg.value);
 #endif
+  case CFI_Parser<A>::kRegisterIsPseudo:
   case CFI_Parser<A>::kRegisterIsExpression:
   case CFI_Parser<A>::kRegisterUnused:
   case CFI_Parser<A>::kRegisterOffsetFromCFA:
@@ -168,6 +175,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
         evaluateExpression((pint_t)savedReg.value, addressSpace,
                             registers, cfa));
 
+  case CFI_Parser<A>::kRegisterIsPseudo:
   case CFI_Parser<A>::kRegisterIsExpression:
   case CFI_Parser<A>::kRegisterUnused:
   case CFI_Parser<A>::kRegisterUndefined:
diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp
index 8e080fb33c5f8..ba40b757ab977 100644
--- a/libunwind/src/DwarfParser.hpp
+++ b/libunwind/src/DwarfParser.hpp
@@ -81,7 +81,8 @@ class CFI_Parser {
     kRegisterOffsetFromCFA,
     kRegisterInRegister,
     kRegisterAtExpression,
-    kRegisterIsExpression
+    kRegisterIsExpression,
+    kRegisterIsPseudo,
   };
   struct RegisterLocation {
     RegisterSavedWhere location;
@@ -794,8 +795,8 @@ bool CFI_Parser<A>::parseFDEInstructions(
         case REGISTERS_ARM64: {
           int64_t value =
               results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x1;
-          results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,
-                                    initialState);
+          results->setRegister(UNW_AARCH64_RA_SIGN_STATE, kRegisterIsPseudo,
+                               value, initialState);
           _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
         } break;
 #endif
@@ -846,8 +847,8 @@ bool CFI_Parser<A>::parseFDEInstructions(
       case DW_CFA_AARCH64_negate_ra_state_with_pc: {
         int64_t value =
             results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3;
-        results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,
-                                  initialState);
+        results->setRegister(UNW_AARCH64_RA_SIGN_STATE, kRegisterIsPseudo,
+                             value, initialState);
         // When using Feat_PAuthLR, the PC value needs to be captured so that
         // during unwinding, the correct PC value is used for 
re-authentication.
         // It is assumed that the CFI is placed before the signing instruction.
diff --git a/libunwind/test/ra_sign_state.pass.cpp 
b/libunwind/test/ra_sign_state.pass.cpp
new file mode 100644
index 0000000000000..9187d039a761b
--- /dev/null
+++ b/libunwind/test/ra_sign_state.pass.cpp
@@ -0,0 +1,164 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// clang-format off
+
+// REQUIRES: target={{aarch64.*}}
+// UNSUPPORTED: target={{.*-windows.*}}
+
+// The libSystem unwinder does not correctly read UNW_AARCH64_RA_SIGN_STATE, at
+// least through OS version 27.0
+// XFAIL: stdlib=apple-libc++ && 
target={{.*}}-apple-{{.*}}{{(11|12|13|14|15|26)(\.\d+)?}}
+// XFAIL: stdlib=apple-libc++ && target={{.*}}-apple-{{.*}}27.0
+
+// clang-format on
+
+#undef NDEBUG
+#include "../src/config.h"
+#include "support/func_bounds.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <libunwind.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <unwind.h>
+
+#if defined(__APPLE__)
+#include <sys/sysctl.h>
+#endif
+#if defined(_LIBUNWIND_HAVE_GETAUXVAL) || defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
+#include <sys/auxv.h>
+#endif
+
+// Note: This test requires FEAT_PAuth (and is setup to pass on other targets).
+
+#if defined(__APPLE__)
+static bool checkHasPAuth() {
+  int has_pauth = 0;
+  size_t size = sizeof(has_pauth);
+  if (sysctlbyname("hw.optional.arm.FEAT_PAuth", &has_pauth, &size, NULL, 0))
+    return false;
+  return has_pauth != 0;
+}
+#elif defined(_LIBUNWIND_HAVE_GETAUXVAL)
+static bool checkHasPAuth() {
+  constexpr unsigned long hwcap_paca = (1UL << 30);
+  unsigned long hwcap = getauxval(AT_HWCAP);
+  return (hwcap & hwcap_paca) != 0;
+}
+#elif defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
+static bool checkHasPAuth() {
+  constexpr unsigned long hwcap_paca = (1UL << 30);
+  unsigned long hwcap = 0;
+  elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap));
+  return (hwcap & hwcap_paca) != 0;
+}
+#else
+static bool checkHasPAuth() {
+  // TODO: Support other platforms.
+  return false;
+}
+#endif
+
+FUNC_BOUNDS_DECL(main_func);
+
+static _Unwind_Reason_Code frame_handler(struct _Unwind_Context *ctx,
+                                         void *arg) {
+  fprintf(stderr, "frame_handler\n");
+  uint64_t ra_sign_state =
+      (uint64_t)_Unwind_GetGR(ctx, UNW_AARCH64_RA_SIGN_STATE);
+
+  fprintf(stderr, "ra_sign_state = 0x%" PRIx64 "\n", ra_sign_state);
+
+  uintptr_t ip = _Unwind_GetIP(ctx);
+
+  fprintf(stderr, "UNW_AARCH64_RA_SIGN_STATE @ 0x%" PRIxPTR " = %" PRIu64 "\n",
+          ip, ra_sign_state);
+
+  if (ip >= (uintptr_t)FUNC_START(main_func) &&
+      ip < (uintptr_t)FUNC_END(main_func)) {
+
+    // Collect the RA from the callee that will return to main.
+    *(uint64_t *)arg = ra_sign_state;
+
+    // Unwind until main is reached, above frames depend on the platform and
+    // architecture.
+    return _URC_END_OF_STACK;
+  }
+
+#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
+  assert(ra_sign_state == 1 || ra_sign_state == 2);
+#endif
+
+  return _URC_NO_REASON;
+}
+
+__attribute__((noinline)) extern "C" uintptr_t get_main_ra_sign_state() {
+  uint64_t sign_state = -1;
+  _Unwind_Backtrace(frame_handler, &sign_state);
+  fprintf(stderr, "get_main_ra_sign_state: sign_state = 0x%" PRIx64 "\n",
+          sign_state);
+  assert((sign_state & 0x3) == sign_state);
+  return sign_state;
+}
+
+__attribute__((noinline)) static uint64_t check_vanilla() {
+  return get_main_ra_sign_state();
+}
+
+__attribute__((naked, target("pauth"))) static uint64_t check_negate() {
+  // clang-format off
+  asm(
+#if !defined(__APPLE__)
+      ".cfi_b_key_frame\n"
+#endif
+      ".cfi_negate_ra_state\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_negate_ra_state\n"
+      "retab");
+  // clang-format on
+}
+
+FUNC_ATTR(main_func) int main(int, char **) {
+  uint64_t ret;
+
+  ret = check_vanilla();
+  fprintf(stderr, "check_vanilla: ret = 0x%" PRIx64 "\n", ret);
+#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
+  assert(ret == 1 || ret == 2);
+#endif
+
+  if (!checkHasPAuth()) {
+    fprintf(stderr, "target does not have FEAT_PAuth\n");
+    return 0;
+  }
+
+  ret = check_negate();
+  fprintf(stderr, "check_negate: ret = 0x%" PRIx64 "\n", ret);
+  assert(ret == 1);
+
+  printf("success\n");
+  return 0;
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to