[lld] [PAC][lld] Use braa instr in PAC PLT sequence with valid PAuth core info (PR #113945)

Daniil Kovalev via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 15 00:04:43 PST 2024


https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/113945

>From cc6c7c482dc05baaea052aee638e86ae81540406 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 28 Oct 2024 21:23:54 +0300
Subject: [PATCH 1/3] [PAC][lld] Use braa instr in PAC PLT sequence with valid
 PAuth core info

Assume PAC instructions being supported with PAuth core info different
from (0,0). Given that, `autia1716; br x17` can be replaced with
`braa x17, x16; nop`.
---
 lld/ELF/Arch/AArch64.cpp             | 19 +++++++++++++++----
 lld/test/ELF/aarch64-feature-pauth.s | 10 ++++++----
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index c4334a6b1a1012..321bdb638ccabd 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -999,7 +999,9 @@ class AArch64BtiPac final : public AArch64 {
 
 private:
   bool btiHeader; // bti instruction needed in PLT Header and Entry
-  bool pacEntry;  // autia1716 instruction needed in PLT Entry
+  bool pacEntry;  // Authenticated branch needed in PLT Entry
+  bool pacUseHint =
+      true; // Use hint space instructions for authenticated branch in PLT entry
 };
 } // namespace
 
@@ -1016,6 +1018,10 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
   // from properties in the objects, so we use the command line flag.
   pacEntry = ctx.arg.zPacPlt;
 
+  if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo,
+                   [](uint8_t c) { return c != 0; }))
+    pacUseHint = false;
+
   if (btiHeader || pacEntry) {
     pltEntrySize = 24;
     ipltEntrySize = 24;
@@ -1066,9 +1072,13 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
       0x11, 0x02, 0x40, 0xf9,  // ldr  x17, [x16, Offset(&(.got.plt[n]))]
       0x10, 0x02, 0x00, 0x91   // add  x16, x16, Offset(&(.got.plt[n]))
   };
+  const uint8_t pacHintBr[] = {
+      0x9f, 0x21, 0x03, 0xd5, // autia1716
+      0x20, 0x02, 0x1f, 0xd6  // br   x17
+  };
   const uint8_t pacBr[] = {
-      0x9f, 0x21, 0x03, 0xd5,  // autia1716
-      0x20, 0x02, 0x1f, 0xd6   // br   x17
+      0x30, 0x0a, 0x1f, 0xd7, // braa x17, x16
+      0x1f, 0x20, 0x03, 0xd5  // nop
   };
   const uint8_t stdBr[] = {
       0x20, 0x02, 0x1f, 0xd6,  // br   x17
@@ -1097,7 +1107,8 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
   relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);
 
   if (pacEntry)
-    memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr));
+    memcpy(buf + sizeof(addrInst), (pacUseHint ? pacHintBr : pacBr),
+           sizeof(pacUseHint ? pacHintBr : pacBr));
   else
     memcpy(buf + sizeof(addrInst), stdBr, sizeof(stdBr));
   if (!hasBti)
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index 3150c130d460f5..c50f38f4a7c975 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -56,8 +56,8 @@
 
 # PACPLTTAG:      0x0000000070000003 (AARCH64_PAC_PLT)
 
-# RUN: llvm-objdump -d pacplt-nowarn | FileCheck --check-prefix PACPLT -DA=10380 -DB=478 -DC=480 %s
-# RUN: llvm-objdump -d pacplt-warn   | FileCheck --check-prefix PACPLT -DA=10390 -DB=488 -DC=490 %s
+# RUN: llvm-objdump -d pacplt-nowarn | FileCheck --check-prefixes=PACPLT,NOHINT -DA=10380 -DB=478 -DC=480 %s
+# RUN: llvm-objdump -d pacplt-warn   | FileCheck --check-prefixes=PACPLT,HINT   -DA=10390 -DB=488 -DC=490 %s
 
 # PACPLT: Disassembly of section .text:
 # PACPLT:      <func2>:
@@ -77,8 +77,10 @@
 # PACPLT-NEXT:     adrp    x16, 0x30000 <func3+0x30000>
 # PACPLT-NEXT:     ldr     x17, [x16, #0x[[C]]]
 # PACPLT-NEXT:     add     x16, x16, #0x[[C]]
-# PACPLT-NEXT:     autia1716
-# PACPLT-NEXT:     br      x17
+# NOHINT-NEXT:     braa    x17, x16
+# NOHINT-NEXT:     nop
+# HINT-NEXT:       autia1716
+# HINT-NEXT:       br      x17
 # PACPLT-NEXT:     nop
 
 #--- abi-tag-short.s

>From 13875e750ef9e7784aedf1cda12a73ad33fb3544 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Fri, 1 Nov 2024 14:20:44 +0300
Subject: [PATCH 2/3] Address review comments

---
 lld/ELF/Arch/AArch64.cpp | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 321bdb638ccabd..e76d53f2adaaed 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -999,9 +999,11 @@ class AArch64BtiPac final : public AArch64 {
 
 private:
   bool btiHeader; // bti instruction needed in PLT Header and Entry
-  bool pacEntry;  // Authenticated branch needed in PLT Entry
-  bool pacUseHint =
-      true; // Use hint space instructions for authenticated branch in PLT entry
+  enum {
+    PEK_NoAuth,
+    PEK_AuthHint, // use autia1716 instr for authenticated branch in PLT entry
+    PEK_Auth,     // use braa instr for authenticated branch in PLT entry
+  } pacEntryKind;
 };
 } // namespace
 
@@ -1016,13 +1018,18 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
   // relocations.
   // The PAC PLT entries require dynamic loader support and this isn't known
   // from properties in the objects, so we use the command line flag.
-  pacEntry = ctx.arg.zPacPlt;
 
-  if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo,
-                   [](uint8_t c) { return c != 0; }))
-    pacUseHint = false;
+  if (ctx.arg.zPacPlt) {
+    if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo,
+                     [](uint8_t c) { return c != 0; }))
+      pacEntryKind = PEK_Auth;
+    else
+      pacEntryKind = PEK_AuthHint;
+  } else {
+    pacEntryKind = PEK_NoAuth;
+  }
 
-  if (btiHeader || pacEntry) {
+  if (btiHeader || (pacEntryKind != PEK_NoAuth)) {
     pltEntrySize = 24;
     ipltEntrySize = 24;
   }
@@ -1106,9 +1113,10 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
   relocateNoSym(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr);
   relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);
 
-  if (pacEntry)
-    memcpy(buf + sizeof(addrInst), (pacUseHint ? pacHintBr : pacBr),
-           sizeof(pacUseHint ? pacHintBr : pacBr));
+  if (pacEntryKind != PEK_NoAuth)
+    memcpy(buf + sizeof(addrInst),
+           pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr,
+           sizeof(pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr));
   else
     memcpy(buf + sizeof(addrInst), stdBr, sizeof(stdBr));
   if (!hasBti)

>From 3d1670d893e0ae98ee96ad4a73272d86d3fb3c5d Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Sun, 10 Nov 2024 19:52:31 +0300
Subject: [PATCH 3/3] Add a comment

---
 lld/ELF/Arch/AArch64.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index e76d53f2adaaed..c64a0dbe8bd62b 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -1018,6 +1018,9 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
   // relocations.
   // The PAC PLT entries require dynamic loader support and this isn't known
   // from properties in the objects, so we use the command line flag.
+  // By default we only use hint-space instructions, but if we detect the
+  // PAuthABI, which requires v8.3-A, we can use the non-hint space
+  // instructions.
 
   if (ctx.arg.zPacPlt) {
     if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo,



More information about the llvm-commits mailing list