================
@@ -1823,9 +1826,127 @@ extern "C" void *__libunwind_shstk_get_jump_target() {
 #endif
 
 class _LIBUNWIND_HIDDEN Registers_arm64 {
+  struct GPRs;
+
+private:
+  /// The program counter is used effectively as a return address
+  /// when the context is restored therefore protect it with PAC.
+  /// The base address of the context is used with the A key for
+  /// authentication and signing. Return address authentication is
+  /// still managed according to the unwind info. In some cases
+  /// the LR contains significant bits in the space for the PAC bits the
+  /// value of the PC is stored in 2 halfs and each signed.
+  inline uint64_t getDiscriminator() const {
+    return reinterpret_cast<uint64_t>(this);
+  }
+#if defined(_LIBUNWIND_AARCH64_PC_PROTECTION)
+#if defined(_LIBUNWIND_PTRAUTH_AVAILABLE)
+/// Use Pointer Authentication Intrinsics when available.
+#define __libunwind_ptrauth_auth_data(__value, __key, __discriminator)         
\
+  ptrauth_auth_data(__value, __key, __discriminator)
+#define __libunwind_ptrauth_auth_and_resign(pointer, oldKey, oldDiscriminator, 
\
+                                            newKey, newDiscriminator)          
\
+  ptrauth_auth_and_resign(pointer, oldKey, oldDiscriminator, newKey,           
\
+                          newDiscriminator)
+#define __libunwind_ptrauth_sign_unauthenticated(__value, __key, __data)       
\
+  ptrauth_sign_unauthenticated(__value, __key, __data)
+#else // !_LIBUNWIND_PTRAUTH_AVAILABLE
+  typedef enum {
+    ptrauth_key_asia = 0,
+  } ptrauth_key;
+  /// Using only the NOP space compatible instructions. FPAC might not be
+  /// available on the target so a manual check is added.
+  inline void *__libunwind_ptrauth_strip(void *__value,
+                                         ptrauth_key __key) const {
+    assert(__key == ptrauth_key_asia && "Only A key is supported");
+    void *__return = 0;
+    asm("mov   x30, %[__value]      \r\n"
+        "hint  0x7                  \r\n" // xpaclri
+        "mov   %[__return], x30     \r\n"
+        : [__return] "+r"(__return)
+        : [__value] "r"(__value)
+        : "x30");
+    return __return;
+  }
+
+  inline void *__libunwind_ptrauth_auth_data(void *__value, ptrauth_key __key,
+                                             uint64_t __discriminator) const {
+    assert(__key == ptrauth_key_asia && "Only A key is supported");
+    register void *x17 __asm("x17") = __value;
+    register uintptr_t x16 __asm("x16") = __discriminator;
+    asm("hint  0xc" // autia1716
+        : "+r"(x17)
+        : "r"(x16)
+        :);
+    if (x17 != __libunwind_ptrauth_strip(__value, __key))
+      _LIBUNWIND_ABORT("ptrauth authentication failure");
+    return x17;
+  }
+
+  inline void *
+  __libunwind_ptrauth_sign_unauthenticated(void *__value, ptrauth_key __key,
+                                           uint64_t __discriminator) const {
+    assert(__key == ptrauth_key_asia && "Only A key is supported");
+    register void *x17 __asm("x17") = __value;
+    register uint64_t x16 __asm("x16") = __discriminator;
+    asm("hint 0x8" : "+r"(x17) : "r"(x16));
+    return x17;
+  }
+
+  inline void *__libunwind_ptrauth_auth_and_resign(
+      void *pointer, ptrauth_key oldKey, uint64_t oldDiscriminator,
+      ptrauth_key newKey, uint64_t newDiscriminator) const {
+    return __libunwind_ptrauth_sign_unauthenticated(
+        __libunwind_ptrauth_auth_data(pointer, oldKey, oldDiscriminator),
+        newKey, newDiscriminator);
+  }
+#endif
+  // Authenticate the currently stored PC and return it's raw value.
+  inline uint64_t authPC(const struct GPRs *gprs,
+                         uint64_t discriminator) const {
+    uint64_t lower = (uint64_t)__libunwind_ptrauth_auth_data(
+        (void *)gprs->__pc, ptrauth_key_asia, discriminator);
+    uint64_t upper = (uint64_t)__libunwind_ptrauth_auth_data(
+        (void *)gprs->__pc2, ptrauth_key_asia, discriminator);
+    return (upper << 32) | lower;
+  }
+
+  // Sign and store the new PC.
+  inline void updatePC(uint64_t value) {
----------------
DanielKristofKiss wrote:

This shouldn't manifest as a function as only internally used and should be 
always inlined, could be improved. 

```suggestion
__attribute__((always_inline))
  inline void updatePC(uint64_t value) {
```

https://github.com/llvm/llvm-project/pull/113368
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to