[lld] [lld] Refactor storage of PAuth ABI core info (PR #141920)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 30 03:53:26 PDT 2025


https://github.com/sivan-shani updated https://github.com/llvm/llvm-project/pull/141920

>From 25ee99e6c6795138093a47933af3f590a6f0fb62 Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Wed, 28 May 2025 13:01:27 +0100
Subject: [PATCH 1/4] [lld][GNU Properties] Refactor storage of PAuth ABI core
 info

Previously, the AArch64 PAuth ABI core values were stored as an ArrayRef<uint8_t>,
introducing unnecessary indirection.

This patch replaces the ArrayRef with two explicit uint64_t fields:
aarch64PauthAbiPlatform and aarch64PauthAbiVersion. This simplifies the
representation and improves readability.

No functional change intended.
---
 lld/ELF/Arch/AArch64.cpp             |  5 +++--
 lld/ELF/Config.h                     |  8 ++++++-
 lld/ELF/Driver.cpp                   | 33 ++++++++++++++++++++--------
 lld/ELF/InputFiles.cpp               |  8 +++++--
 lld/ELF/InputFiles.h                 |  2 +-
 lld/ELF/SyntheticSections.cpp        | 16 ++++++++------
 lld/test/ELF/aarch64-feature-pauth.s |  6 ++---
 7 files changed, 53 insertions(+), 25 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 9538dd4a70bae..3900712cf2312 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -1044,8 +1044,9 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
   // instructions.
 
   if (ctx.arg.zPacPlt) {
-    if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo,
-                     [](uint8_t c) { return c != 0; }))
+    if (ctx.aarch64PauthAbiCoreInfo.has_value() &&
+        (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform != 0 ||
+         ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion != 0))
       pacEntryKind = PEK_Auth;
     else
       pacEntryKind = PEK_AuthHint;
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index f0e9592d85dd6..fcf56cd1d5edb 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -29,6 +29,7 @@
 #include "llvm/Support/GlobPattern.h"
 #include "llvm/Support/TarWriter.h"
 #include <atomic>
+#include <cstdint>
 #include <memory>
 #include <mutex>
 #include <optional>
@@ -139,6 +140,11 @@ enum class GcsPolicy { Implicit, Never, Always };
 // For some options that resemble -z bti-report={none,warning,error}
 enum class ReportPolicy { None, Warning, Error };
 
+struct AArch64PauthAbiCoreInfo {
+  uint64_t aarch64PauthAbiPlatform;
+  uint64_t aarch64PauthAbiVersion;
+};
+
 struct SymbolVersion {
   llvm::StringRef name;
   bool isExternCpp;
@@ -695,7 +701,7 @@ struct Ctx : CommonLinkerContext {
 
   llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &);
 
-  ArrayRef<uint8_t> aarch64PauthAbiCoreInfo;
+  std::optional<AArch64PauthAbiCoreInfo> aarch64PauthAbiCoreInfo;
 };
 
 // The first two elements of versionDefinitions represent VER_NDX_LOCAL and
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 76a37b706c5fa..500d7376404cc 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2841,15 +2841,17 @@ static void readSecurityNotes(Ctx &ctx) {
   StringRef referenceFileName;
   if (ctx.arg.emachine == EM_AARCH64) {
     auto it = llvm::find_if(ctx.objectFiles, [](const ELFFileBase *f) {
-      return !f->aarch64PauthAbiCoreInfo.empty();
+      return f->aarch64PauthAbiCoreInfo.has_value();
     });
     if (it != ctx.objectFiles.end()) {
       ctx.aarch64PauthAbiCoreInfo = (*it)->aarch64PauthAbiCoreInfo;
       referenceFileName = (*it)->getName();
     }
   }
-  bool hasValidPauthAbiCoreInfo = llvm::any_of(
-      ctx.aarch64PauthAbiCoreInfo, [](uint8_t c) { return c != 0; });
+  bool hasValidPauthAbiCoreInfo =
+      ctx.aarch64PauthAbiCoreInfo.has_value() &&
+      (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform != 0 ||
+       ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion != 0);
 
   auto report = [&](ReportPolicy policy) -> ELFSyncStream {
     return {ctx, toDiagLevel(policy)};
@@ -2909,10 +2911,10 @@ static void readSecurityNotes(Ctx &ctx) {
     }
     ctx.arg.andFeatures &= features;
 
-    if (ctx.aarch64PauthAbiCoreInfo.empty())
+    if (!ctx.aarch64PauthAbiCoreInfo)
       continue;
 
-    if (f->aarch64PauthAbiCoreInfo.empty()) {
+    if (!f->aarch64PauthAbiCoreInfo) {
       report(ctx.arg.zPauthReport)
           << f
           << ": -z pauth-report: file does not have AArch64 "
@@ -2921,12 +2923,25 @@ static void readSecurityNotes(Ctx &ctx) {
       continue;
     }
 
-    if (ctx.aarch64PauthAbiCoreInfo != f->aarch64PauthAbiCoreInfo)
-      Err(ctx) << "incompatible values of AArch64 PAuth core info found\n>>> "
+    if (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform !=
+        f->aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform)
+      Err(ctx) << "incompatible AArch64 PAuth Platform Values\n>>> "
                << referenceFileName << ": 0x"
-               << toHex(ctx.aarch64PauthAbiCoreInfo, /*LowerCase=*/true)
+               << toHex(ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform,
+                        /*LowerCase=*/true)
                << "\n>>> " << f << ": 0x"
-               << toHex(f->aarch64PauthAbiCoreInfo, /*LowerCase=*/true);
+               << toHex(f->aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform,
+                        /*LowerCase=*/true);
+
+    if (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion !=
+        f->aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion)
+      Err(ctx) << "incompatible AArch64 PAuth Version Values\n>>> "
+               << referenceFileName << ": 0x"
+               << toHex(ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion,
+                        /*LowerCase=*/true)
+               << "\n>>> " << f << ": 0x"
+               << toHex(f->aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion,
+                        /*LowerCase=*/true);
   }
 
   // Force enable Shadow Stack.
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 5f6d2b6b647ee..73ff437907066 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -950,7 +950,7 @@ static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f,
     } else if (ctx.arg.emachine == EM_AARCH64 &&
                type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) {
       ArrayRef<uint8_t> contents = data ? *data : desc;
-      if (!f.aarch64PauthAbiCoreInfo.empty()) {
+      if (f.aarch64PauthAbiCoreInfo) {
         return void(
             err(contents.data())
             << "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are "
@@ -961,7 +961,11 @@ static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f,
                        "is invalid: expected 16 bytes, but got "
                     << size);
       }
-      f.aarch64PauthAbiCoreInfo = desc;
+      f.aarch64PauthAbiCoreInfo.emplace();
+      f.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform =
+          support::endian::read64<ELFT::Endianness>(&desc[0]);
+      f.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion =
+          support::endian::read64<ELFT::Endianness>(&desc[8]);
     }
 
     // Padding is present in the note descriptor, if necessary.
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 808cb5d24079f..ba844ad18f637 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -241,7 +241,7 @@ class ELFFileBase : public InputFile {
   StringRef sourceFile;
   uint32_t andFeatures = 0;
   bool hasCommonSyms = false;
-  ArrayRef<uint8_t> aarch64PauthAbiCoreInfo;
+  std::optional<AArch64PauthAbiCoreInfo> aarch64PauthAbiCoreInfo;
 };
 
 // .o file.
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 46591e909ba4f..f777bc20b8fcc 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -344,11 +344,13 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
     offset += 16;
   }
 
-  if (!ctx.aarch64PauthAbiCoreInfo.empty()) {
+  if (ctx.aarch64PauthAbiCoreInfo) {
     write32(ctx, buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH);
-    write32(ctx, buf + offset + 4, ctx.aarch64PauthAbiCoreInfo.size());
-    memcpy(buf + offset + 8, ctx.aarch64PauthAbiCoreInfo.data(),
-           ctx.aarch64PauthAbiCoreInfo.size());
+    write32(ctx, buf + offset + 4, sizeof(uint64_t) * 2);
+    write64(ctx, buf + offset + 8,
+            ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform);
+    write64(ctx, buf + offset + 16,
+            ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion);
   }
 }
 
@@ -356,8 +358,8 @@ size_t GnuPropertySection::getSize() const {
   uint32_t contentSize = 0;
   if (ctx.arg.andFeatures != 0)
     contentSize += ctx.arg.is64 ? 16 : 12;
-  if (!ctx.aarch64PauthAbiCoreInfo.empty())
-    contentSize += 4 + 4 + ctx.aarch64PauthAbiCoreInfo.size();
+  if (ctx.aarch64PauthAbiCoreInfo)
+    contentSize += 4 + 4 + sizeof(uint64_t) * 2;
   assert(contentSize != 0);
   return contentSize + 16;
 }
@@ -4959,7 +4961,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
   ctx.in.iplt = std::make_unique<IpltSection>(ctx);
   add(*ctx.in.iplt);
 
-  if (ctx.arg.andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty()) {
+  if (ctx.arg.andFeatures || ctx.aarch64PauthAbiCoreInfo) {
     ctx.in.gnuProperty = std::make_unique<GnuPropertySection>(ctx);
     add(*ctx.in.gnuProperty);
   }
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index bc58f69d32f2b..15ad6a802c680 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -12,9 +12,9 @@
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o
 # RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s
 
-# ERR1:      error: incompatible values of AArch64 PAuth core info found
-# ERR1-NEXT: >>> tag1.o: 0x2a000000000000000{{1|2}}00000000000000
-# ERR1-NEXT: >>> tag2.o: 0x2a000000000000000{{1|2}}00000000000000
+# ERR1:      error: incompatible AArch64 PAuth Version Values
+# ERR1-NEXT: >>> tag1.o: 0x01
+# ERR1-NEXT: >>> tag2.o: 0x02
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o
 # RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s

>From fe8a6c347e0349ee5b4e1466813ec2bab3d3b01f Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Thu, 29 May 2025 15:43:28 +0100
Subject: [PATCH 2/4] Address general code review feedback

- Remove redundant include
- Rename fields in AArch64PauthAbiCoreInfo
- Simplify assignment using direct initialization
---
 lld/ELF/Arch/AArch64.cpp      |  4 ++--
 lld/ELF/Config.h              |  5 ++---
 lld/ELF/Driver.cpp            | 23 +++++++++++------------
 lld/ELF/InputFiles.cpp        |  8 +++-----
 lld/ELF/SyntheticSections.cpp |  6 ++----
 5 files changed, 20 insertions(+), 26 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 3900712cf2312..0a86da089709b 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -1045,8 +1045,8 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
 
   if (ctx.arg.zPacPlt) {
     if (ctx.aarch64PauthAbiCoreInfo.has_value() &&
-        (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform != 0 ||
-         ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion != 0))
+        (ctx.aarch64PauthAbiCoreInfo->platform != 0 ||
+         ctx.aarch64PauthAbiCoreInfo->version != 0))
       pacEntryKind = PEK_Auth;
     else
       pacEntryKind = PEK_AuthHint;
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index fcf56cd1d5edb..a141d4d245f92 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -29,7 +29,6 @@
 #include "llvm/Support/GlobPattern.h"
 #include "llvm/Support/TarWriter.h"
 #include <atomic>
-#include <cstdint>
 #include <memory>
 #include <mutex>
 #include <optional>
@@ -141,8 +140,8 @@ enum class GcsPolicy { Implicit, Never, Always };
 enum class ReportPolicy { None, Warning, Error };
 
 struct AArch64PauthAbiCoreInfo {
-  uint64_t aarch64PauthAbiPlatform;
-  uint64_t aarch64PauthAbiVersion;
+  uint64_t platform;
+  uint64_t version;
 };
 
 struct SymbolVersion {
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 500d7376404cc..368cdf53eb321 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2848,10 +2848,9 @@ static void readSecurityNotes(Ctx &ctx) {
       referenceFileName = (*it)->getName();
     }
   }
-  bool hasValidPauthAbiCoreInfo =
-      ctx.aarch64PauthAbiCoreInfo.has_value() &&
-      (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform != 0 ||
-       ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion != 0);
+  bool hasValidPauthAbiCoreInfo = ctx.aarch64PauthAbiCoreInfo.has_value() &&
+                                  (ctx.aarch64PauthAbiCoreInfo->platform != 0 ||
+                                   ctx.aarch64PauthAbiCoreInfo->version != 0);
 
   auto report = [&](ReportPolicy policy) -> ELFSyncStream {
     return {ctx, toDiagLevel(policy)};
@@ -2923,24 +2922,24 @@ static void readSecurityNotes(Ctx &ctx) {
       continue;
     }
 
-    if (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform !=
-        f->aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform)
+    if (ctx.aarch64PauthAbiCoreInfo->platform !=
+        f->aarch64PauthAbiCoreInfo->platform)
       Err(ctx) << "incompatible AArch64 PAuth Platform Values\n>>> "
                << referenceFileName << ": 0x"
-               << toHex(ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform,
+               << toHex(ctx.aarch64PauthAbiCoreInfo->platform,
                         /*LowerCase=*/true)
                << "\n>>> " << f << ": 0x"
-               << toHex(f->aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform,
+               << toHex(f->aarch64PauthAbiCoreInfo->platform,
                         /*LowerCase=*/true);
 
-    if (ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion !=
-        f->aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion)
+    if (ctx.aarch64PauthAbiCoreInfo->version !=
+        f->aarch64PauthAbiCoreInfo->version)
       Err(ctx) << "incompatible AArch64 PAuth Version Values\n>>> "
                << referenceFileName << ": 0x"
-               << toHex(ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion,
+               << toHex(ctx.aarch64PauthAbiCoreInfo->version,
                         /*LowerCase=*/true)
                << "\n>>> " << f << ": 0x"
-               << toHex(f->aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion,
+               << toHex(f->aarch64PauthAbiCoreInfo->version,
                         /*LowerCase=*/true);
   }
 
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 73ff437907066..817af15a841ec 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -961,11 +961,9 @@ static void parseGnuPropertyNote(Ctx &ctx, ELFFileBase &f,
                        "is invalid: expected 16 bytes, but got "
                     << size);
       }
-      f.aarch64PauthAbiCoreInfo.emplace();
-      f.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform =
-          support::endian::read64<ELFT::Endianness>(&desc[0]);
-      f.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion =
-          support::endian::read64<ELFT::Endianness>(&desc[8]);
+      f.aarch64PauthAbiCoreInfo = {
+          support::endian::read64<ELFT::Endianness>(&desc[0]),
+          support::endian::read64<ELFT::Endianness>(&desc[8])};
     }
 
     // Padding is present in the note descriptor, if necessary.
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index f777bc20b8fcc..70d7e96f3d9cd 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -347,10 +347,8 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
   if (ctx.aarch64PauthAbiCoreInfo) {
     write32(ctx, buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH);
     write32(ctx, buf + offset + 4, sizeof(uint64_t) * 2);
-    write64(ctx, buf + offset + 8,
-            ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiPlatform);
-    write64(ctx, buf + offset + 16,
-            ctx.aarch64PauthAbiCoreInfo->aarch64PauthAbiVersion);
+    write64(ctx, buf + offset + 8, ctx.aarch64PauthAbiCoreInfo->platform);
+    write64(ctx, buf + offset + 16, ctx.aarch64PauthAbiCoreInfo->version);
   }
 }
 

>From e29b15b62c1c3461707753d7d2cdea5da37a4291 Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Thu, 29 May 2025 17:24:07 +0100
Subject: [PATCH 3/4] Add helper methods to AArch64PauthAbiCoreInfo

- Convert AArch64PauthAbiCoreInfo to a struct with isValid(), size(), and comparison operators.
- Simplify comparison logic in readSecurityNotes() using operator!=.
---
 lld/ELF/Arch/AArch64.cpp             |  4 +--
 lld/ELF/Config.h                     |  8 ++++++
 lld/ELF/Driver.cpp                   | 37 +++++++++++-----------------
 lld/ELF/SyntheticSections.cpp        |  2 +-
 lld/test/ELF/aarch64-feature-pauth.s |  6 ++++-
 5 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 0a86da089709b..30ce41e4effa8 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -1044,9 +1044,7 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
   // instructions.
 
   if (ctx.arg.zPacPlt) {
-    if (ctx.aarch64PauthAbiCoreInfo.has_value() &&
-        (ctx.aarch64PauthAbiCoreInfo->platform != 0 ||
-         ctx.aarch64PauthAbiCoreInfo->version != 0))
+    if (ctx.aarch64PauthAbiCoreInfo && ctx.aarch64PauthAbiCoreInfo->isValid())
       pacEntryKind = PEK_Auth;
     else
       pacEntryKind = PEK_AuthHint;
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index a141d4d245f92..7269be0f24816 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -142,6 +142,14 @@ enum class ReportPolicy { None, Warning, Error };
 struct AArch64PauthAbiCoreInfo {
   uint64_t platform;
   uint64_t version;
+  bool isValid() const { return platform || version; }
+  static constexpr size_t size() { return sizeof(platform) + sizeof(version); }
+  bool operator==(const AArch64PauthAbiCoreInfo &other) const {
+    return platform == other.platform && version == other.version;
+  }
+  bool operator!=(const AArch64PauthAbiCoreInfo &other) const {
+    return !(*this == other);
+  }
 };
 
 struct SymbolVersion {
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 368cdf53eb321..da51d9fab8d07 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2848,9 +2848,8 @@ static void readSecurityNotes(Ctx &ctx) {
       referenceFileName = (*it)->getName();
     }
   }
-  bool hasValidPauthAbiCoreInfo = ctx.aarch64PauthAbiCoreInfo.has_value() &&
-                                  (ctx.aarch64PauthAbiCoreInfo->platform != 0 ||
-                                   ctx.aarch64PauthAbiCoreInfo->version != 0);
+  bool hasValidPauthAbiCoreInfo =
+      ctx.aarch64PauthAbiCoreInfo && ctx.aarch64PauthAbiCoreInfo->isValid();
 
   auto report = [&](ReportPolicy policy) -> ELFSyncStream {
     return {ctx, toDiagLevel(policy)};
@@ -2922,25 +2921,19 @@ static void readSecurityNotes(Ctx &ctx) {
       continue;
     }
 
-    if (ctx.aarch64PauthAbiCoreInfo->platform !=
-        f->aarch64PauthAbiCoreInfo->platform)
-      Err(ctx) << "incompatible AArch64 PAuth Platform Values\n>>> "
-               << referenceFileName << ": 0x"
-               << toHex(ctx.aarch64PauthAbiCoreInfo->platform,
-                        /*LowerCase=*/true)
-               << "\n>>> " << f << ": 0x"
-               << toHex(f->aarch64PauthAbiCoreInfo->platform,
-                        /*LowerCase=*/true);
-
-    if (ctx.aarch64PauthAbiCoreInfo->version !=
-        f->aarch64PauthAbiCoreInfo->version)
-      Err(ctx) << "incompatible AArch64 PAuth Version Values\n>>> "
-               << referenceFileName << ": 0x"
-               << toHex(ctx.aarch64PauthAbiCoreInfo->version,
-                        /*LowerCase=*/true)
-               << "\n>>> " << f << ": 0x"
-               << toHex(f->aarch64PauthAbiCoreInfo->version,
-                        /*LowerCase=*/true);
+    if (ctx.aarch64PauthAbiCoreInfo != f->aarch64PauthAbiCoreInfo)
+      Err(ctx)
+          << "incompatible values of AArch64 PAuth core info found\n"
+          << "platform:\n"
+          << ">>> " << referenceFileName << ": 0x"
+          << toHex(ctx.aarch64PauthAbiCoreInfo->platform, /*LowerCase=*/true)
+          << "\n>>> " << f << ": 0x"
+          << toHex(f->aarch64PauthAbiCoreInfo->platform, /*LowerCase=*/true)
+          << "\nversion:\n"
+          << ">>> " << referenceFileName << ": 0x"
+          << toHex(ctx.aarch64PauthAbiCoreInfo->version, /*LowerCase=*/true)
+          << "\n>>> " << f << ": 0x"
+          << toHex(f->aarch64PauthAbiCoreInfo->version, /*LowerCase=*/true);
   }
 
   // Force enable Shadow Stack.
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 70d7e96f3d9cd..fcea14e8a9542 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -346,7 +346,7 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
 
   if (ctx.aarch64PauthAbiCoreInfo) {
     write32(ctx, buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH);
-    write32(ctx, buf + offset + 4, sizeof(uint64_t) * 2);
+    write32(ctx, buf + offset + 4, AArch64PauthAbiCoreInfo::size());
     write64(ctx, buf + offset + 8, ctx.aarch64PauthAbiCoreInfo->platform);
     write64(ctx, buf + offset + 16, ctx.aarch64PauthAbiCoreInfo->version);
   }
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index 15ad6a802c680..e8c900b9cb134 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -12,7 +12,11 @@
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o
 # RUN: not ld.lld tag1.o tag1a.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s
 
-# ERR1:      error: incompatible AArch64 PAuth Version Values
+# ERR1:      error: incompatible values of AArch64 PAuth core info found
+# ERR1-NEXT: platform:
+# ERR1-NEXT: >>> tag1.o: 0x2a
+# ERR1-NEXT: >>> tag2.o: 0x2a
+# ERR1-NEXT: version:
 # ERR1-NEXT: >>> tag1.o: 0x01
 # ERR1-NEXT: >>> tag2.o: 0x02
 

>From f962335a61a6fb6a7f0a230a5312fb1410379c9a Mon Sep 17 00:00:00 2001
From: Sivan Shani <sivan.shani at arm.com>
Date: Fri, 30 May 2025 11:52:52 +0100
Subject: [PATCH 4/4] Address review feedback: clarify core info usage and use
 size() helper - Added comments explaining the semantics of
 AArch64PauthAbiCoreInfo and the reserved (0, 0) value. - Replaced hardcoded
 sizeof(uint64_t) * 2 with AArch64PauthAbiCoreInfo::size().

---
 lld/ELF/Config.h              | 4 ++++
 lld/ELF/SyntheticSections.cpp | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 7269be0f24816..d8d9e3fd1699e 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -139,9 +139,13 @@ enum class GcsPolicy { Implicit, Never, Always };
 // For some options that resemble -z bti-report={none,warning,error}
 enum class ReportPolicy { None, Warning, Error };
 
+// Describes the signing schema for a file using the PAuth ABI extension.
+// Two files are considered compatible when both `platform` and `version` match.
+// The pair (0, 0) is reserved to indicate incompatibility with the PAuth ABI.
 struct AArch64PauthAbiCoreInfo {
   uint64_t platform;
   uint64_t version;
+  // Returns true if the core info is not the reserved (0, 0) value.
   bool isValid() const { return platform || version; }
   static constexpr size_t size() { return sizeof(platform) + sizeof(version); }
   bool operator==(const AArch64PauthAbiCoreInfo &other) const {
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index fcea14e8a9542..eb902767746de 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -357,7 +357,7 @@ size_t GnuPropertySection::getSize() const {
   if (ctx.arg.andFeatures != 0)
     contentSize += ctx.arg.is64 ? 16 : 12;
   if (ctx.aarch64PauthAbiCoreInfo)
-    contentSize += 4 + 4 + sizeof(uint64_t) * 2;
+    contentSize += 4 + 4 + AArch64PauthAbiCoreInfo::size();
   assert(contentSize != 0);
   return contentSize + 16;
 }



More information about the llvm-commits mailing list