[lld] [lld][AArch64][ELF][PAC] Support AUTH relocations and AUTH ELF marking (PR #72714)

Daniil Kovalev via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 18 09:15:24 PDT 2024


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

>From c493d78e6c482bb530189de05b79e7082a224fab Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 28 Sep 2023 03:14:35 +0300
Subject: [PATCH 01/23] [lld][AArch64][ELF][PAC] Support AUTH relocations and
 AUTH ELF marking

This patch adds lld support for:

- Dynamic R_AARCH64_AUTH_* relocations (including RELR compressed AUTH
  relocations) as described here:
  https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#auth-variant-dynamic-relocations

- .note.AARCH64-PAUTH-ABI-tag section as defined here
  https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking

Co-authored-by: Peter Collingbourne <peter at pcc.me.uk>
---
 lld/ELF/Arch/AArch64.cpp             |   5 +
 lld/ELF/Config.h                     |   4 +
 lld/ELF/Driver.cpp                   |  57 +++++++++-
 lld/ELF/InputFiles.cpp               |  44 ++++++++
 lld/ELF/InputFiles.h                 |   1 +
 lld/ELF/Relocations.cpp              |  26 +++++
 lld/ELF/SyntheticSections.cpp        |  44 ++++++--
 lld/ELF/SyntheticSections.h          |  19 +++-
 lld/ELF/Writer.cpp                   |  17 +++
 lld/test/ELF/aarch64-feature-pauth.s |  83 ++++++++++++++
 lld/test/ELF/aarch64-ptrauth.s       | 156 +++++++++++++++++++++++++++
 11 files changed, 445 insertions(+), 11 deletions(-)
 create mode 100644 lld/test/ELF/aarch64-feature-pauth.s
 create mode 100644 lld/test/ELF/aarch64-ptrauth.s

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 048f0ec30ebd28..6828d3f57c10e8 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -112,6 +112,7 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
   case R_AARCH64_MOVW_UABS_G2:
   case R_AARCH64_MOVW_UABS_G2_NC:
   case R_AARCH64_MOVW_UABS_G3:
+  case R_AARCH64_AUTH_ABS64:
     return R_ABS;
   case R_AARCH64_TLSDESC_ADR_PAGE21:
     return R_AARCH64_TLSDESC_PAGE;
@@ -395,6 +396,10 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
   case R_AARCH64_PREL64:
     write64(loc, val);
     break;
+  case R_AARCH64_AUTH_ABS64:
+    checkIntUInt(loc, val, 32, rel);
+    write32(loc, val);
+    break;
   case R_AARCH64_ADD_ABS_LO12_NC:
     or32AArch64Imm(loc, val);
     break;
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 56229334f9a44a..1b633a79842769 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -187,6 +187,7 @@ struct Config {
   llvm::StringRef cmseOutputLib;
   StringRef zBtiReport = "none";
   StringRef zCetReport = "none";
+  StringRef zPauthReport = "none";
   llvm::StringRef ltoBasicBlockSections;
   std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
   llvm::StringRef thinLTOPrefixReplaceOld;
@@ -275,6 +276,7 @@ struct Config {
   bool relocatable;
   bool relrGlibc = false;
   bool relrPackDynRelocs = false;
+  bool relrPackAuthDynRelocs = false;
   llvm::DenseSet<llvm::StringRef> saveTempsArgs;
   llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
   bool singleRoRx;
@@ -492,6 +494,8 @@ struct Ctx {
   void reset();
 
   llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &);
+
+  SmallVector<uint8_t, 0> aarch64PauthAbiTag;
 };
 
 LLVM_LIBRARY_VISIBILITY extern Ctx ctx;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 6bef09eeca015a..4e8e9eb86ecf77 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -65,6 +65,7 @@
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/raw_ostream.h"
+#include <algorithm>
 #include <cstdlib>
 #include <tuple>
 #include <utility>
@@ -459,6 +460,8 @@ static void checkOptions() {
       error("-z force-bti only supported on AArch64");
     if (config->zBtiReport != "none")
       error("-z bti-report only supported on AArch64");
+    if (config->zPauthReport != "none")
+      error("-z pauth-report only supported on AArch64");
   }
 
   if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
@@ -558,6 +561,7 @@ constexpr const char *knownZFlags[] = {
     "nognustack",
     "nokeep-text-section-prefix",
     "nopack-relative-relocs",
+    "nopack-relative-auth-relocs",
     "norelro",
     "noseparate-code",
     "nostart-stop-gc",
@@ -566,6 +570,7 @@ constexpr const char *knownZFlags[] = {
     "origin",
     "pac-plt",
     "pack-relative-relocs",
+    "pack-relative-auth-relocs",
     "rel",
     "rela",
     "relro",
@@ -583,7 +588,7 @@ constexpr const char *knownZFlags[] = {
 static bool isKnownZFlag(StringRef s) {
   return llvm::is_contained(knownZFlags, s) ||
          s.starts_with("common-page-size=") || s.starts_with("bti-report=") ||
-         s.starts_with("cet-report=") ||
+         s.starts_with("cet-report=") || s.starts_with("pauth-report=") ||
          s.starts_with("dead-reloc-in-nonalloc=") ||
          s.starts_with("max-page-size=") || s.starts_with("stack-size=") ||
          s.starts_with("start-stop-visibility=");
@@ -1514,7 +1519,8 @@ static void readConfigs(opt::InputArgList &args) {
   }
 
   auto reports = {std::make_pair("bti-report", &config->zBtiReport),
-                  std::make_pair("cet-report", &config->zCetReport)};
+                  std::make_pair("cet-report", &config->zCetReport),
+                  std::make_pair("pauth-report", &config->zPauthReport)};
   for (opt::Arg *arg : args.filtered(OPT_z)) {
     std::pair<StringRef, StringRef> option =
         StringRef(arg->getValue()).split('=');
@@ -1671,6 +1677,9 @@ static void readConfigs(opt::InputArgList &args) {
         getPackDynRelocs(args);
   }
 
+  config->relrPackAuthDynRelocs = getZFlag(
+      args, "pack-relative-auth-relocs", "nopack-relative-auth-relocs", false);
+
   if (auto *arg = args.getLastArg(OPT_symbol_ordering_file)){
     if (args.hasArg(OPT_call_graph_ordering_file))
       error("--symbol-ordering-file and --call-graph-order-file "
@@ -2639,6 +2648,47 @@ static uint32_t getAndFeatures() {
   return ret;
 }
 
+static void getAarch64PauthInfo() {
+  if (ctx.objectFiles.empty())
+    return;
+
+  auto NonEmptyIt = std::find_if(
+      ctx.objectFiles.begin(), ctx.objectFiles.end(),
+      [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); });
+  if (NonEmptyIt == ctx.objectFiles.end())
+    return;
+
+  ctx.aarch64PauthAbiTag = (*NonEmptyIt)->aarch64PauthAbiTag;
+  StringRef F1 = (*NonEmptyIt)->getName();
+  for (ELFFileBase *F : ArrayRef(ctx.objectFiles)) {
+    StringRef F2 = F->getName();
+    const SmallVector<uint8_t, 0> &D1 = ctx.aarch64PauthAbiTag;
+    const SmallVector<uint8_t, 0> &D2 = F->aarch64PauthAbiTag;
+    if (D1.empty() != D2.empty()) {
+      auto Helper = [](StringRef Report, const Twine &Msg) {
+        if (Report == "warning")
+          warn(Msg);
+        else if (Report == "error")
+          error(Msg);
+      };
+
+      Helper(config->zPauthReport,
+             (D1.empty() ? F1.str() : F2.str()) +
+                 " has no AArch64 PAuth compatibility info while " +
+                 (D1.empty() ? F2.str() : F1.str()) +
+                 " has one; either all or no input files must have it");
+    }
+
+    if (!D1.empty() && !D2.empty() &&
+        !std::equal(D1.begin(), D1.end(), D2.begin(), D2.end()))
+      errorOrWarn(
+          "incompatible values of AArch64 PAuth compatibility info found"
+          "\n" +
+          F1 + ": 0x" + toHex(ArrayRef(D1.data(), D1.size())) + "\n" + F2 +
+          ": 0x" + toHex(ArrayRef(D2.data(), D2.size())));
+  }
+}
+
 static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) {
   switch (file->ekind) {
   case ELF32LEKind:
@@ -2976,6 +3026,9 @@ void LinkerDriver::link(opt::InputArgList &args) {
   // contain a hint to tweak linker's and loader's behaviors.
   config->andFeatures = getAndFeatures();
 
+  if (config->emachine == EM_AARCH64)
+    getAarch64PauthInfo();
+
   // The Target instance handles target-specific stuff, such as applying
   // relocations or writing a PLT section. It also contains target-dependent
   // values such as a default image base address.
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index cc2c5916e05c22..44c8050f2c967a 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -962,6 +962,44 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
   return featuresSet;
 }
 
+// Extract compatibility info for aarch64 pointer authentication from the
+// .note.AARCH64-PAUTH-ABI-tag section and write it to the corresponding ObjFile
+// field. See the following ABI documentation:
+// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking
+template <class ELFT>
+static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile<ELFT> &f) {
+  using Elf_Nhdr = typename ELFT::Nhdr;
+  using Elf_Note = typename ELFT::Note;
+  ArrayRef<uint8_t> data = sec.content();
+  auto reportError = [&](const Twine &msg) {
+    errorOrWarn(toString(sec.file) + ":(" + sec.name + "): " + msg);
+  };
+
+  auto *nhdr = reinterpret_cast<const Elf_Nhdr *>(data.data());
+  if (data.size() < sizeof(Elf_Nhdr) ||
+      data.size() < nhdr->getSize(sec.addralign)) {
+    reportError("section is too short");
+    return;
+  }
+
+  Elf_Note note(*nhdr);
+  if (nhdr->n_type != NT_ARM_TYPE_PAUTH_ABI_TAG)
+    reportError("invalid type field value " + Twine(nhdr->n_type) + " (" +
+                Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) + " expected)");
+  if (note.getName() != "ARM")
+    reportError("invalid name field value " + note.getName() +
+                " (ARM expected)");
+
+  ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
+  if (desc.size() < 16) {
+    reportError("too short AArch64 PAuth compatibility info "
+                "(at least 16 bytes expected)");
+    return;
+  }
+
+  f.aarch64PauthAbiTag = SmallVector<uint8_t, 0>(iterator_range(desc));
+}
+
 template <class ELFT>
 InputSectionBase *ObjFile<ELFT>::getRelocTarget(uint32_t idx,
                                                 const Elf_Shdr &sec,
@@ -1020,6 +1058,12 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
       return &InputSection::discarded;
     }
 
+    if (config->emachine == EM_AARCH64 &&
+        name == ".note.AARCH64-PAUTH-ABI-tag") {
+      readAArch64PauthAbiTag<ELFT>(InputSection(*this, sec, name), *this);
+      return &InputSection::discarded;
+    }
+
     // Split stacks is a feature to support a discontiguous stack,
     // commonly used in the programming language Go. For the details,
     // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index ab98d78fcf1455..6a74ba7fb20998 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -218,6 +218,7 @@ class ELFFileBase : public InputFile {
 public:
   uint32_t andFeatures = 0;
   bool hasCommonSyms = false;
+  SmallVector<uint8_t, 0> aarch64PauthAbiTag;
 };
 
 // .o file.
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index fe3d7f419e84aa..5b5e6b154d52f4 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1444,6 +1444,32 @@ template <class ELFT, class RelTy> void RelocationScanner::scanOne(RelTy *&i) {
     }
   }
 
+  if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
+    // Assume relocations from relocatable objects are RELA.
+    assert(RelTy::IsRela);
+    std::lock_guard<std::mutex> lock(relocMutex);
+    // For a preemptible symbol, we can't use a relative relocation. For an
+    // undefined symbol, we can't compute offset at link-time and use a relative
+    // relocation. Use a symbolic relocation instead.
+    Partition &part = sec->getPartition();
+    if (sym.isPreemptible || sym.isUndefined()) {
+      part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
+    } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
+               isInt<32>(sym.getVA(addend))) {
+      // Implicit addend is below 32-bits so we can use the compressed
+      // relative relocation section. The R_AARCH64_AUTH_RELATIVE
+      // has a smaller addend fielf as bits [63:32] encode the signing-schema.
+      sec->addReloc({expr, type, offset, addend, &sym});
+      part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back(
+          {sec, offset});
+    } else {
+      part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
+                              DynamicReloc::AddendOnlyWithTargetVA, sym, addend,
+                              R_ABS});
+    }
+    return;
+  }
+
   // If the relocation does not emit a GOT or GOTPLT entry but its computation
   // uses their addresses, we need GOT or GOTPLT to be created.
   //
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2b32eb3a0fe355..fa7589806a7b5b 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -331,6 +331,29 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
 
 size_t GnuPropertySection::getSize() const { return config->is64 ? 32 : 28; }
 
+AArch64PauthAbiTag::AArch64PauthAbiTag()
+    : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE,
+                       config->wordsize, ".note.AARCH64-PAUTH-ABI-tag") {}
+
+bool AArch64PauthAbiTag::isNeeded() const {
+  return !ctx.aarch64PauthAbiTag.empty();
+}
+
+void AArch64PauthAbiTag::writeTo(uint8_t *buf) {
+  const SmallVector<uint8_t, 0> &data = ctx.aarch64PauthAbiTag;
+  write32(buf, 4);                             // Name size
+  write32(buf + 4, data.size());               // Content size
+  write32(buf + 8, NT_ARM_TYPE_PAUTH_ABI_TAG); // Type
+  memcpy(buf + 12, "ARM", 4);                  // Name string
+  memcpy(buf + 16, data.data(), data.size());
+  memset(buf + 16 + data.size(), 0, getSize() - 16 - data.size()); // Padding
+}
+
+size_t AArch64PauthAbiTag::getSize() const {
+  return alignToPowerOf2(16 + ctx.aarch64PauthAbiTag.size(),
+                         config->is64 ? 8 : 4);
+}
+
 BuildIdSection::BuildIdSection()
     : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"),
       hashSize(getHashSize()) {}
@@ -1406,6 +1429,12 @@ DynamicSection<ELFT>::computeContents() {
     addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
            sizeof(Elf_Relr));
   }
+  if (part.relrAuthDyn && part.relrAuthDyn->getParent() &&
+      !part.relrAuthDyn->relocs.empty()) {
+    addInSec(DT_AARCH64_AUTH_RELR, *part.relrAuthDyn);
+    addInt(DT_AARCH64_AUTH_RELRSZ, part.relrAuthDyn->getParent()->size);
+    addInt(DT_AARCH64_AUTH_RELRENT, sizeof(Elf_Relr));
+  }
   // .rel[a].plt section usually consists of two parts, containing plt and
   // iplt relocations. It is possible to have only iplt relocations in the
   // output. In that case relaPlt is empty and have zero offset, the same offset
@@ -1717,10 +1746,13 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
   }
 }
 
-RelrBaseSection::RelrBaseSection(unsigned concurrency)
-    : SyntheticSection(SHF_ALLOC,
-                       config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR,
-                       config->wordsize, ".relr.dyn"),
+RelrBaseSection::RelrBaseSection(unsigned concurrency, bool isAArch64Auth)
+    : SyntheticSection(
+          SHF_ALLOC,
+          isAArch64Auth
+              ? SHT_AARCH64_AUTH_RELR
+              : (config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR),
+          config->wordsize, isAArch64Auth ? ".relr.auth.dyn" : ".relr.dyn"),
       relocsVec(concurrency) {}
 
 void RelrBaseSection::mergeRels() {
@@ -1988,8 +2020,8 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
 }
 
 template <class ELFT>
-RelrSection<ELFT>::RelrSection(unsigned concurrency)
-    : RelrBaseSection(concurrency) {
+RelrSection<ELFT>::RelrSection(unsigned concurrency, bool isAArch64Auth)
+    : RelrBaseSection(concurrency, isAArch64Auth) {
   this->entsize = config->wordsize;
 }
 
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 3a9f4ba886f6bb..d183a547c68205 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -144,6 +144,16 @@ class GnuPropertySection final : public SyntheticSection {
   size_t getSize() const override;
 };
 
+// .note.AARCH64-PAUTH-ABI-tag section. See
+// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking
+class AArch64PauthAbiTag final : public SyntheticSection {
+public:
+  AArch64PauthAbiTag();
+  void writeTo(uint8_t *buf) override;
+  size_t getSize() const override;
+  bool isNeeded() const override;
+};
+
 // .note.gnu.build-id section.
 class BuildIdSection : public SyntheticSection {
   // First 16 bytes are a header.
@@ -543,7 +553,8 @@ class RelocationBaseSection : public SyntheticSection {
   static bool classof(const SectionBase *d) {
     return SyntheticSection::classof(d) &&
            (d->type == llvm::ELF::SHT_RELA || d->type == llvm::ELF::SHT_REL ||
-            d->type == llvm::ELF::SHT_RELR);
+            d->type == llvm::ELF::SHT_RELR ||
+            d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR);
   }
   int32_t dynamicTag, sizeDynamicTag;
   SmallVector<DynamicReloc, 0> relocs;
@@ -599,7 +610,7 @@ struct RelativeReloc {
 
 class RelrBaseSection : public SyntheticSection {
 public:
-  RelrBaseSection(unsigned concurrency);
+  RelrBaseSection(unsigned concurrency, bool isAArch64Auth = false);
   void mergeRels();
   bool isNeeded() const override {
     return !relocs.empty() ||
@@ -617,7 +628,7 @@ template <class ELFT> class RelrSection final : public RelrBaseSection {
   using Elf_Relr = typename ELFT::Relr;
 
 public:
-  RelrSection(unsigned concurrency);
+  RelrSection(unsigned concurrency, bool isAArch64Auth = false);
 
   bool updateAllocSize() override;
   size_t getSize() const override { return relrRelocs.size() * this->entsize; }
@@ -1319,6 +1330,7 @@ struct Partition {
   std::unique_ptr<PackageMetadataNote> packageMetadataNote;
   std::unique_ptr<RelocationBaseSection> relaDyn;
   std::unique_ptr<RelrBaseSection> relrDyn;
+  std::unique_ptr<RelrBaseSection> relrAuthDyn;
   std::unique_ptr<VersionDefinitionSection> verDef;
   std::unique_ptr<SyntheticSection> verNeed;
   std::unique_ptr<VersionTableSection> verSym;
@@ -1363,6 +1375,7 @@ struct InStruct {
   std::unique_ptr<StringTableSection> strTab;
   std::unique_ptr<SymbolTableBaseSection> symTab;
   std::unique_ptr<SymtabShndxSection> symTabShndx;
+  std::unique_ptr<AArch64PauthAbiTag> aarch64PauthAbiTag;
 
   void reset();
 };
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index a84e4864ab0e5a..f1b569daada663 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -445,6 +445,12 @@ template <class ELFT> void elf::createSyntheticSections() {
       add(*part.relrDyn);
     }
 
+    if (config->relrPackAuthDynRelocs) {
+      part.relrAuthDyn = std::make_unique<RelrSection<ELFT>>(
+          threadCount, /*isAArch64Auth=*/true);
+      add(*part.relrAuthDyn);
+    }
+
     if (!config->relocatable) {
       if (config->ehFrameHdr) {
         part.ehFrameHdr = std::make_unique<EhFrameHeader>();
@@ -566,6 +572,11 @@ template <class ELFT> void elf::createSyntheticSections() {
   if (config->andFeatures)
     add(*make<GnuPropertySection>());
 
+  if (!ctx.aarch64PauthAbiTag.empty()) {
+    in.aarch64PauthAbiTag = std::make_unique<AArch64PauthAbiTag>();
+    add(*in.aarch64PauthAbiTag);
+  }
+
   // .note.GNU-stack is always added when we are creating a re-linkable
   // object file. Other linkers are using the presence of this marker
   // section to control the executable-ness of the stack area, but that
@@ -1725,6 +1736,8 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
       changed |= part.relaDyn->updateAllocSize();
       if (part.relrDyn)
         changed |= part.relrDyn->updateAllocSize();
+      if (part.relrAuthDyn)
+        changed |= part.relrAuthDyn->updateAllocSize();
       if (part.memtagDescriptors)
         changed |= part.memtagDescriptors->updateAllocSize();
     }
@@ -2179,6 +2192,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
         part.relrDyn->mergeRels();
         finalizeSynthetic(part.relrDyn.get());
       }
+      if (part.relrAuthDyn) {
+        part.relrAuthDyn->mergeRels();
+        finalizeSynthetic(part.relrAuthDyn.get());
+      }
 
       finalizeSynthetic(part.dynSymTab.get());
       finalizeSynthetic(part.gnuHashTab.get());
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
new file mode 100644
index 00000000000000..0520b2f28631e1
--- /dev/null
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -0,0 +1,83 @@
+# REQUIRES: aarch64
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag1.s -o tag11.o
+# RUN: cp tag11.o tag12.o
+# RUN: ld.lld -shared tag11.o tag12.o -o tagok.so
+# RUN: llvm-readelf -n tagok.so | FileCheck --check-prefix OK %s
+
+# OK: AArch64 PAuth ABI tag: platform 0x2a, version 0x1
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o
+# RUN: not ld.lld tag11.o tag12.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s
+
+# ERR1: error: incompatible values of AArch64 PAuth compatibility info found
+# ERR1: {{.*}}: 0x2A000000000000000{{1|2}}00000000000000
+# ERR1: {{.*}}: 0x2A000000000000000{{1|2}}00000000000000
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o
+# RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s
+
+# ERR2:      error: {{.*}}: invalid type field value 42 (1 expected)
+# ERR2-NEXT: error: {{.*}}: invalid name field value XXX (ARM expected)
+# ERR2-NEXT: error: {{.*}}: too short AArch64 PAuth compatibility info (at least 16 bytes expected)
+
+# 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 ERR3 %s
+
+# ERR3: error: {{.*}}: section is too short
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o
+# RUN: cp noinfo1.o noinfo2.o
+# RUN: not ld.lld -z pauth-report=error tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s
+# RUN: ld.lld -z pauth-report=warning tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s
+# RUN: ld.lld -z pauth-report=none tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix NONE %s
+
+# ERR4:      error: {{.*}}noinfo1.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it
+# ERR4-NEXT: error: {{.*}}noinfo2.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it
+# WARN:      warning: {{.*}}noinfo1.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it
+# WARN-NEXT: warning: {{.*}}noinfo2.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it
+# NONE-NOT:  {{.*}} has no AArch64 PAuth compatibility info while {{.*}} has one; either all or no input files must have it
+
+#--- abi-tag-short.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 8
+
+#--- abi-tag-errs.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 8
+.long 42
+.asciz "XXX"
+
+.quad 42
+
+#--- abi-tag1.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 16
+.long 1
+.asciz "ARM"
+
+.quad 42         // platform
+.quad 1          // version
+
+#--- abi-tag2.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 16
+.long 1
+.asciz "ARM"
+
+.quad 42         // platform
+.quad 2          // version
+
+#--- no-info.s
+
+.section ".test", "a"
diff --git a/lld/test/ELF/aarch64-ptrauth.s b/lld/test/ELF/aarch64-ptrauth.s
new file mode 100644
index 00000000000000..db946fc4c3e55c
--- /dev/null
+++ b/lld/test/ELF/aarch64-ptrauth.s
@@ -0,0 +1,156 @@
+// REQUIRES: aarch64
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
+// RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
+// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+// RUN: ld.lld -pie -z nopack-relative-auth-relocs %t.o %t.so -o %t2
+// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s
+
+// UNPACKED:          Section ({{.+}}) .rela.dyn {
+// UNPACKED-NEXT:       0x30680 R_AARCH64_AUTH_RELATIVE - 0x1
+// UNPACKED-NEXT:       0x30688 R_AARCH64_AUTH_RELATIVE - 0x2
+// UNPACKED-NEXT:       0x30690 R_AARCH64_AUTH_RELATIVE - 0x3
+// UNPACKED-NEXT:       0x30698 R_AARCH64_AUTH_RELATIVE - 0x4
+// UNPACKED-NEXT:       0x306A0 R_AARCH64_AUTH_RELATIVE - 0x5
+// UNPACKED-NEXT:       0x306A8 R_AARCH64_AUTH_RELATIVE - 0x6
+// UNPACKED-NEXT:       0x306B0 R_AARCH64_AUTH_RELATIVE - 0x7
+// UNPACKED-NEXT:       0x306B8 R_AARCH64_AUTH_RELATIVE - 0x8
+// UNPACKED-NEXT:       0x306C8 R_AARCH64_AUTH_RELATIVE - 0x1
+// UNPACKED-NEXT:       0x306D0 R_AARCH64_AUTH_RELATIVE - 0x2
+// UNPACKED-NEXT:       0x306D8 R_AARCH64_AUTH_RELATIVE - 0x3
+// UNPACKED-NEXT:       0x306E0 R_AARCH64_AUTH_RELATIVE - 0x4
+// UNPACKED-NEXT:       0x306E8 R_AARCH64_AUTH_RELATIVE - 0x5
+// UNPACKED-NEXT:       0x306F0 R_AARCH64_AUTH_RELATIVE - 0x6
+// UNPACKED-NEXT:       0x306F8 R_AARCH64_AUTH_RELATIVE - 0x7
+// UNPACKED-NEXT:       0x30710 R_AARCH64_AUTH_RELATIVE - 0x1
+// UNPACKED-NEXT:       0x30718 R_AARCH64_AUTH_RELATIVE - 0x2
+// UNPACKED-NEXT:       0x30720 R_AARCH64_AUTH_RELATIVE - 0x3
+// UNPACKED-NEXT:       0x30728 R_AARCH64_AUTH_RELATIVE - 0x4
+// UNPACKED-NEXT:       0x30730 R_AARCH64_AUTH_RELATIVE - 0x5
+// UNPACKED-NEXT:       0x30738 R_AARCH64_AUTH_RELATIVE - 0x6
+// UNPACKED-NEXT:       0x30740 R_AARCH64_AUTH_RELATIVE - 0x7
+// UNPACKED-NEXT:       0x30748 R_AARCH64_AUTH_RELATIVE - 0x8
+// UNPACKED-NEXT:       0x30750 R_AARCH64_AUTH_RELATIVE - 0x9
+// UNPACKED-NEXT:       0x30759 R_AARCH64_AUTH_RELATIVE - 0xA
+// UNPACKED-NEXT:       0x306C0 R_AARCH64_AUTH_ABS64 bar2 0x1
+// UNPACKED-NEXT:       0x30708 R_AARCH64_AUTH_ABS64 bar2 0x0
+// UNPACKED-NEXT:       0x30761 R_AARCH64_AUTH_ABS64 bar2 0x0
+// UNPACKED-NEXT:       0x30769 R_AARCH64_AUTH_ABS64 bar2 0x0
+// UNPACKED-NEXT:       0x30771 R_AARCH64_AUTH_ABS64 bar2 0x1
+// UNPACKED-NEXT:       0x30779 R_AARCH64_AUTH_ABS64 bar2 0x1
+// UNPACKED-NEXT:       0x30781 R_AARCH64_AUTH_ABS64 bar2 0x0
+// UNPACKED-NEXT:       0x30700 R_AARCH64_AUTH_ABS64 zed2 0x0
+// UNPACKED-NEXT:     }
+
+// RUN: ld.lld -pie -z pack-relative-auth-relocs %t.o %t.so -o %t2
+// RUN: llvm-readobj -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s
+// RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s
+// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s
+
+// RELR-HEADERS:       Index: 1
+// RELR-HEADERS-NEXT:  Name: .dynsym
+
+// RELR-HEADERS:       Name: .relr.auth.dyn
+// RELR-HEADERS-NEXT:  Type: SHT_AARCH64_AUTH_RELR
+// RELR-HEADERS-NEXT:  Flags [ (0x2)
+// RELR-HEADERS-NEXT:    SHF_ALLOC (0x2)
+// RELR-HEADERS-NEXT:  ]
+// RELR-HEADERS-NEXT:  Address: [[ADDR:.*]]
+// RELR-HEADERS-NEXT:  Offset: [[ADDR]]
+// RELR-HEADERS-NEXT:  Size: 16
+// RELR-HEADERS-NEXT:  Link: 0
+// RELR-HEADERS-NEXT:  Info: 0
+// RELR-HEADERS-NEXT:  AddressAlignment: 8
+// RELR-HEADERS-NEXT:  EntrySize: 8
+
+// RELR-HEADERS:       0x0000000070000012 AARCH64_AUTH_RELR    [[ADDR]]
+// RELR-HEADERS:       0x0000000070000011 AARCH64_AUTH_RELRSZ  16 (bytes)
+// RELR-HEADERS:       0x0000000070000013 AARCH64_AUTH_RELRENT 8 (bytes)
+
+/// SHT_RELR section contains address/bitmap entries
+/// encoding the offsets for relative relocation.
+// RAW-RELR:           Section ({{.+}}) .relr.auth.dyn {
+// RAW-RELR-NEXT:      0x30480
+// RAW-RELR-NEXT:      0x7FCFEFF
+// RAW-RELR-NEXT:      }
+
+/// Decoded SHT_RELR section is same as UNPACKED,
+/// but contains only the relative relocations.
+/// Any relative relocations with odd offset stay in SHT_RELA.
+
+// RELR:      Section ({{.+}}) .rela.dyn {
+// RELR-NEXT:   0x30559 R_AARCH64_AUTH_RELATIVE - 0xA
+// RELR-NEXT:   0x304C0 R_AARCH64_AUTH_ABS64 bar2 0x1
+// RELR-NEXT:   0x30508 R_AARCH64_AUTH_ABS64 bar2 0x0
+// RELR-NEXT:   0x30561 R_AARCH64_AUTH_ABS64 bar2 0x0
+// RELR-NEXT:   0x30569 R_AARCH64_AUTH_ABS64 bar2 0x0
+// RELR-NEXT:   0x30571 R_AARCH64_AUTH_ABS64 bar2 0x1
+// RELR-NEXT:   0x30579 R_AARCH64_AUTH_ABS64 bar2 0x1
+// RELR-NEXT:   0x30581 R_AARCH64_AUTH_ABS64 bar2 0x0
+// RELR-NEXT:   0x30500 R_AARCH64_AUTH_ABS64 zed2 0x0
+// RELR-NEXT: }
+// RELR-NEXT: Section ({{.+}}) .relr.auth.dyn {
+// RELR-NEXT:   0x30480 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30488 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30490 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30498 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304A0 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304A8 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304B0 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304B8 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304C8 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304D0 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304D8 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304E0 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304E8 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304F0 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x304F8 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30510 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30518 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30520 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30528 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30530 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30538 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30540 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30548 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x30550 R_AARCH64_RELATIVE -
+// RELR-NEXT: }
+
+.section .test, "aw"
+.p2align 3
+.quad (__ehdr_start + 1)@AUTH(da,42)
+.quad (__ehdr_start + 2)@AUTH(da,42)
+.quad (__ehdr_start + 3)@AUTH(da,42)
+.quad (__ehdr_start + 4)@AUTH(da,42)
+.quad (__ehdr_start + 5)@AUTH(da,42)
+.quad (__ehdr_start + 6)@AUTH(da,42)
+.quad (__ehdr_start + 7)@AUTH(da,42)
+.quad (__ehdr_start + 8)@AUTH(da,42)
+.quad (bar2 + 1)@AUTH(ia,42)
+
+.quad (__ehdr_start + 1)@AUTH(da,65535)
+.quad (__ehdr_start + 2)@AUTH(da,65535)
+.quad (__ehdr_start + 3)@AUTH(da,65535)
+.quad (__ehdr_start + 4)@AUTH(da,65535)
+.quad (__ehdr_start + 5)@AUTH(da,65535)
+.quad (__ehdr_start + 6)@AUTH(da,65535)
+.quad (__ehdr_start + 7)@AUTH(da,65535)
+.quad zed2 at AUTH(da,42)
+.quad bar2 at AUTH(ia,42)
+
+.quad (__ehdr_start + 1)@AUTH(da,0)
+.quad (__ehdr_start + 2)@AUTH(da,0)
+.quad (__ehdr_start + 3)@AUTH(da,0)
+.quad (__ehdr_start + 4)@AUTH(da,0)
+.quad (__ehdr_start + 5)@AUTH(da,0)
+.quad (__ehdr_start + 6)@AUTH(da,0)
+.quad (__ehdr_start + 7)@AUTH(da,0)
+.quad (__ehdr_start + 8)@AUTH(da,0)
+.quad (__ehdr_start + 9)@AUTH(da,0)
+.byte 00
+.quad (__ehdr_start + 10)@AUTH(da,0)
+.quad bar2 at AUTH(ia,42)
+.quad bar2 at AUTH(ia,42)
+.quad (bar2 + 1)@AUTH(ia,42)
+.quad (bar2 + 1)@AUTH(ia,42)
+.quad bar2 at AUTH(ia,42)

>From 589c6455a929f41ed3a79fc7d91119586eb1ee7b Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 12 Dec 2023 09:05:38 +0300
Subject: [PATCH 02/23] Address trivial review comments

---
 lld/ELF/Driver.cpp                       | 46 ++++++++++++------------
 lld/ELF/InputFiles.cpp                   |  2 +-
 lld/test/ELF/aarch64-bti-pac-cli-error.s | 15 +++++---
 lld/test/ELF/aarch64-feature-pauth.s     |  2 +-
 4 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 4e8e9eb86ecf77..ca5a8b8d994a4b 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2648,44 +2648,44 @@ static uint32_t getAndFeatures() {
   return ret;
 }
 
-static void getAarch64PauthInfo() {
+static void getAArch64PauthInfo() {
   if (ctx.objectFiles.empty())
     return;
 
-  auto NonEmptyIt = std::find_if(
+  auto it = std::find_if(
       ctx.objectFiles.begin(), ctx.objectFiles.end(),
       [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); });
-  if (NonEmptyIt == ctx.objectFiles.end())
+  if (it == ctx.objectFiles.end())
     return;
 
-  ctx.aarch64PauthAbiTag = (*NonEmptyIt)->aarch64PauthAbiTag;
-  StringRef F1 = (*NonEmptyIt)->getName();
-  for (ELFFileBase *F : ArrayRef(ctx.objectFiles)) {
-    StringRef F2 = F->getName();
-    const SmallVector<uint8_t, 0> &D1 = ctx.aarch64PauthAbiTag;
-    const SmallVector<uint8_t, 0> &D2 = F->aarch64PauthAbiTag;
-    if (D1.empty() != D2.empty()) {
-      auto Helper = [](StringRef Report, const Twine &Msg) {
-        if (Report == "warning")
-          warn(Msg);
-        else if (Report == "error")
-          error(Msg);
+  ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag;
+  StringRef f1 = (*it)->getName();
+  for (ELFFileBase *f : ArrayRef(ctx.objectFiles)) {
+    StringRef f2 = f->getName();
+    const SmallVector<uint8_t, 0> &d1 = ctx.aarch64PauthAbiTag;
+    const SmallVector<uint8_t, 0> &d2 = f->aarch64PauthAbiTag;
+    if (d1.empty() != d2.empty()) {
+      auto helper = [](StringRef report, const Twine &msg) {
+        if (report == "warning")
+          warn(msg);
+        else if (report == "error")
+          error(msg);
       };
 
-      Helper(config->zPauthReport,
-             (D1.empty() ? F1.str() : F2.str()) +
+      helper(config->zPauthReport,
+             (d1.empty() ? f1.str() : f2.str()) +
                  " has no AArch64 PAuth compatibility info while " +
-                 (D1.empty() ? F2.str() : F1.str()) +
+                 (d1.empty() ? f2.str() : f1.str()) +
                  " has one; either all or no input files must have it");
     }
 
-    if (!D1.empty() && !D2.empty() &&
-        !std::equal(D1.begin(), D1.end(), D2.begin(), D2.end()))
+    if (!d1.empty() && !d2.empty() &&
+        !std::equal(d1.begin(), d1.end(), d2.begin(), d2.end()))
       errorOrWarn(
           "incompatible values of AArch64 PAuth compatibility info found"
           "\n" +
-          F1 + ": 0x" + toHex(ArrayRef(D1.data(), D1.size())) + "\n" + F2 +
-          ": 0x" + toHex(ArrayRef(D2.data(), D2.size())));
+          f1 + ": 0x" + toHex(ArrayRef(d1.data(), d1.size())) + "\n" + f2 +
+          ": 0x" + toHex(ArrayRef(d2.data(), d2.size())));
   }
 }
 
@@ -3027,7 +3027,7 @@ void LinkerDriver::link(opt::InputArgList &args) {
   config->andFeatures = getAndFeatures();
 
   if (config->emachine == EM_AARCH64)
-    getAarch64PauthInfo();
+    getAArch64PauthInfo();
 
   // The Target instance handles target-specific stuff, such as applying
   // relocations or writing a PLT section. It also contains target-dependent
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 44c8050f2c967a..d7ceaf476cf9bf 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -992,7 +992,7 @@ static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile<ELFT> &f) {
 
   ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
   if (desc.size() < 16) {
-    reportError("too short AArch64 PAuth compatibility info "
+    reportError("AArch64 PAuth compatibility info is too short "
                 "(at least 16 bytes expected)");
     return;
   }
diff --git a/lld/test/ELF/aarch64-bti-pac-cli-error.s b/lld/test/ELF/aarch64-bti-pac-cli-error.s
index b8ab1a28fa5a86..703c0aac6ea5ac 100644
--- a/lld/test/ELF/aarch64-bti-pac-cli-error.s
+++ b/lld/test/ELF/aarch64-bti-pac-cli-error.s
@@ -1,17 +1,22 @@
 # REQUIRES: x86
 # RUN: llvm-mc --triple=x86_64-pc-linux --filetype=obj -o %t.o %s
-# RUN: not ld.lld -z pac-plt -z force-bti -z bti-report=error %t.o -o /dev/null 2>&1 | FileCheck %s
+# RUN: not ld.lld -z pac-plt -z force-bti -z bti-report=error   \
+# RUN:     -z pauth-report=error   %t.o -o /dev/null 2>&1 | FileCheck %s
+# RUN: not ld.lld -z pac-plt -z force-bti -z bti-report=warning \
+# RUN:     -z pauth-report=warning %t.o -o /dev/null 2>&1 | FileCheck %s
 #
-## Check that we error if -z pac-plt, -z force-bti and -z bti-report=error are used when target is not
-## aarch64
+## Check that we error if -z pac-plt, -z force-bti are present and
+## -z bti-report and -z pauth-report are not none when target is not aarch64
 
 # CHECK: error: -z pac-plt only supported on AArch64
 # CHECK-NEXT: error: -z force-bti only supported on AArch64
 # CHECK-NEXT: error: -z bti-report only supported on AArch64
+# CHECK-NEXT: error: -z pauth-report only supported on AArch64
 
-# RUN: not ld.lld -z bti-report=something %t.o -o /dev/null 2>&1 | \
-# RUN:     FileCheck --check-prefix=REPORT_INVALID %s
+# RUN: not ld.lld -z bti-report=something -z pauth-report=something \
+# RUN:     %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=REPORT_INVALID %s
 # REPORT_INVALID: error: -z bti-report= parameter something is not recognized
+# REPORT_INVALID: error: -z pauth-report= parameter something is not recognized
 # REPORT_INVALID-EMPTY:
 
         .globl start
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index 0520b2f28631e1..9060eb71f81757 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -21,7 +21,7 @@
 
 # ERR2:      error: {{.*}}: invalid type field value 42 (1 expected)
 # ERR2-NEXT: error: {{.*}}: invalid name field value XXX (ARM expected)
-# ERR2-NEXT: error: {{.*}}: too short AArch64 PAuth compatibility info (at least 16 bytes expected)
+# ERR2-NEXT: error: {{.*}}: AArch64 PAuth compatibility info is too short (at least 16 bytes expected)
 
 # 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 ERR3 %s

>From d3411595fbbe37a14b0187ff0d134bd105892931 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 9 Jan 2024 21:53:00 +0300
Subject: [PATCH 03/23] Use `pack-relative-relocs` for both regular and auth
 relr relocs

---
 lld/ELF/Config.h               | 1 -
 lld/ELF/Driver.cpp             | 3 ---
 lld/ELF/Writer.cpp             | 3 ---
 lld/test/ELF/aarch64-ptrauth.s | 4 ++--
 4 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 1b633a79842769..e2a3cb2a61e936 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -276,7 +276,6 @@ struct Config {
   bool relocatable;
   bool relrGlibc = false;
   bool relrPackDynRelocs = false;
-  bool relrPackAuthDynRelocs = false;
   llvm::DenseSet<llvm::StringRef> saveTempsArgs;
   llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
   bool singleRoRx;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index ca5a8b8d994a4b..6ab93c74bc6453 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1677,9 +1677,6 @@ static void readConfigs(opt::InputArgList &args) {
         getPackDynRelocs(args);
   }
 
-  config->relrPackAuthDynRelocs = getZFlag(
-      args, "pack-relative-auth-relocs", "nopack-relative-auth-relocs", false);
-
   if (auto *arg = args.getLastArg(OPT_symbol_ordering_file)){
     if (args.hasArg(OPT_call_graph_ordering_file))
       error("--symbol-ordering-file and --call-graph-order-file "
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index af2544c3fa0f7f..81e743d67dabd1 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -450,9 +450,6 @@ template <class ELFT> void elf::createSyntheticSections() {
     if (config->relrPackDynRelocs) {
       part.relrDyn = std::make_unique<RelrSection<ELFT>>(threadCount);
       add(*part.relrDyn);
-    }
-
-    if (config->relrPackAuthDynRelocs) {
       part.relrAuthDyn = std::make_unique<RelrSection<ELFT>>(
           threadCount, /*isAArch64Auth=*/true);
       add(*part.relrAuthDyn);
diff --git a/lld/test/ELF/aarch64-ptrauth.s b/lld/test/ELF/aarch64-ptrauth.s
index db946fc4c3e55c..26cc2d779e7482 100644
--- a/lld/test/ELF/aarch64-ptrauth.s
+++ b/lld/test/ELF/aarch64-ptrauth.s
@@ -3,7 +3,7 @@
 // RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
 // RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
 // RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
-// RUN: ld.lld -pie -z nopack-relative-auth-relocs %t.o %t.so -o %t2
+// RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2
 // RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s
 
 // UNPACKED:          Section ({{.+}}) .rela.dyn {
@@ -42,7 +42,7 @@
 // UNPACKED-NEXT:       0x30700 R_AARCH64_AUTH_ABS64 zed2 0x0
 // UNPACKED-NEXT:     }
 
-// RUN: ld.lld -pie -z pack-relative-auth-relocs %t.o %t.so -o %t2
+// RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2
 // RUN: llvm-readobj -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s
 // RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s
 // RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s

>From b791da9dd02f8b3bf59d2d235181f945844d3039 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 9 Jan 2024 21:59:35 +0300
Subject: [PATCH 04/23] Rename aarch64-ptrauth.s to aarch64-reloc-pauth.s

---
 lld/test/ELF/{aarch64-ptrauth.s => aarch64-reloc-pauth.s} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename lld/test/ELF/{aarch64-ptrauth.s => aarch64-reloc-pauth.s} (100%)

diff --git a/lld/test/ELF/aarch64-ptrauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
similarity index 100%
rename from lld/test/ELF/aarch64-ptrauth.s
rename to lld/test/ELF/aarch64-reloc-pauth.s

>From b95dcf8e7cd9c3c162a25c93a9c2b09ba8bb124c Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 9 Jan 2024 22:23:16 +0300
Subject: [PATCH 05/23] Remove unneeded test directives

---
 lld/test/ELF/aarch64-reloc-pauth.s | 114 +++--------------------------
 1 file changed, 12 insertions(+), 102 deletions(-)

diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 26cc2d779e7482..79e6e4246cc457 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -7,39 +7,10 @@
 // RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s
 
 // UNPACKED:          Section ({{.+}}) .rela.dyn {
-// UNPACKED-NEXT:       0x30680 R_AARCH64_AUTH_RELATIVE - 0x1
-// UNPACKED-NEXT:       0x30688 R_AARCH64_AUTH_RELATIVE - 0x2
-// UNPACKED-NEXT:       0x30690 R_AARCH64_AUTH_RELATIVE - 0x3
-// UNPACKED-NEXT:       0x30698 R_AARCH64_AUTH_RELATIVE - 0x4
-// UNPACKED-NEXT:       0x306A0 R_AARCH64_AUTH_RELATIVE - 0x5
-// UNPACKED-NEXT:       0x306A8 R_AARCH64_AUTH_RELATIVE - 0x6
-// UNPACKED-NEXT:       0x306B0 R_AARCH64_AUTH_RELATIVE - 0x7
-// UNPACKED-NEXT:       0x306B8 R_AARCH64_AUTH_RELATIVE - 0x8
-// UNPACKED-NEXT:       0x306C8 R_AARCH64_AUTH_RELATIVE - 0x1
-// UNPACKED-NEXT:       0x306D0 R_AARCH64_AUTH_RELATIVE - 0x2
-// UNPACKED-NEXT:       0x306D8 R_AARCH64_AUTH_RELATIVE - 0x3
-// UNPACKED-NEXT:       0x306E0 R_AARCH64_AUTH_RELATIVE - 0x4
-// UNPACKED-NEXT:       0x306E8 R_AARCH64_AUTH_RELATIVE - 0x5
-// UNPACKED-NEXT:       0x306F0 R_AARCH64_AUTH_RELATIVE - 0x6
-// UNPACKED-NEXT:       0x306F8 R_AARCH64_AUTH_RELATIVE - 0x7
-// UNPACKED-NEXT:       0x30710 R_AARCH64_AUTH_RELATIVE - 0x1
-// UNPACKED-NEXT:       0x30718 R_AARCH64_AUTH_RELATIVE - 0x2
-// UNPACKED-NEXT:       0x30720 R_AARCH64_AUTH_RELATIVE - 0x3
-// UNPACKED-NEXT:       0x30728 R_AARCH64_AUTH_RELATIVE - 0x4
-// UNPACKED-NEXT:       0x30730 R_AARCH64_AUTH_RELATIVE - 0x5
-// UNPACKED-NEXT:       0x30738 R_AARCH64_AUTH_RELATIVE - 0x6
-// UNPACKED-NEXT:       0x30740 R_AARCH64_AUTH_RELATIVE - 0x7
-// UNPACKED-NEXT:       0x30748 R_AARCH64_AUTH_RELATIVE - 0x8
-// UNPACKED-NEXT:       0x30750 R_AARCH64_AUTH_RELATIVE - 0x9
-// UNPACKED-NEXT:       0x30759 R_AARCH64_AUTH_RELATIVE - 0xA
-// UNPACKED-NEXT:       0x306C0 R_AARCH64_AUTH_ABS64 bar2 0x1
-// UNPACKED-NEXT:       0x30708 R_AARCH64_AUTH_ABS64 bar2 0x0
-// UNPACKED-NEXT:       0x30761 R_AARCH64_AUTH_ABS64 bar2 0x0
-// UNPACKED-NEXT:       0x30769 R_AARCH64_AUTH_ABS64 bar2 0x0
-// UNPACKED-NEXT:       0x30771 R_AARCH64_AUTH_ABS64 bar2 0x1
-// UNPACKED-NEXT:       0x30779 R_AARCH64_AUTH_ABS64 bar2 0x1
-// UNPACKED-NEXT:       0x30781 R_AARCH64_AUTH_ABS64 bar2 0x0
-// UNPACKED-NEXT:       0x30700 R_AARCH64_AUTH_ABS64 zed2 0x0
+// UNPACKED-NEXT:       0x303C8 R_AARCH64_AUTH_RELATIVE - 0x1
+// UNPACKED-NEXT:       0x303E1 R_AARCH64_AUTH_RELATIVE - 0x2
+// UNPACKED-NEXT:       0x303D0 R_AARCH64_AUTH_ABS64 zed2 0x0
+// UNPACKED-NEXT:       0x303D8 R_AARCH64_AUTH_ABS64 bar2 0x0
 // UNPACKED-NEXT:     }
 
 // RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2
@@ -57,21 +28,20 @@
 // RELR-HEADERS-NEXT:  ]
 // RELR-HEADERS-NEXT:  Address: [[ADDR:.*]]
 // RELR-HEADERS-NEXT:  Offset: [[ADDR]]
-// RELR-HEADERS-NEXT:  Size: 16
+// RELR-HEADERS-NEXT:  Size: 8
 // RELR-HEADERS-NEXT:  Link: 0
 // RELR-HEADERS-NEXT:  Info: 0
 // RELR-HEADERS-NEXT:  AddressAlignment: 8
 // RELR-HEADERS-NEXT:  EntrySize: 8
 
 // RELR-HEADERS:       0x0000000070000012 AARCH64_AUTH_RELR    [[ADDR]]
-// RELR-HEADERS:       0x0000000070000011 AARCH64_AUTH_RELRSZ  16 (bytes)
+// RELR-HEADERS:       0x0000000070000011 AARCH64_AUTH_RELRSZ  8 (bytes)
 // RELR-HEADERS:       0x0000000070000013 AARCH64_AUTH_RELRENT 8 (bytes)
 
 /// SHT_RELR section contains address/bitmap entries
 /// encoding the offsets for relative relocation.
 // RAW-RELR:           Section ({{.+}}) .relr.auth.dyn {
-// RAW-RELR-NEXT:      0x30480
-// RAW-RELR-NEXT:      0x7FCFEFF
+// RAW-RELR-NEXT:      0x303E8
 // RAW-RELR-NEXT:      }
 
 /// Decoded SHT_RELR section is same as UNPACKED,
@@ -79,78 +49,18 @@
 /// Any relative relocations with odd offset stay in SHT_RELA.
 
 // RELR:      Section ({{.+}}) .rela.dyn {
-// RELR-NEXT:   0x30559 R_AARCH64_AUTH_RELATIVE - 0xA
-// RELR-NEXT:   0x304C0 R_AARCH64_AUTH_ABS64 bar2 0x1
-// RELR-NEXT:   0x30508 R_AARCH64_AUTH_ABS64 bar2 0x0
-// RELR-NEXT:   0x30561 R_AARCH64_AUTH_ABS64 bar2 0x0
-// RELR-NEXT:   0x30569 R_AARCH64_AUTH_ABS64 bar2 0x0
-// RELR-NEXT:   0x30571 R_AARCH64_AUTH_ABS64 bar2 0x1
-// RELR-NEXT:   0x30579 R_AARCH64_AUTH_ABS64 bar2 0x1
-// RELR-NEXT:   0x30581 R_AARCH64_AUTH_ABS64 bar2 0x0
-// RELR-NEXT:   0x30500 R_AARCH64_AUTH_ABS64 zed2 0x0
+// RELR-NEXT:   0x30401 R_AARCH64_AUTH_RELATIVE - 0x2
+// RELR-NEXT:   0x303F0 R_AARCH64_AUTH_ABS64 zed2 0x0
+// RELR-NEXT:   0x303F8 R_AARCH64_AUTH_ABS64 bar2 0x0
 // RELR-NEXT: }
 // RELR-NEXT: Section ({{.+}}) .relr.auth.dyn {
-// RELR-NEXT:   0x30480 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30488 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30490 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30498 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304A0 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304A8 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304B0 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304B8 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304C8 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304D0 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304D8 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304E0 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304E8 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304F0 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x304F8 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30510 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30518 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30520 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30528 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30530 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30538 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30540 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30548 R_AARCH64_RELATIVE -
-// RELR-NEXT:   0x30550 R_AARCH64_RELATIVE -
+// RELR-NEXT:   0x303E8 R_AARCH64_RELATIVE -
 // RELR-NEXT: }
 
 .section .test, "aw"
 .p2align 3
 .quad (__ehdr_start + 1)@AUTH(da,42)
-.quad (__ehdr_start + 2)@AUTH(da,42)
-.quad (__ehdr_start + 3)@AUTH(da,42)
-.quad (__ehdr_start + 4)@AUTH(da,42)
-.quad (__ehdr_start + 5)@AUTH(da,42)
-.quad (__ehdr_start + 6)@AUTH(da,42)
-.quad (__ehdr_start + 7)@AUTH(da,42)
-.quad (__ehdr_start + 8)@AUTH(da,42)
-.quad (bar2 + 1)@AUTH(ia,42)
-
-.quad (__ehdr_start + 1)@AUTH(da,65535)
-.quad (__ehdr_start + 2)@AUTH(da,65535)
-.quad (__ehdr_start + 3)@AUTH(da,65535)
-.quad (__ehdr_start + 4)@AUTH(da,65535)
-.quad (__ehdr_start + 5)@AUTH(da,65535)
-.quad (__ehdr_start + 6)@AUTH(da,65535)
-.quad (__ehdr_start + 7)@AUTH(da,65535)
 .quad zed2 at AUTH(da,42)
 .quad bar2 at AUTH(ia,42)
-
-.quad (__ehdr_start + 1)@AUTH(da,0)
-.quad (__ehdr_start + 2)@AUTH(da,0)
-.quad (__ehdr_start + 3)@AUTH(da,0)
-.quad (__ehdr_start + 4)@AUTH(da,0)
-.quad (__ehdr_start + 5)@AUTH(da,0)
-.quad (__ehdr_start + 6)@AUTH(da,0)
-.quad (__ehdr_start + 7)@AUTH(da,0)
-.quad (__ehdr_start + 8)@AUTH(da,0)
-.quad (__ehdr_start + 9)@AUTH(da,0)
 .byte 00
-.quad (__ehdr_start + 10)@AUTH(da,0)
-.quad bar2 at AUTH(ia,42)
-.quad bar2 at AUTH(ia,42)
-.quad (bar2 + 1)@AUTH(ia,42)
-.quad (bar2 + 1)@AUTH(ia,42)
-.quad bar2 at AUTH(ia,42)
+.quad (__ehdr_start + 2)@AUTH(da,42)

>From 594f8a0e8331b5d11f3efc58fcaa7eae4b9fd7b4 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 11 Jan 2024 03:19:14 +0300
Subject: [PATCH 06/23] Do not emit AUTH relocations in read-only sections

---
 lld/ELF/Relocations.cpp               | 85 +++++++++++++++++++--------
 lld/test/ELF/aarch64-reloc-pauth-ro.s | 21 +++++++
 2 files changed, 80 insertions(+), 26 deletions(-)
 create mode 100644 lld/test/ELF/aarch64-reloc-pauth-ro.s

diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 166407d573252a..53f638ae2f854e 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1125,11 +1125,37 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
                     (isa<EhInputSection>(sec) && config->emachine != EM_MIPS));
   if (canWrite) {
     RelType rel = target->getDynRel(type);
+    if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
+      // Assume relocations from relocatable objects are RELA.
+      assert(config->isRela);
+      std::lock_guard<std::mutex> lock(relocMutex);
+      // For a preemptible symbol, we can't use a relative relocation. For an
+      // undefined symbol, we can't compute offset at link-time and use a
+      // relative relocation. Use a symbolic relocation instead.
+      Partition &part = sec->getPartition();
+      if (sym.isPreemptible || sym.isUndefined()) {
+        part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
+      } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
+                 isInt<32>(sym.getVA(addend))) {
+        // Implicit addend is below 32-bits so we can use the compressed
+        // relative relocation section. The R_AARCH64_AUTH_RELATIVE
+        // has a smaller addend field as bits [63:32] encode the signing-schema.
+        sec->addReloc({expr, type, offset, addend, &sym});
+        part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back(
+            {sec, offset});
+      } else {
+        part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
+                                DynamicReloc::AddendOnlyWithTargetVA, sym,
+                                addend, R_ABS});
+      }
+      return;
+    }
     if (oneof<R_GOT, R_LOONGARCH_GOT>(expr) ||
         (rel == target->symbolicRel && !sym.isPreemptible)) {
       addRelativeReloc<true>(*sec, offset, sym, addend, expr, type);
       return;
-    } else if (rel != 0) {
+    }
+    if (rel != 0) {
       if (config->emachine == EM_MIPS && rel == target->symbolicRel)
         rel = target->relativeRel;
       std::lock_guard<std::mutex> lock(relocMutex);
@@ -1157,6 +1183,12 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
     }
   }
 
+  if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
+    error("relocation " + toString(type) + " against symbol '" + toString(sym) +
+          "'" + " in read-only section" + getLocation(*sec, sym, offset));
+    return;
+  }
+
   // When producing an executable, we can perform copy relocations (for
   // STT_OBJECT) and canonical PLT (for STT_FUNC) if sym is defined by a DSO.
   if (!config->shared && sym.isShared()) {
@@ -1444,31 +1476,32 @@ template <class ELFT, class RelTy> void RelocationScanner::scanOne(RelTy *&i) {
     }
   }
 
-  if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
-    // Assume relocations from relocatable objects are RELA.
-    assert(RelTy::IsRela);
-    std::lock_guard<std::mutex> lock(relocMutex);
-    // For a preemptible symbol, we can't use a relative relocation. For an
-    // undefined symbol, we can't compute offset at link-time and use a relative
-    // relocation. Use a symbolic relocation instead.
-    Partition &part = sec->getPartition();
-    if (sym.isPreemptible || sym.isUndefined()) {
-      part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
-    } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
-               isInt<32>(sym.getVA(addend))) {
-      // Implicit addend is below 32-bits so we can use the compressed
-      // relative relocation section. The R_AARCH64_AUTH_RELATIVE
-      // has a smaller addend fielf as bits [63:32] encode the signing-schema.
-      sec->addReloc({expr, type, offset, addend, &sym});
-      part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back(
-          {sec, offset});
-    } else {
-      part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
-                              DynamicReloc::AddendOnlyWithTargetVA, sym, addend,
-                              R_ABS});
-    }
-    return;
-  }
+  // if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
+  //   // Assume relocations from relocatable objects are RELA.
+  //   assert(RelTy::IsRela);
+  //   std::lock_guard<std::mutex> lock(relocMutex);
+  //   // For a preemptible symbol, we can't use a relative relocation. For an
+  //   // undefined symbol, we can't compute offset at link-time and use a
+  //   relative
+  //   // relocation. Use a symbolic relocation instead.
+  //   Partition &part = sec->getPartition();
+  //   if (sym.isPreemptible || sym.isUndefined()) {
+  //     part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
+  //   } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
+  //              isInt<32>(sym.getVA(addend))) {
+  //     // Implicit addend is below 32-bits so we can use the compressed
+  //     // relative relocation section. The R_AARCH64_AUTH_RELATIVE
+  //     // has a smaller addend fielf as bits [63:32] encode the
+  //     signing-schema. sec->addReloc({expr, type, offset, addend, &sym});
+  //     part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back(
+  //         {sec, offset});
+  //   } else {
+  //     part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
+  //                             DynamicReloc::AddendOnlyWithTargetVA, sym,
+  //                             addend, R_ABS});
+  //   }
+  //   return;
+  // }
 
   // If the relocation does not emit a GOT or GOTPLT entry but its computation
   // uses their addresses, we need GOT or GOTPLT to be created.
diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s
new file mode 100644
index 00000000000000..80afb921a5c26f
--- /dev/null
+++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s
@@ -0,0 +1,21 @@
+// REQUIRES: aarch64
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
+// RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
+// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+// RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck %s
+
+// CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section
+// CHECK-NEXT: defined in
+// CHECK-NEXT: referenced by
+// CHECK-SAME: :(.test+0x0)
+
+// CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section
+// CHECK-NEXT: defined in
+// CHECK-NEXT: referenced by
+// CHECK-SAME: :(.test+0x8)
+
+.section .test, "a"
+.p2align 3
+.quad zed2 at AUTH(da,42)
+.quad bar2 at AUTH(ia,42)

>From acb1730e74ce0ca8c55960018318e9943ec66bfd Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 31 Jan 2024 21:38:05 +0300
Subject: [PATCH 07/23] Apply fix from 37efa70 accidently deleted in d793c0c

---
 lld/ELF/Driver.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index f17ec7759482c2..faf7dcd2d5e81f 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -563,6 +563,7 @@ static void checkZOptions(opt::InputArgList &args) {
   // initialized yet. Claim them here.
   args::getZOptionValue(args, OPT_z, "max-page-size", 0);
   args::getZOptionValue(args, OPT_z, "common-page-size", 0);
+  getZFlag(args, "rel", "rela", false);
   for (auto *arg : args.filtered(OPT_z))
     if (!arg->isClaimed())
       warn("unknown -z value: " + StringRef(arg->getValue()));

>From de73eae53481bb805fbabe97a38055ebaad934de Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 31 Jan 2024 21:39:46 +0300
Subject: [PATCH 08/23] Address review comments

---
 lld/ELF/Relocations.cpp              | 27 ---------------------------
 lld/ELF/SyntheticSections.h          |  3 ++-
 lld/test/ELF/aarch64-feature-pauth.s | 20 ++++++++++----------
 3 files changed, 12 insertions(+), 38 deletions(-)

diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 6e8191f7b4f55e..16ab213b60234a 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1493,33 +1493,6 @@ template <class ELFT, class RelTy> void RelocationScanner::scanOne(RelTy *&i) {
     }
   }
 
-  // if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
-  //   // Assume relocations from relocatable objects are RELA.
-  //   assert(RelTy::IsRela);
-  //   std::lock_guard<std::mutex> lock(relocMutex);
-  //   // For a preemptible symbol, we can't use a relative relocation. For an
-  //   // undefined symbol, we can't compute offset at link-time and use a
-  //   relative
-  //   // relocation. Use a symbolic relocation instead.
-  //   Partition &part = sec->getPartition();
-  //   if (sym.isPreemptible || sym.isUndefined()) {
-  //     part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
-  //   } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
-  //              isInt<32>(sym.getVA(addend))) {
-  //     // Implicit addend is below 32-bits so we can use the compressed
-  //     // relative relocation section. The R_AARCH64_AUTH_RELATIVE
-  //     // has a smaller addend fielf as bits [63:32] encode the
-  //     signing-schema. sec->addReloc({expr, type, offset, addend, &sym});
-  //     part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back(
-  //         {sec, offset});
-  //   } else {
-  //     part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
-  //                             DynamicReloc::AddendOnlyWithTargetVA, sym,
-  //                             addend, R_ABS});
-  //   }
-  //   return;
-  // }
-
   // If the relocation does not emit a GOT or GOTPLT entry but its computation
   // uses their addresses, we need GOT or GOTPLT to be created.
   //
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 79fe636cc09ef3..c36f08e26c2a7b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -554,7 +554,8 @@ class RelocationBaseSection : public SyntheticSection {
     return SyntheticSection::classof(d) &&
            (d->type == llvm::ELF::SHT_RELA || d->type == llvm::ELF::SHT_REL ||
             d->type == llvm::ELF::SHT_RELR ||
-            d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR);
+            (config->emachine == llvm::ELF::EM_AARCH64 &&
+             d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR));
   }
   int32_t dynamicTag, sizeDynamicTag;
   SmallVector<DynamicReloc, 0> relocs;
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index 9060eb71f81757..4d1b9d9164004f 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -13,20 +13,20 @@
 # RUN: not ld.lld tag11.o tag12.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s
 
 # ERR1: error: incompatible values of AArch64 PAuth compatibility info found
-# ERR1: {{.*}}: 0x2A000000000000000{{1|2}}00000000000000
-# ERR1: {{.*}}: 0x2A000000000000000{{1|2}}00000000000000
+# ERR1: tag11.o: 0x2A000000000000000{{1|2}}00000000000000
+# ERR1: tag2.o: 0x2A000000000000000{{1|2}}00000000000000
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o
 # RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s
 
-# ERR2:      error: {{.*}}: invalid type field value 42 (1 expected)
-# ERR2-NEXT: error: {{.*}}: invalid name field value XXX (ARM expected)
-# ERR2-NEXT: error: {{.*}}: AArch64 PAuth compatibility info is too short (at least 16 bytes expected)
+# ERR2:      error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid type field value 42 (1 expected)
+# ERR2-NEXT: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid name field value XXX (ARM expected)
+# ERR2-NEXT: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): AArch64 PAuth compatibility info is too short (at least 16 bytes expected)
 
 # 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 ERR3 %s
 
-# ERR3: error: {{.*}}: section is too short
+# ERR3: error: short.o:(.note.AARCH64-PAUTH-ABI-tag): section is too short
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o
 # RUN: cp noinfo1.o noinfo2.o
@@ -34,10 +34,10 @@
 # RUN: ld.lld -z pauth-report=warning tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s
 # RUN: ld.lld -z pauth-report=none tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix NONE %s
 
-# ERR4:      error: {{.*}}noinfo1.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it
-# ERR4-NEXT: error: {{.*}}noinfo2.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it
-# WARN:      warning: {{.*}}noinfo1.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it
-# WARN-NEXT: warning: {{.*}}noinfo2.o has no AArch64 PAuth compatibility info while {{.*}}tag11.o has one; either all or no input files must have it
+# ERR4:      error: noinfo1.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it
+# ERR4-NEXT: error: noinfo2.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it
+# WARN:      warning: noinfo1.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it
+# WARN-NEXT: warning: noinfo2.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it
 # NONE-NOT:  {{.*}} has no AArch64 PAuth compatibility info while {{.*}} has one; either all or no input files must have it
 
 #--- abi-tag-short.s

>From aff3a96d4383b6aa930d4d21db949b3b459f2163 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 15 Feb 2024 12:38:42 +0300
Subject: [PATCH 09/23] Address several review comments

---
 lld/ELF/Config.h                      |  2 +-
 lld/ELF/Driver.cpp                    | 21 ++++++++-------------
 lld/ELF/InputFiles.cpp                |  2 +-
 lld/ELF/InputFiles.h                  |  2 +-
 lld/ELF/Relocations.cpp               |  4 +---
 lld/ELF/SyntheticSections.cpp         |  2 +-
 lld/test/ELF/aarch64-reloc-pauth-ro.s | 12 +++++-------
 7 files changed, 18 insertions(+), 27 deletions(-)

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index eb76f72f2196f7..22d706688334f2 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -497,7 +497,7 @@ struct Ctx {
 
   llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &);
 
-  SmallVector<uint8_t, 0> aarch64PauthAbiTag;
+  ArrayRef<uint8_t> aarch64PauthAbiTag;
 };
 
 LLVM_LIBRARY_VISIBILITY extern Ctx ctx;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 096b9b2de401c4..c1eb2df9e37161 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2624,9 +2624,6 @@ static uint32_t getAndFeatures() {
 }
 
 static void getAArch64PauthInfo() {
-  if (ctx.objectFiles.empty())
-    return;
-
   auto it = std::find_if(
       ctx.objectFiles.begin(), ctx.objectFiles.end(),
       [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); });
@@ -2635,11 +2632,11 @@ static void getAArch64PauthInfo() {
 
   ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag;
   StringRef f1 = (*it)->getName();
-  for (ELFFileBase *f : ArrayRef(ctx.objectFiles)) {
+  for (ELFFileBase *f : ctx.objectFiles) {
     StringRef f2 = f->getName();
-    const SmallVector<uint8_t, 0> &d1 = ctx.aarch64PauthAbiTag;
-    const SmallVector<uint8_t, 0> &d2 = f->aarch64PauthAbiTag;
-    if (d1.empty() != d2.empty()) {
+    ArrayRef<uint8_t> d1 = ctx.aarch64PauthAbiTag;
+    ArrayRef<uint8_t> d2 = f->aarch64PauthAbiTag;
+    if (d2.empty()) {
       auto helper = [](StringRef report, const Twine &msg) {
         if (report == "warning")
           warn(msg);
@@ -2648,14 +2645,12 @@ static void getAArch64PauthInfo() {
       };
 
       helper(config->zPauthReport,
-             (d1.empty() ? f1.str() : f2.str()) +
-                 " has no AArch64 PAuth compatibility info while " +
-                 (d1.empty() ? f2.str() : f1.str()) +
+             f2.str() + " has no AArch64 PAuth compatibility info while " +
+                 f1.str() +
                  " has one; either all or no input files must have it");
+      continue;
     }
-
-    if (!d1.empty() && !d2.empty() &&
-        !std::equal(d1.begin(), d1.end(), d2.begin(), d2.end()))
+    if (!std::equal(d1.begin(), d1.end(), d2.begin(), d2.end()))
       errorOrWarn(
           "incompatible values of AArch64 PAuth compatibility info found"
           "\n" +
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 90480e142477ef..3f7ef755a83af8 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -997,7 +997,7 @@ static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile<ELFT> &f) {
     return;
   }
 
-  f.aarch64PauthAbiTag = SmallVector<uint8_t, 0>(iterator_range(desc));
+  f.aarch64PauthAbiTag = desc;
 }
 
 template <class ELFT>
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index c881a801182806..51db76dae17307 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -218,7 +218,7 @@ class ELFFileBase : public InputFile {
 public:
   uint32_t andFeatures = 0;
   bool hasCommonSyms = false;
-  SmallVector<uint8_t, 0> aarch64PauthAbiTag;
+  ArrayRef<uint8_t> aarch64PauthAbiTag;
 };
 
 // .o file.
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index fafabc0caf9d03..157c6b734c493b 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1138,14 +1138,12 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
   if (canWrite) {
     RelType rel = target->getDynRel(type);
     if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
-      // Assume relocations from relocatable objects are RELA.
-      assert(config->isRela);
       std::lock_guard<std::mutex> lock(relocMutex);
       // For a preemptible symbol, we can't use a relative relocation. For an
       // undefined symbol, we can't compute offset at link-time and use a
       // relative relocation. Use a symbolic relocation instead.
       Partition &part = sec->getPartition();
-      if (sym.isPreemptible || sym.isUndefined()) {
+      if (sym.isPreemptible) {
         part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
       } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
                  isInt<32>(sym.getVA(addend))) {
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2dcb81d6f95d12..eea77295ae1a4f 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -340,7 +340,7 @@ bool AArch64PauthAbiTag::isNeeded() const {
 }
 
 void AArch64PauthAbiTag::writeTo(uint8_t *buf) {
-  const SmallVector<uint8_t, 0> &data = ctx.aarch64PauthAbiTag;
+  ArrayRef<uint8_t> data = ctx.aarch64PauthAbiTag;
   write32(buf, 4);                             // Name size
   write32(buf + 4, data.size());               // Content size
   write32(buf + 8, NT_ARM_TYPE_PAUTH_ABI_TAG); // Type
diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s
index 80afb921a5c26f..61a52a1e4f8af2 100644
--- a/lld/test/ELF/aarch64-reloc-pauth-ro.s
+++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s
@@ -3,17 +3,15 @@
 // RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
 // RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
 // RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
-// RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck %s
+// RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s
 
 // CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section
-// CHECK-NEXT: defined in
-// CHECK-NEXT: referenced by
-// CHECK-SAME: :(.test+0x0)
+// CHECK-NEXT: defined in [[FILE]].so
+// CHECK-NEXT: referenced by [[FILE]].o:(.test+0x0)
 
 // CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section
-// CHECK-NEXT: defined in
-// CHECK-NEXT: referenced by
-// CHECK-SAME: :(.test+0x8)
+// CHECK-NEXT: defined in [[FILE]].so
+// CHECK-NEXT: referenced by [[FILE]].o:(.test+0x8)
 
 .section .test, "a"
 .p2align 3

>From 4e53afaa50e63466263d0697e0e2a335d281dbf6 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 15 Feb 2024 14:58:15 +0300
Subject: [PATCH 10/23] Address several review comments

---
 lld/ELF/InputFiles.cpp                |  17 ++---
 lld/ELF/Relocations.cpp               |   5 +-
 lld/test/ELF/aarch64-feature-pauth.s  |  29 +++----
 lld/test/ELF/aarch64-reloc-pauth-ro.s |  22 +++---
 lld/test/ELF/aarch64-reloc-pauth.s    | 105 ++++++++++++--------------
 5 files changed, 85 insertions(+), 93 deletions(-)

diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 3f7ef755a83af8..f8030d0f773695 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -971,28 +971,27 @@ static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile<ELFT> &f) {
   using Elf_Nhdr = typename ELFT::Nhdr;
   using Elf_Note = typename ELFT::Note;
   ArrayRef<uint8_t> data = sec.content();
-  auto reportError = [&](const Twine &msg) {
-    errorOrWarn(toString(sec.file) + ":(" + sec.name + "): " + msg);
-  };
 
   auto *nhdr = reinterpret_cast<const Elf_Nhdr *>(data.data());
   if (data.size() < sizeof(Elf_Nhdr) ||
       data.size() < nhdr->getSize(sec.addralign)) {
-    reportError("section is too short");
+    errorOrWarn(toString(&sec) + ": section is too short");
     return;
   }
 
   Elf_Note note(*nhdr);
   if (nhdr->n_type != NT_ARM_TYPE_PAUTH_ABI_TAG)
-    reportError("invalid type field value " + Twine(nhdr->n_type) + " (" +
-                Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) + " expected)");
+    errorOrWarn(toString(&sec) + ": invalid type field value " +
+                Twine(nhdr->n_type) + " (" + Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) +
+                " expected)");
   if (note.getName() != "ARM")
-    reportError("invalid name field value " + note.getName() +
-                " (ARM expected)");
+    errorOrWarn(toString(&sec) + ": invalid name field value " +
+                note.getName() + " (ARM expected)");
 
   ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
   if (desc.size() < 16) {
-    reportError("AArch64 PAuth compatibility info is too short "
+    errorOrWarn(toString(&sec) +
+                ": AArch64 PAuth compatibility info is too short "
                 "(at least 16 bytes expected)");
     return;
   }
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 157c6b734c493b..f5e00e4a8de59e 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1194,8 +1194,9 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
   }
 
   if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
-    error("relocation " + toString(type) + " against symbol '" + toString(sym) +
-          "'" + " in read-only section" + getLocation(*sec, sym, offset));
+    errorOrWarn("relocation " + toString(type) + " against symbol '" +
+                toString(sym) + "'" + " in read-only section" +
+                getLocation(*sec, sym, offset));
     return;
   }
 
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index 4d1b9d9164004f..229b9203c4332f 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -2,18 +2,18 @@
 
 # RUN: rm -rf %t && split-file %s %t && cd %t
 
-# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag1.s -o tag11.o
-# RUN: cp tag11.o tag12.o
-# RUN: ld.lld -shared tag11.o tag12.o -o tagok.so
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag1.s -o tag1.o
+# RUN: cp tag1.o tag1a.o
+# RUN: ld.lld -shared tag1.o tag1a.o -o tagok.so
 # RUN: llvm-readelf -n tagok.so | FileCheck --check-prefix OK %s
 
 # OK: AArch64 PAuth ABI tag: platform 0x2a, version 0x1
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag2.s -o tag2.o
-# RUN: not ld.lld tag11.o tag12.o tag2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s
+# 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 compatibility info found
-# ERR1: tag11.o: 0x2A000000000000000{{1|2}}00000000000000
+# ERR1: tag1.o: 0x2A000000000000000{{1|2}}00000000000000
 # ERR1: tag2.o: 0x2A000000000000000{{1|2}}00000000000000
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o
@@ -30,15 +30,14 @@
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o
 # RUN: cp noinfo1.o noinfo2.o
-# RUN: not ld.lld -z pauth-report=error tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s
-# RUN: ld.lld -z pauth-report=warning tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s
-# RUN: ld.lld -z pauth-report=none tag11.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix NONE %s
+# RUN: not ld.lld -z pauth-report=error tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s
+# RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s
+# RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null
 
-# ERR4:      error: noinfo1.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it
-# ERR4-NEXT: error: noinfo2.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it
-# WARN:      warning: noinfo1.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it
-# WARN-NEXT: warning: noinfo2.o has no AArch64 PAuth compatibility info while tag11.o has one; either all or no input files must have it
-# NONE-NOT:  {{.*}} has no AArch64 PAuth compatibility info while {{.*}} has one; either all or no input files must have it
+# ERR4:      error: noinfo1.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it
+# ERR4-NEXT: error: noinfo2.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it
+# WARN:      warning: noinfo1.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it
+# WARN-NEXT: warning: noinfo2.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it
 
 #--- abi-tag-short.s
 
@@ -80,4 +79,8 @@
 
 #--- no-info.s
 
+.globl _start;   // define _start to avoid missing entry warning and use --fatal-warnings to assert no diagnostic
+.weak _start;    // allow multiple definitions of _start for simplicity
+_start:
+
 .section ".test", "a"
diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s
index 61a52a1e4f8af2..4e496d52ab548f 100644
--- a/lld/test/ELF/aarch64-reloc-pauth-ro.s
+++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s
@@ -1,17 +1,17 @@
-// REQUIRES: aarch64
+# REQUIRES: aarch64
 
-// RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
-// RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
-// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
-// RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
+# RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s
 
-// CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section
-// CHECK-NEXT: defined in [[FILE]].so
-// CHECK-NEXT: referenced by [[FILE]].o:(.test+0x0)
+# CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section
+# CHECK-NEXT: defined in [[FILE]].so
+# CHECK-NEXT: referenced by [[FILE]].o:(.test+0x0)
 
-// CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section
-// CHECK-NEXT: defined in [[FILE]].so
-// CHECK-NEXT: referenced by [[FILE]].o:(.test+0x8)
+# CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section
+# CHECK-NEXT: defined in [[FILE]].so
+# CHECK-NEXT: referenced by [[FILE]].o:(.test+0x8)
 
 .section .test, "a"
 .p2align 3
diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 79e6e4246cc457..8c0f147d783c56 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -1,61 +1,50 @@
-// REQUIRES: aarch64
-
-// RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
-// RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
-// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
-// RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2
-// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s
-
-// UNPACKED:          Section ({{.+}}) .rela.dyn {
-// UNPACKED-NEXT:       0x303C8 R_AARCH64_AUTH_RELATIVE - 0x1
-// UNPACKED-NEXT:       0x303E1 R_AARCH64_AUTH_RELATIVE - 0x2
-// UNPACKED-NEXT:       0x303D0 R_AARCH64_AUTH_ABS64 zed2 0x0
-// UNPACKED-NEXT:       0x303D8 R_AARCH64_AUTH_ABS64 bar2 0x0
-// UNPACKED-NEXT:     }
-
-// RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2
-// RUN: llvm-readobj -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s
-// RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s
-// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s
-
-// RELR-HEADERS:       Index: 1
-// RELR-HEADERS-NEXT:  Name: .dynsym
-
-// RELR-HEADERS:       Name: .relr.auth.dyn
-// RELR-HEADERS-NEXT:  Type: SHT_AARCH64_AUTH_RELR
-// RELR-HEADERS-NEXT:  Flags [ (0x2)
-// RELR-HEADERS-NEXT:    SHF_ALLOC (0x2)
-// RELR-HEADERS-NEXT:  ]
-// RELR-HEADERS-NEXT:  Address: [[ADDR:.*]]
-// RELR-HEADERS-NEXT:  Offset: [[ADDR]]
-// RELR-HEADERS-NEXT:  Size: 8
-// RELR-HEADERS-NEXT:  Link: 0
-// RELR-HEADERS-NEXT:  Info: 0
-// RELR-HEADERS-NEXT:  AddressAlignment: 8
-// RELR-HEADERS-NEXT:  EntrySize: 8
-
-// RELR-HEADERS:       0x0000000070000012 AARCH64_AUTH_RELR    [[ADDR]]
-// RELR-HEADERS:       0x0000000070000011 AARCH64_AUTH_RELRSZ  8 (bytes)
-// RELR-HEADERS:       0x0000000070000013 AARCH64_AUTH_RELRENT 8 (bytes)
-
-/// SHT_RELR section contains address/bitmap entries
-/// encoding the offsets for relative relocation.
-// RAW-RELR:           Section ({{.+}}) .relr.auth.dyn {
-// RAW-RELR-NEXT:      0x303E8
-// RAW-RELR-NEXT:      }
-
-/// Decoded SHT_RELR section is same as UNPACKED,
-/// but contains only the relative relocations.
-/// Any relative relocations with odd offset stay in SHT_RELA.
-
-// RELR:      Section ({{.+}}) .rela.dyn {
-// RELR-NEXT:   0x30401 R_AARCH64_AUTH_RELATIVE - 0x2
-// RELR-NEXT:   0x303F0 R_AARCH64_AUTH_ABS64 zed2 0x0
-// RELR-NEXT:   0x303F8 R_AARCH64_AUTH_ABS64 bar2 0x0
-// RELR-NEXT: }
-// RELR-NEXT: Section ({{.+}}) .relr.auth.dyn {
-// RELR-NEXT:   0x303E8 R_AARCH64_RELATIVE -
-// RELR-NEXT: }
+# REQUIRES: aarch64
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
+# RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2
+# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s
+
+# UNPACKED:          Section ({{.+}}) .rela.dyn {
+# UNPACKED-NEXT:       0x303C8 R_AARCH64_AUTH_RELATIVE - 0x1
+# UNPACKED-NEXT:       0x303E1 R_AARCH64_AUTH_RELATIVE - 0x2
+# UNPACKED-NEXT:       0x303D0 R_AARCH64_AUTH_ABS64 zed2 0x0
+# UNPACKED-NEXT:       0x303D8 R_AARCH64_AUTH_ABS64 bar2 0x0
+# UNPACKED-NEXT:     }
+
+# RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2
+# RUN: llvm-readelf -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s
+# RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s
+# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s
+
+# RELR-HEADERS:      Section Headers:
+# RELR-HEADERS-NEXT: Name Type Address Off Size ES Flg Lk Inf Al
+# RELR-HEADERS:      .relr.auth.dyn AARCH64_AUTH_RELR 0000000000[[ADDR:.*]] [[ADDR]] 000008 08 A 0 0 8
+
+# RELR-HEADERS:      Dynamic section at offset 0x2e8 contains 16 entries
+# RELR-HEADERS:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x2e0
+# RELR-HEADERS-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 8 (bytes)
+# RELR-HEADERS-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)
+
+## SHT_RELR section contains address/bitmap entries
+## encoding the offsets for relative relocation.
+# RAW-RELR:           Section ({{.+}}) .relr.auth.dyn {
+# RAW-RELR-NEXT:      0x303E8
+# RAW-RELR-NEXT:      }
+
+## Decoded SHT_RELR section is same as UNPACKED,
+## but contains only the relative relocations.
+## Any relative relocations with odd offset stay in SHT_RELA.
+
+# RELR:      Section ({{.+}}) .rela.dyn {
+# RELR-NEXT:   0x30401 R_AARCH64_AUTH_RELATIVE - 0x2
+# RELR-NEXT:   0x303F0 R_AARCH64_AUTH_ABS64 zed2 0x0
+# RELR-NEXT:   0x303F8 R_AARCH64_AUTH_ABS64 bar2 0x0
+# RELR-NEXT: }
+# RELR-NEXT: Section ({{.+}}) .relr.auth.dyn {
+# RELR-NEXT:   0x303E8 R_AARCH64_RELATIVE -
+# RELR-NEXT: }
 
 .section .test, "aw"
 .p2align 3

>From ec1c6322341f3f25f3ad0070810c4a90d188c3b5 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Sat, 17 Feb 2024 04:13:30 +0300
Subject: [PATCH 11/23] Address review comments

---
 lld/test/ELF/aarch64-reloc-pauth.s | 95 ++++++++++++++++++++++++------
 1 file changed, 77 insertions(+), 18 deletions(-)

diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 8c0f147d783c56..aeed86f42e88f9 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -3,53 +3,112 @@
 # RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
 # RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
 # RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+
 # RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2
 # RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s
 
 # UNPACKED:          Section ({{.+}}) .rela.dyn {
-# UNPACKED-NEXT:       0x303C8 R_AARCH64_AUTH_RELATIVE - 0x1
-# UNPACKED-NEXT:       0x303E1 R_AARCH64_AUTH_RELATIVE - 0x2
-# UNPACKED-NEXT:       0x303D0 R_AARCH64_AUTH_ABS64 zed2 0x0
-# UNPACKED-NEXT:       0x303D8 R_AARCH64_AUTH_ABS64 bar2 0x0
+# UNPACKED-NEXT:       0x30440 R_AARCH64_AUTH_RELATIVE - 0x1
+# UNPACKED-NEXT:       0x30448 R_AARCH64_AUTH_RELATIVE - 0x2
+# UNPACKED-NEXT:       0x30450 R_AARCH64_AUTH_RELATIVE - 0x3
+# UNPACKED-NEXT:       0x30458 R_AARCH64_AUTH_RELATIVE - 0x12345678
+# UNPACKED-NEXT:       0x30460 R_AARCH64_AUTH_RELATIVE - 0x123456789A
+# UNPACKED-NEXT:       0x30479 R_AARCH64_AUTH_RELATIVE - 0x4
+# UNPACKED-NEXT:       0x30482 R_AARCH64_AUTH_RELATIVE - 0x5
+# UNPACKED-NEXT:       0x30468 R_AARCH64_AUTH_ABS64 zed2 0x0
+# UNPACKED-NEXT:       0x30470 R_AARCH64_AUTH_ABS64 bar2 0x0
 # UNPACKED-NEXT:     }
 
 # RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2
 # RUN: llvm-readelf -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s
-# RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s
-# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s
 
 # RELR-HEADERS:      Section Headers:
 # RELR-HEADERS-NEXT: Name Type Address Off Size ES Flg Lk Inf Al
-# RELR-HEADERS:      .relr.auth.dyn AARCH64_AUTH_RELR 0000000000[[ADDR:.*]] [[ADDR]] 000008 08 A 0 0 8
+# RELR-HEADERS:      .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8
 
-# RELR-HEADERS:      Dynamic section at offset 0x2e8 contains 16 entries
-# RELR-HEADERS:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x2e0
-# RELR-HEADERS-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 8 (bytes)
+# RELR-HEADERS:      Dynamic section at offset 0x310 contains 16 entries
+# RELR-HEADERS:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]]
+# RELR-HEADERS-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes)
 # RELR-HEADERS-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)
 
+# RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s
+
 ## SHT_RELR section contains address/bitmap entries
 ## encoding the offsets for relative relocation.
+
 # RAW-RELR:           Section ({{.+}}) .relr.auth.dyn {
-# RAW-RELR-NEXT:      0x303E8
+# RAW-RELR-NEXT:      0x30410
+# RAW-RELR-NEXT:      0xF
+# RAW-RELR-NEXT:      0x30452
 # RAW-RELR-NEXT:      }
 
+# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s
+
 ## Decoded SHT_RELR section is same as UNPACKED,
 ## but contains only the relative relocations.
 ## Any relative relocations with odd offset stay in SHT_RELA.
 
 # RELR:      Section ({{.+}}) .rela.dyn {
-# RELR-NEXT:   0x30401 R_AARCH64_AUTH_RELATIVE - 0x2
-# RELR-NEXT:   0x303F0 R_AARCH64_AUTH_ABS64 zed2 0x0
-# RELR-NEXT:   0x303F8 R_AARCH64_AUTH_ABS64 bar2 0x0
+# RELR-NEXT:   0x30430 R_AARCH64_AUTH_RELATIVE - 0x123456789A
+# RELR-NEXT:   0x30449 R_AARCH64_AUTH_RELATIVE - 0x4
+# RELR-NEXT:   0x30438 R_AARCH64_AUTH_ABS64 zed2 0x0
+# RELR-NEXT:   0x30440 R_AARCH64_AUTH_ABS64 bar2 0x0
 # RELR-NEXT: }
 # RELR-NEXT: Section ({{.+}}) .relr.auth.dyn {
-# RELR-NEXT:   0x303E8 R_AARCH64_RELATIVE -
+# RELR-NEXT:   0x30410 R_AARCH64_RELATIVE -
+# RELR-NEXT:   0x30418 R_AARCH64_RELATIVE -
+# RELR-NEXT:   0x30420 R_AARCH64_RELATIVE -
+# RELR-NEXT:   0x30428 R_AARCH64_RELATIVE -
+# RELR-NEXT:   0x30452 R_AARCH64_RELATIVE -
 # RELR-NEXT: }
 
+# RUN: llvm-readobj -x .test %t2 | FileCheck --check-prefix=HEX %s
+
+# HEX:      Hex dump of section '.test':
+# HEX-NEXT: 0x00030410 01000000 2a000020 02000000 2b000000
+##                     ^^^^^^^^ Addend = 1
+##                              ^^^^ Discr = 42
+##                                    ^^ Key (bits 5..6) = DA
+##                                       ^^^^^^^^ Addend = 2
+##                                                ^^^^ Discr = 43
+##                                                      ^^ Key (bits 5..6) = IA
+# HEX-NEXT: 0x00030420 03000000 2c000080 78563412 2d000020
+##                     ^^^^^^^^ Addend = 3
+##                              ^^^^ Discr = 44
+##                                    ^^ Key (bits 5..6) = IA
+##                                    ^^ Addr diversity (bit 7) = true
+##                                       ^^^^^^^^ Addend = 0x12345678
+##                                                ^^^^ Discr = 45
+##                                                      ^^ Key (bits 5..6) = DA
+# HEX-NEXT: 0x00030430 00000000 2e000020 00000000 2f000020
+##                     ^^^^^^^^ No implicit addend (rela reloc)
+##                              ^^^^ Discr = 46
+##                                    ^^ Key (bits 5..6) = DA
+##                                       ^^^^^^^^ Addend = 0
+##                                                ^^^^ Discr = 47
+##                                                      ^^ Key (bits 5..6) = DA
+# HEX-NEXT: 0x00030440 00000000 30000000 00000000 00310000
+##                     ^^^^^^^^ Addend = 0
+##                              ^^^^ Discr = 48
+##                                    ^^ Key (bits 5..6) = IA
+##                                         ^^^^^^ ^^ No implicit addend (rela reloc)
+##                                                  ^^^^ Discr = 49
+# HEX-NEXT: 0x00030450 20000500 00003200 0020{{\ }}
+##                     ^^ Key (bits 5..6) = DA
+##                         ^^^^ ^^^^ Addend = 5
+##                                  ^^^^ Discr = 48
+##                                         ^^ Key (bits 5..6) = DA
+
 .section .test, "aw"
 .p2align 3
 .quad (__ehdr_start + 1)@AUTH(da,42)
-.quad zed2 at AUTH(da,42)
-.quad bar2 at AUTH(ia,42)
+.quad (__ehdr_start + 2)@AUTH(ia,43)
+.quad (__ehdr_start + 3)@AUTH(ia,44,addr)
+.quad (__ehdr_start + 0x12345678)@AUTH(da,45)
+.quad (__ehdr_start + 0x123456789A)@AUTH(da,46)
+.quad zed2 at AUTH(da,47)
+.quad bar2 at AUTH(ia,48)
+.byte 00
+.quad (__ehdr_start + 4)@AUTH(da,49)
 .byte 00
-.quad (__ehdr_start + 2)@AUTH(da,42)
+.quad (__ehdr_start + 5)@AUTH(da,50)

>From 2136ad1f2c8e92d52fb0b96a77c4cbc7828916b3 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 19 Feb 2024 17:22:33 -0800
Subject: [PATCH 12/23] Simplify RelocationScanner::processAux

---
 lld/ELF/Arch/AArch64.cpp |  2 +-
 lld/ELF/Relocations.cpp  | 48 +++++++++++++++++++---------------------
 2 files changed, 24 insertions(+), 26 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 79318637d85e9d..20f637e49f1874 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -205,7 +205,7 @@ bool AArch64::usesOnlyLowPageBits(RelType type) const {
 }
 
 RelType AArch64::getDynRel(RelType type) const {
-  if (type == R_AARCH64_ABS64)
+  if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64)
     return type;
   return R_AARCH64_NONE;
 }
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index f5e00e4a8de59e..926de8748e72da 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1137,29 +1137,6 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
                     (isa<EhInputSection>(sec) && config->emachine != EM_MIPS));
   if (canWrite) {
     RelType rel = target->getDynRel(type);
-    if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
-      std::lock_guard<std::mutex> lock(relocMutex);
-      // For a preemptible symbol, we can't use a relative relocation. For an
-      // undefined symbol, we can't compute offset at link-time and use a
-      // relative relocation. Use a symbolic relocation instead.
-      Partition &part = sec->getPartition();
-      if (sym.isPreemptible) {
-        part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
-      } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
-                 isInt<32>(sym.getVA(addend))) {
-        // Implicit addend is below 32-bits so we can use the compressed
-        // relative relocation section. The R_AARCH64_AUTH_RELATIVE
-        // has a smaller addend field as bits [63:32] encode the signing-schema.
-        sec->addReloc({expr, type, offset, addend, &sym});
-        part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back(
-            {sec, offset});
-      } else {
-        part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
-                                DynamicReloc::AddendOnlyWithTargetVA, sym,
-                                addend, R_ABS});
-      }
-      return;
-    }
     if (oneof<R_GOT, R_LOONGARCH_GOT>(expr) ||
         (rel == target->symbolicRel && !sym.isPreemptible)) {
       addRelativeReloc<true>(*sec, offset, sym, addend, expr, type);
@@ -1169,8 +1146,29 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
       if (config->emachine == EM_MIPS && rel == target->symbolicRel)
         rel = target->relativeRel;
       std::lock_guard<std::mutex> lock(relocMutex);
-      sec->getPartition().relaDyn->addSymbolReloc(rel, *sec, offset, sym,
-                                                  addend, type);
+      Partition &part = sec->getPartition();
+      if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
+        // For a preemptible symbol, we can't use a relative relocation. For an
+        // undefined symbol, we can't compute offset at link-time and use a
+        // relative relocation. Use a symbolic relocation instead.
+        if (sym.isPreemptible) {
+          part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
+        } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
+                   isInt<32>(sym.getVA(addend))) {
+          // Implicit addend is below 32-bits so we can use the compressed
+          // relative relocation section. The R_AARCH64_AUTH_RELATIVE has a
+          // smaller addend field as bits [63:32] encode the signing-schema.
+          sec->addReloc({expr, type, offset, addend, &sym});
+          part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back(
+              {sec, offset});
+        } else {
+          part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
+                                  DynamicReloc::AddendOnlyWithTargetVA, sym,
+                                  addend, R_ABS});
+        }
+        return;
+      }
+      part.relaDyn->addSymbolReloc(rel, *sec, offset, sym, addend, type);
 
       // MIPS ABI turns using of GOT and dynamic relocations inside out.
       // While regular ABI uses dynamic relocations to fill up GOT entries

>From 9ea8c5c45f5615f5c09e54cb23290ae174b7c82a Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 19 Feb 2024 17:32:21 -0800
Subject: [PATCH 13/23] Fix error message in a read-only section when the
 symbol is local

---
 lld/ELF/Relocations.cpp               | 12 ++++--------
 lld/test/ELF/aarch64-reloc-pauth-ro.s | 17 ++++++++++-------
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 926de8748e72da..eb4b38a99c72f8 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1191,16 +1191,12 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
     }
   }
 
-  if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
-    errorOrWarn("relocation " + toString(type) + " against symbol '" +
-                toString(sym) + "'" + " in read-only section" +
-                getLocation(*sec, sym, offset));
-    return;
-  }
-
   // When producing an executable, we can perform copy relocations (for
   // STT_OBJECT) and canonical PLT (for STT_FUNC) if sym is defined by a DSO.
-  if (!config->shared && sym.isShared()) {
+  // Copy relocations/canonical PLT entries are unsupported for
+  // R_AARCH64_AUTH_ABS64.
+  if (!config->shared && sym.isShared() &&
+      !(config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64)) {
     if (!canDefineSymbolInExecutable(sym)) {
       errorOrWarn("cannot preempt symbol: " + toString(sym) +
                   getLocation(*sec, sym, offset));
diff --git a/lld/test/ELF/aarch64-reloc-pauth-ro.s b/lld/test/ELF/aarch64-reloc-pauth-ro.s
index 4e496d52ab548f..5bc9d805b481a7 100644
--- a/lld/test/ELF/aarch64-reloc-pauth-ro.s
+++ b/lld/test/ELF/aarch64-reloc-pauth-ro.s
@@ -5,15 +5,18 @@
 # RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
 # RUN: not ld.lld -pie %t.o %t.so -o %t2 2>&1 | FileCheck -DFILE=%t %s
 
-# CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'zed2' in read-only section
-# CHECK-NEXT: defined in [[FILE]].so
-# CHECK-NEXT: referenced by [[FILE]].o:(.test+0x0)
+# CHECK:      error: relocation R_AARCH64_AUTH_ABS64 cannot be used against symbol 'zed2'; recompile with -fPIC
+# CHECK-NEXT: >>> defined in [[FILE]].so
+# CHECK-NEXT: >>> referenced by [[FILE]].o:(.ro+0x0)
 
-# CHECK:      error: relocation R_AARCH64_AUTH_ABS64 against symbol 'bar2' in read-only section
-# CHECK-NEXT: defined in [[FILE]].so
-# CHECK-NEXT: referenced by [[FILE]].o:(.test+0x8)
+# CHECK:      error: relocation R_AARCH64_AUTH_ABS64 cannot be used against symbol 'bar2'; recompile with -fPIC
+# CHECK:      error: relocation R_AARCH64_AUTH_ABS64 cannot be used against local symbol; recompile with -fPIC
 
-.section .test, "a"
+foo:
+.type foo, @function
+
+.section .ro, "a"
 .p2align 3
 .quad zed2 at AUTH(da,42)
 .quad bar2 at AUTH(ia,42)
+.quad foo at AUTH(ia,42)

>From e3a64d213c5f3d8f46a4b7fb304ba61c4bba390b Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 19 Feb 2024 18:20:15 -0800
Subject: [PATCH 14/23] Simplify aarch64-reloc-pauth.s

---
 lld/test/ELF/aarch64-reloc-pauth.s | 61 ++++++++++++++----------------
 1 file changed, 29 insertions(+), 32 deletions(-)

diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index aeed86f42e88f9..4bd305dc4f3e60 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -4,8 +4,8 @@
 # RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
 # RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
 
-# RUN: ld.lld -pie -z nopack-relative-relocs %t.o %t.so -o %t2
-# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=UNPACKED %s
+# RUN: ld.lld -pie %t.o %t.so -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=UNPACKED %s
 
 # UNPACKED:          Section ({{.+}}) .rela.dyn {
 # UNPACKED-NEXT:       0x30440 R_AARCH64_AUTH_RELATIVE - 0x1
@@ -20,16 +20,35 @@
 # UNPACKED-NEXT:     }
 
 # RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2
-# RUN: llvm-readelf -S --dynamic-table %t2 | FileCheck --check-prefix=RELR-HEADERS %s
+# RUN: llvm-readelf -S -d -r -x .test %t2 | FileCheck --check-prefixes=RELR,HEX %s
 
-# RELR-HEADERS:      Section Headers:
-# RELR-HEADERS-NEXT: Name Type Address Off Size ES Flg Lk Inf Al
-# RELR-HEADERS:      .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8
+# RELR:      Section Headers:
+# RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al
+# RELR:      .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8
 
-# RELR-HEADERS:      Dynamic section at offset 0x310 contains 16 entries
-# RELR-HEADERS:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]]
-# RELR-HEADERS-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes)
-# RELR-HEADERS-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)
+# RELR:      Dynamic section at offset 0x310 contains 16 entries
+# RELR:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]]
+# RELR-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes)
+# RELR-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)
+
+## Decoded SHT_RELR section is same as UNPACKED,
+## but contains only the relative relocations.
+## Any relative relocations with odd offset stay in SHT_RELA.
+
+# RELR:      Relocation section '.rela.dyn' at offset {{.*}} contains 4 entries:
+# RELR-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
+# RELR-NEXT: 0000000000030430  0000000000000411 R_AARCH64_AUTH_RELATIVE           123456789a
+# RELR-NEXT: 0000000000030449  0000000000000411 R_AARCH64_AUTH_RELATIVE           4
+# RELR-NEXT: 0000000000030438  0000000100000244 R_AARCH64_AUTH_ABS64   0000000000000000 zed2 + 0
+# RELR-NEXT: 0000000000030440  0000000200000244 R_AARCH64_AUTH_ABS64   0000000000000000 bar2 + 0
+# RELR-EMPTY:
+# RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 5 entries:
+# RELR-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name
+# RELR-NEXT: 0000000000030410  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030418  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030420  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030428  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030452  0000000000000403 R_AARCH64_RELATIVE
 
 # RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s
 
@@ -42,28 +61,6 @@
 # RAW-RELR-NEXT:      0x30452
 # RAW-RELR-NEXT:      }
 
-# RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=RELR %s
-
-## Decoded SHT_RELR section is same as UNPACKED,
-## but contains only the relative relocations.
-## Any relative relocations with odd offset stay in SHT_RELA.
-
-# RELR:      Section ({{.+}}) .rela.dyn {
-# RELR-NEXT:   0x30430 R_AARCH64_AUTH_RELATIVE - 0x123456789A
-# RELR-NEXT:   0x30449 R_AARCH64_AUTH_RELATIVE - 0x4
-# RELR-NEXT:   0x30438 R_AARCH64_AUTH_ABS64 zed2 0x0
-# RELR-NEXT:   0x30440 R_AARCH64_AUTH_ABS64 bar2 0x0
-# RELR-NEXT: }
-# RELR-NEXT: Section ({{.+}}) .relr.auth.dyn {
-# RELR-NEXT:   0x30410 R_AARCH64_RELATIVE -
-# RELR-NEXT:   0x30418 R_AARCH64_RELATIVE -
-# RELR-NEXT:   0x30420 R_AARCH64_RELATIVE -
-# RELR-NEXT:   0x30428 R_AARCH64_RELATIVE -
-# RELR-NEXT:   0x30452 R_AARCH64_RELATIVE -
-# RELR-NEXT: }
-
-# RUN: llvm-readobj -x .test %t2 | FileCheck --check-prefix=HEX %s
-
 # HEX:      Hex dump of section '.test':
 # HEX-NEXT: 0x00030410 01000000 2a000020 02000000 2b000000
 ##                     ^^^^^^^^ Addend = 1

>From 865c9839d0186852f3adaae6ab33551e2ca98818 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 19 Feb 2024 18:34:01 -0800
Subject: [PATCH 15/23] Force dynamic relocation in -no-pie mode

R_AARCH64_AUTH_ABS64 requires dynamic behavior, not resolvable by the linker.
---
 lld/ELF/Arch/AArch64.cpp           |  5 +++--
 lld/ELF/InputSection.cpp           |  1 +
 lld/ELF/Relocations.cpp            |  3 ++-
 lld/ELF/Relocations.h              |  1 +
 lld/test/ELF/aarch64-reloc-pauth.s | 15 +++++++++++++++
 5 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 20f637e49f1874..909fbdacdb3036 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -112,8 +112,9 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
   case R_AARCH64_MOVW_UABS_G2:
   case R_AARCH64_MOVW_UABS_G2_NC:
   case R_AARCH64_MOVW_UABS_G3:
-  case R_AARCH64_AUTH_ABS64:
     return R_ABS;
+  case R_AARCH64_AUTH_ABS64:
+    return R_AARCH64_AUTH;
   case R_AARCH64_TLSDESC_ADR_PAGE21:
     return R_AARCH64_TLSDESC_PAGE;
   case R_AARCH64_TLSDESC_LD64_LO12:
@@ -400,7 +401,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
     write64(loc, val);
     break;
   case R_AARCH64_AUTH_ABS64:
-    checkIntUInt(loc, val, 32, rel);
+    assert(isInt<32>(val));
     write32(loc, val);
     break;
   case R_AARCH64_ADD_ABS_LO12_NC:
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index e033a715b59214..4a84842fabb64e 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -674,6 +674,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
   case R_DTPREL:
   case R_RELAX_TLS_LD_TO_LE_ABS:
   case R_RELAX_GOT_PC_NOPIC:
+  case R_AARCH64_AUTH:
   case R_RISCV_ADD:
   case R_RISCV_LEB128:
     return sym.getVA(a);
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index eb4b38a99c72f8..cac385b6f9fcc9 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -995,7 +995,8 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
   if (e == R_GOT || e == R_PLT)
     return target->usesOnlyLowPageBits(type) || !config->isPic;
 
-  if (sym.isPreemptible)
+  // R_AARCH64_AUTH_ABS64 requires a dynamic relocation.
+  if (sym.isPreemptible || e == R_AARCH64_AUTH)
     return false;
   if (!config->isPic)
     return true;
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index 7eb8a811e6934f..b7b9c09e1b8922 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -87,6 +87,7 @@ enum RelExpr {
   R_AARCH64_PAGE_PC,
   R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC,
   R_AARCH64_TLSDESC_PAGE,
+  R_AARCH64_AUTH,
   R_ARM_PCA,
   R_ARM_SBREL,
   R_MIPS_GOTREL,
diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 4bd305dc4f3e60..2c617f2899e65e 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -19,6 +19,21 @@
 # UNPACKED-NEXT:       0x30470 R_AARCH64_AUTH_ABS64 bar2 0x0
 # UNPACKED-NEXT:     }
 
+# RUN: ld.lld %t.o %t.so -o %t.nopie
+# RUN: llvm-readobj -r %t.nopie | FileCheck --check-prefix=NOPIE %s
+
+# NOPIE:      Section ({{.+}}) .rela.dyn {
+# NOPIE:        0x230430 R_AARCH64_AUTH_RELATIVE - 0x200001
+# NOPIE-NEXT:   0x230438 R_AARCH64_AUTH_RELATIVE - 0x200002
+# NOPIE-NEXT:   0x230440 R_AARCH64_AUTH_RELATIVE - 0x200003
+# NOPIE-NEXT:   0x230448 R_AARCH64_AUTH_RELATIVE - 0x12545678
+# NOPIE-NEXT:   0x230450 R_AARCH64_AUTH_RELATIVE - 0x123476789A
+# NOPIE-NEXT:   0x230469 R_AARCH64_AUTH_RELATIVE - 0x200004
+# NOPIE-NEXT:   0x230472 R_AARCH64_AUTH_RELATIVE - 0x200005
+# NOPIE-NEXT:   0x230458 R_AARCH64_AUTH_ABS64 zed2 0x0
+# NOPIE-NEXT:   0x230460 R_AARCH64_AUTH_ABS64 bar2 0x0
+# NOPIE-NEXT: }
+
 # RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2
 # RUN: llvm-readelf -S -d -r -x .test %t2 | FileCheck --check-prefixes=RELR,HEX %s
 

>From 1448a4a4e0e3cb70358558579e97fce3f0990356 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 27 Feb 2024 12:28:59 +0300
Subject: [PATCH 16/23] Address the following review comments:

- issues in lld/test/ELF/aarch64-feature-pauth.s;
- "\n>>> " for error continuation lines;
- `ArrayRef`-related stuff;
- merge `getAndFeatures` and `getAArch64PauthInfo` into
  `readSecurityNotes`;
- change '-z pauth-report' error message to match '-z cet-report'
  and '-z bti-report'.
---
 lld/ELF/Driver.cpp                   | 104 +++++++++++++--------------
 lld/test/ELF/aarch64-feature-pauth.s |  21 +++---
 2 files changed, 62 insertions(+), 63 deletions(-)

diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index c1eb2df9e37161..3390c33e050c93 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2554,14 +2554,17 @@ static void redirectSymbols(ArrayRef<WrappedSymbol> wrapped) {
     symtab.wrap(w.sym, w.real, w.wrap);
 }
 
+static void reportMissingFeature(StringRef config, const Twine &report) {
+  if (config == "error")
+    error(report);
+  else if (config == "warning")
+    warn(report);
+}
+
 static void checkAndReportMissingFeature(StringRef config, uint32_t features,
                                          uint32_t mask, const Twine &report) {
-  if (!(features & mask)) {
-    if (config == "error")
-      error(report);
-    else if (config == "warning")
-      warn(report);
-  }
+  if (!(features & mask))
+    reportMissingFeature(config, report);
 }
 
 // To enable CET (x86's hardware-assisted control flow enforcement), each
@@ -2572,12 +2575,28 @@ static void checkAndReportMissingFeature(StringRef config, uint32_t features,
 //
 // This is also the case with AARCH64's BTI and PAC which use the similar
 // GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism.
-static uint32_t getAndFeatures() {
+//
+// For AArch64 PAuth-enabled object files, the compatibility info of all of them
+// must match. Missing info for some object files with matching info for
+// remaining ones can be allowed (see -z pauth-report).
+static void readSecurityNotes() {
   if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
       config->emachine != EM_AARCH64)
-    return 0;
+    return;
+
+  config->andFeatures = -1;
+
+  StringRef referenceFileName;
+  if (config->emachine == EM_AARCH64) {
+    auto it = std::find_if(
+        ctx.objectFiles.begin(), ctx.objectFiles.end(),
+        [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); });
+    if (it != ctx.objectFiles.end()) {
+      ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag;
+      referenceFileName = (*it)->getName();
+    }
+  }
 
-  uint32_t ret = -1;
   for (ELFFileBase *f : ctx.objectFiles) {
     uint32_t features = f->andFeatures;
 
@@ -2613,50 +2632,31 @@ static uint32_t getAndFeatures() {
                          "GNU_PROPERTY_AARCH64_FEATURE_1_PAC property");
       features |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
     }
-    ret &= features;
-  }
+    config->andFeatures &= features;
 
-  // Force enable Shadow Stack.
-  if (config->zShstk)
-    ret |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
-
-  return ret;
-}
-
-static void getAArch64PauthInfo() {
-  auto it = std::find_if(
-      ctx.objectFiles.begin(), ctx.objectFiles.end(),
-      [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); });
-  if (it == ctx.objectFiles.end())
-    return;
+    if (ctx.aarch64PauthAbiTag.empty())
+      continue;
 
-  ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag;
-  StringRef f1 = (*it)->getName();
-  for (ELFFileBase *f : ctx.objectFiles) {
-    StringRef f2 = f->getName();
-    ArrayRef<uint8_t> d1 = ctx.aarch64PauthAbiTag;
-    ArrayRef<uint8_t> d2 = f->aarch64PauthAbiTag;
-    if (d2.empty()) {
-      auto helper = [](StringRef report, const Twine &msg) {
-        if (report == "warning")
-          warn(msg);
-        else if (report == "error")
-          error(msg);
-      };
-
-      helper(config->zPauthReport,
-             f2.str() + " has no AArch64 PAuth compatibility info while " +
-                 f1.str() +
-                 " has one; either all or no input files must have it");
+    if (f->aarch64PauthAbiTag.empty()) {
+      reportMissingFeature(config->zPauthReport,
+                           toString(f) +
+                               ": -z pauth-report: file does not have AArch64 "
+                               "PAuth compatibility info while " +
+                               referenceFileName + " has one");
       continue;
     }
-    if (!std::equal(d1.begin(), d1.end(), d2.begin(), d2.end()))
+
+    if (ctx.aarch64PauthAbiTag != f->aarch64PauthAbiTag)
       errorOrWarn(
           "incompatible values of AArch64 PAuth compatibility info found"
-          "\n" +
-          f1 + ": 0x" + toHex(ArrayRef(d1.data(), d1.size())) + "\n" + f2 +
-          ": 0x" + toHex(ArrayRef(d2.data(), d2.size())));
+          "\n>>> " +
+          referenceFileName + ": 0x" + toHex(ctx.aarch64PauthAbiTag) +
+          "\n>>> " + toString(f) + ": 0x" + toHex(f->aarch64PauthAbiTag));
   }
+
+  // Force enable Shadow Stack.
+  if (config->zShstk)
+    config->andFeatures |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
 }
 
 static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) {
@@ -2994,12 +2994,12 @@ void LinkerDriver::link(opt::InputArgList &args) {
   // partition.
   mainPart = &partitions[0];
 
-  // Read .note.gnu.property sections from input object files which
-  // contain a hint to tweak linker's and loader's behaviors.
-  config->andFeatures = getAndFeatures();
-
-  if (config->emachine == EM_AARCH64)
-    getAArch64PauthInfo();
+  // Read:
+  // - .note.gnu.property sections from input object files which
+  //   contain a hint to tweak linker's and loader's behaviors;
+  // - .note.AARCH64-PAUTH-ABI-tag sections contents from input object files
+  //   which contain AArch64 PAuth compatibility info.
+  readSecurityNotes();
 
   // The Target instance handles target-specific stuff, such as applying
   // relocations or writing a PLT section. It also contains target-dependent
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index 229b9203c4332f..25c43e6ad01808 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 compatibility info found
-# ERR1: tag1.o: 0x2A000000000000000{{1|2}}00000000000000
-# ERR1: tag2.o: 0x2A000000000000000{{1|2}}00000000000000
+# ERR1:      error: incompatible values of AArch64 PAuth compatibility info found
+# ERR1-NEXT: >>> tag1.o: 0x2A000000000000000{{1|2}}00000000000000
+# ERR1-NEXT: >>> tag2.o: 0x2A000000000000000{{1|2}}00000000000000
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o
 # RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s
@@ -34,10 +34,10 @@
 # RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s
 # RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null
 
-# ERR4:      error: noinfo1.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it
-# ERR4-NEXT: error: noinfo2.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it
-# WARN:      warning: noinfo1.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it
-# WARN-NEXT: warning: noinfo2.o has no AArch64 PAuth compatibility info while tag1.o has one; either all or no input files must have it
+# ERR4:      error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
+# ERR4-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
+# WARN:      warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
+# WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
 
 #--- abi-tag-short.s
 
@@ -79,8 +79,7 @@
 
 #--- no-info.s
 
-.globl _start;   // define _start to avoid missing entry warning and use --fatal-warnings to assert no diagnostic
-.weak _start;    // allow multiple definitions of _start for simplicity
+## define _start to avoid missing entry warning and use --fatal-warnings to assert no diagnostic
+## allow multiple definitions of _start for simplicity
+.weak _start;
 _start:
-
-.section ".test", "a"

>From 203f61e5cc831f27fef8dde654972f0dfe7d47a0 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 28 Feb 2024 20:58:19 +0300
Subject: [PATCH 17/23] Use `relocs` instead of `relocsVec` inside
 `lock(relocMutex)` scope

---
 lld/ELF/Relocations.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index cac385b6f9fcc9..040771789959b9 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1160,8 +1160,7 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
           // relative relocation section. The R_AARCH64_AUTH_RELATIVE has a
           // smaller addend field as bits [63:32] encode the signing-schema.
           sec->addReloc({expr, type, offset, addend, &sym});
-          part.relrAuthDyn->relocsVec[parallel::getThreadIndex()].push_back(
-              {sec, offset});
+          part.relrAuthDyn->relocs.push_back({sec, offset});
         } else {
           part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
                                   DynamicReloc::AddendOnlyWithTargetVA, sym,

>From 1b8c52b2b0a0cc87e63dc3ecfb0853aa279d9b8a Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 28 Feb 2024 21:05:57 +0300
Subject: [PATCH 18/23] Allow arbitrary offset for dynamic section: no need to
 rely on it in tests

---
 lld/test/ELF/aarch64-reloc-pauth.s | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 2c617f2899e65e..2a7c2c179fd51c 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -41,7 +41,7 @@
 # RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al
 # RELR:      .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8
 
-# RELR:      Dynamic section at offset 0x310 contains 16 entries
+# RELR:      Dynamic section at offset {{.*}} contains 16 entries
 # RELR:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]]
 # RELR-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes)
 # RELR-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)

>From e9b53374522fca221414aac3d5a3b225e7fc73d4 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 28 Feb 2024 22:17:29 +0300
Subject: [PATCH 19/23] Fix relocs with wide addends for non-preemptible
 symbols

For packed AUTH relocs in .relr.auth.dyn section, the implicit value
must fit 32 bits since other 32 bits are used for storing signing
schema. During relocation scanning, we do not know the final layout and
cannot comput the final VA.

In `Writer<ELFT>::finalizeAddressDependentContent()`, we adjust the
layout-dependent content and convert relr relocs with implicit values
wider than 32 bits to regular rela relocs.

Since .rela.dyn might be empty before this and non-empty after, we
should skip it in `removeUnusedSyntheticSections`. It might result in an
empty .rela.dyn section in the output. Similarly, an empty .relr.auth.dyn
might also appear - see lld/test/ELF/aarch64-reloc-pauth.s for details
and comments.
---
 lld/ELF/Arch/AArch64.cpp           |  18 ++-
 lld/ELF/Relocations.cpp            |  12 +-
 lld/ELF/SyntheticSections.h        |   4 +-
 lld/ELF/Writer.cpp                 |  39 ++++-
 lld/test/ELF/aarch64-reloc-pauth.s | 244 ++++++++++++++++++++---------
 5 files changed, 236 insertions(+), 81 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 909fbdacdb3036..d2134493fd71c2 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -401,8 +401,22 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
     write64(loc, val);
     break;
   case R_AARCH64_AUTH_ABS64:
-    assert(isInt<32>(val));
-    write32(loc, val);
+    // - If val is wider than 32 bits, we must have converted the auth relr
+    //   reloc to rela in Writer<ELFT>::finalizeAddressDependentContent(). If
+    //   so, no need to write anything, the rela entry holds all the info.
+    //
+    // - If val fits 32 bits:
+    //
+    //   - The relocation might still be rela instead of relr, for example, if
+    //     the relr -> rela conversion was performed during an iteration in
+    //     finalizeAddressDependentContent, but further iterations made the val
+    //     fitting 32 bits. In such case, there is no trouble with writing the
+    //     val since it will be treated as garbage and have no effect during
+    //     dynamic linking.
+    //
+    //   - If the relocation is actually relr, write the 32-bit val as expected.
+    if (isInt<32>(val))
+      write32(loc, val);
     break;
   case R_AARCH64_ADD_ABS_LO12_NC:
     or32AArch64Imm(loc, val);
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 040771789959b9..c6f702dbabaca7 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -898,9 +898,9 @@ static void addRelativeReloc(InputSectionBase &isec, uint64_t offsetInSec,
     isec.addReloc({expr, type, offsetInSec, addend, &sym});
     if (shard)
       part.relrDyn->relocsVec[parallel::getThreadIndex()].push_back(
-          {&isec, offsetInSec});
+          {&isec, &isec.relocs().back()});
     else
-      part.relrDyn->relocs.push_back({&isec, offsetInSec});
+      part.relrDyn->relocs.push_back({&isec, &isec.relocs().back()});
     return;
   }
   part.relaDyn->addRelativeReloc<shard>(target->relativeRel, isec, offsetInSec,
@@ -1158,9 +1158,13 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
                    isInt<32>(sym.getVA(addend))) {
           // Implicit addend is below 32-bits so we can use the compressed
           // relative relocation section. The R_AARCH64_AUTH_RELATIVE has a
-          // smaller addend field as bits [63:32] encode the signing-schema.
+          // smaller addend field as bits [63:32] encode the signing schema.
+          // The final VA might differ from the one calculated now since it
+          // might depend on the final layout. If the final VA does not fit 32
+          // bits, the packed AUTH reloc will be converted to rela in
+          // Writer<ELFT>::finalizeAddressDependentContent().
           sec->addReloc({expr, type, offset, addend, &sym});
-          part.relrAuthDyn->relocs.push_back({sec, offset});
+          part.relrAuthDyn->relocs.push_back({sec, &sec->relocs().back()});
         } else {
           part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
                                   DynamicReloc::AddendOnlyWithTargetVA, sym,
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index c36f08e26c2a7b..6b35178c0c21d8 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -603,10 +603,10 @@ class AndroidPackedRelocationSection final : public RelocationBaseSection {
 };
 
 struct RelativeReloc {
-  uint64_t getOffset() const { return inputSec->getVA(offsetInSec); }
+  uint64_t getOffset() const { return inputSec->getVA(reloc->offset); }
 
   const InputSectionBase *inputSec;
-  uint64_t offsetInSec;
+  Relocation *reloc;
 };
 
 class RelrBaseSection : public SyntheticSection {
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 5c8195e6448d70..c29ec4c11ce97c 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1742,6 +1742,29 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
       in.mipsGot->updateAllocSize();
 
     for (Partition &part : partitions) {
+      // We've put relocations in relrAuthDyn during
+      // RelocationScanner::processAux, but the target VA for some of them might
+      // be wider than 32 bits which does not fit the place for implicit value
+      // of relr AUTH reloc. We can only know the final VA at this point, so
+      // move relocations with large values from relr to rela.
+      if (part.relrAuthDyn) {
+        for (auto it = part.relrAuthDyn->relocs.begin();
+             it != part.relrAuthDyn->relocs.end();) {
+          if (isInt<32>(it->reloc->sym->getVA(it->reloc->addend))) {
+            ++it;
+            continue;
+          }
+          part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, it->inputSec,
+                                  it->reloc->offset,
+                                  DynamicReloc::AddendOnlyWithTargetVA,
+                                  *it->reloc->sym, it->reloc->addend, R_ABS});
+          part.relrAuthDyn->relocs.erase(it);
+          // We keep the relocation in the it->inputSec->relocations so pointers
+          // to them in part.relrAuthDyn->relocs items remain valid. See
+          // corresponding comment AArch64::relocate for details.
+          changed = true;
+        }
+      }
       changed |= part.relaDyn->updateAllocSize();
       if (part.relrDyn)
         changed |= part.relrDyn->updateAllocSize();
@@ -1881,7 +1904,7 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
 // To deal with the above problem, this function is called after
 // scanRelocations is called to remove synthetic sections that turn
 // out to be empty.
-static void removeUnusedSyntheticSections() {
+template <class ELFT> static void removeUnusedSyntheticSections() {
   // All input synthetic sections that can be empty are placed after
   // all regular ones. Reverse iterate to find the first synthetic section
   // after a non-synthetic one which will be our starting point.
@@ -1897,6 +1920,18 @@ static void removeUnusedSyntheticSections() {
         auto *sec = cast<SyntheticSection>(s);
         if (sec->getParent() && sec->isNeeded())
           return false;
+        // Packed AArch64 AUTH relocs might be moved from .relr.auth.dyn to
+        // .rela.dyn further in finalizeAddressDependentContent(). It is called
+        // later since removing unused synthetic sections changes the final
+        // layout. So, .rela.dyn should be kept now in such a case even if it's
+        // currently empty. A possible side effect is having empty
+        // .relr.auth.dyn (if all the packed AUTH relocs were moved to
+        // .rela.dyn) or empty .rela.dyn (if no rela relocs were there and no
+        // packed AUTH relocs were moved to it) in the output binary.
+        if (config->emachine == EM_AARCH64 && config->relrPackDynRelocs)
+          if (auto *relSec = dyn_cast<RelocationSection<ELFT>>(sec))
+            if (relSec->name == ".rela.dyn")
+              return false;
         unused.insert(sec);
         return true;
       });
@@ -2102,7 +2137,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   if (in.mipsGot)
     in.mipsGot->build();
 
-  removeUnusedSyntheticSections();
+  removeUnusedSyntheticSections<ELFT>();
   script->diagnoseOrphanHandling();
   script->diagnoseMissingSGSectionAddress();
 
diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 2a7c2c179fd51c..370600384e0676 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -1,126 +1,228 @@
 # REQUIRES: aarch64
 
-# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o %t.so.o
-# RUN: ld.lld -shared %t.so.o -soname=so -o %t.so
-# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: rm -rf %t && split-file %s %t && cd %t
 
-# RUN: ld.lld -pie %t.o %t.so -o %t
-# RUN: llvm-readobj -r %t | FileCheck --check-prefix=UNPACKED %s
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o main.so.o
+# RUN: ld.lld -shared main.so.o -soname=so -o main.so
+# RUN: llvm-mc -filetype=obj -triple=aarch64 main.s -o main.o
+
+# RUN: ld.lld -pie main.o main.so -o main
+# RUN: llvm-readobj -r main | FileCheck --check-prefix=UNPACKED %s
 
 # UNPACKED:          Section ({{.+}}) .rela.dyn {
-# UNPACKED-NEXT:       0x30440 R_AARCH64_AUTH_RELATIVE - 0x1
-# UNPACKED-NEXT:       0x30448 R_AARCH64_AUTH_RELATIVE - 0x2
-# UNPACKED-NEXT:       0x30450 R_AARCH64_AUTH_RELATIVE - 0x3
-# UNPACKED-NEXT:       0x30458 R_AARCH64_AUTH_RELATIVE - 0x12345678
-# UNPACKED-NEXT:       0x30460 R_AARCH64_AUTH_RELATIVE - 0x123456789A
-# UNPACKED-NEXT:       0x30479 R_AARCH64_AUTH_RELATIVE - 0x4
-# UNPACKED-NEXT:       0x30482 R_AARCH64_AUTH_RELATIVE - 0x5
-# UNPACKED-NEXT:       0x30468 R_AARCH64_AUTH_ABS64 zed2 0x0
-# UNPACKED-NEXT:       0x30470 R_AARCH64_AUTH_ABS64 bar2 0x0
+# UNPACKED-NEXT:       0x30470 R_AARCH64_AUTH_RELATIVE - 0x1
+# UNPACKED-NEXT:       0x30478 R_AARCH64_AUTH_RELATIVE - 0x30472
+# UNPACKED-NEXT:       0x30480 R_AARCH64_AUTH_RELATIVE - 0xFFFFFFFFFFFFFFFD
+# UNPACKED-NEXT:       0x30488 R_AARCH64_AUTH_RELATIVE - 0x12345678
+# UNPACKED-NEXT:       0x30490 R_AARCH64_AUTH_RELATIVE - 0x123456789A
+# UNPACKED-NEXT:       0x30498 R_AARCH64_AUTH_RELATIVE - 0xFFFFFFEDCBA98766
+# UNPACKED-NEXT:       0x304A0 R_AARCH64_AUTH_RELATIVE - 0x8003046F
+# UNPACKED-NEXT:       0x304B9 R_AARCH64_AUTH_RELATIVE - 0x4
+# UNPACKED-NEXT:       0x304C2 R_AARCH64_AUTH_RELATIVE - 0x30475
+# UNPACKED-NEXT:       0x304A8 R_AARCH64_AUTH_ABS64 zed2 0x1111
+# UNPACKED-NEXT:       0x304B0 R_AARCH64_AUTH_ABS64 bar2 0x0
 # UNPACKED-NEXT:     }
 
-# RUN: ld.lld %t.o %t.so -o %t.nopie
-# RUN: llvm-readobj -r %t.nopie | FileCheck --check-prefix=NOPIE %s
+# RUN: ld.lld main.o main.so -o main.nopie
+# RUN: llvm-readobj -r main.nopie | FileCheck --check-prefix=NOPIE %s
 
 # NOPIE:      Section ({{.+}}) .rela.dyn {
-# NOPIE:        0x230430 R_AARCH64_AUTH_RELATIVE - 0x200001
-# NOPIE-NEXT:   0x230438 R_AARCH64_AUTH_RELATIVE - 0x200002
-# NOPIE-NEXT:   0x230440 R_AARCH64_AUTH_RELATIVE - 0x200003
-# NOPIE-NEXT:   0x230448 R_AARCH64_AUTH_RELATIVE - 0x12545678
-# NOPIE-NEXT:   0x230450 R_AARCH64_AUTH_RELATIVE - 0x123476789A
-# NOPIE-NEXT:   0x230469 R_AARCH64_AUTH_RELATIVE - 0x200004
-# NOPIE-NEXT:   0x230472 R_AARCH64_AUTH_RELATIVE - 0x200005
-# NOPIE-NEXT:   0x230458 R_AARCH64_AUTH_ABS64 zed2 0x0
-# NOPIE-NEXT:   0x230460 R_AARCH64_AUTH_ABS64 bar2 0x0
+# NOPIE:        0x230460 R_AARCH64_AUTH_RELATIVE - 0x200001
+# NOPIE-NEXT:   0x230468 R_AARCH64_AUTH_RELATIVE - 0x230462
+# NOPIE-NEXT:   0x230470 R_AARCH64_AUTH_RELATIVE - 0x1FFFFD
+# NOPIE-NEXT:   0x230478 R_AARCH64_AUTH_RELATIVE - 0x12545678
+# NOPIE-NEXT:   0x230480 R_AARCH64_AUTH_RELATIVE - 0x123476789A
+# NOPIE-NEXT:   0x230488 R_AARCH64_AUTH_RELATIVE - 0xFFFFFFEDCBC98766
+# NOPIE-NEXT:   0x230490 R_AARCH64_AUTH_RELATIVE - 0x8023045F
+# NOPIE-NEXT:   0x2304A9 R_AARCH64_AUTH_RELATIVE - 0x200004
+# NOPIE-NEXT:   0x2304B2 R_AARCH64_AUTH_RELATIVE - 0x230465
+# NOPIE-NEXT:   0x230498 R_AARCH64_AUTH_ABS64 zed2 0x1111
+# NOPIE-NEXT:   0x2304A0 R_AARCH64_AUTH_ABS64 bar2 0x0
 # NOPIE-NEXT: }
 
-# RUN: ld.lld -pie -z pack-relative-relocs %t.o %t.so -o %t2
-# RUN: llvm-readelf -S -d -r -x .test %t2 | FileCheck --check-prefixes=RELR,HEX %s
+# RUN: ld.lld -pie -z pack-relative-relocs main.o main.so -o main.pie
+# RUN: llvm-readelf -S -d -r -x .test main.pie | FileCheck --check-prefixes=RELR,HEX %s
 
 # RELR:      Section Headers:
 # RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al
-# RELR:      .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR:.*]] {{0*}}[[ADDR]] 000018 08 A 0 0 8
+# RELR:      .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000090 18 A 1 0 8
+# RELR:      .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000018 08 A 0 0 8
 
 # RELR:      Dynamic section at offset {{.*}} contains 16 entries
-# RELR:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR]]
+# RELR:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR2]]
 # RELR-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes)
 # RELR-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)
 
 ## Decoded SHT_RELR section is same as UNPACKED,
 ## but contains only the relative relocations.
-## Any relative relocations with odd offset stay in SHT_RELA.
+## Any relative relocations with odd offset or value wider than 32 bits stay in SHT_RELA.
 
-# RELR:      Relocation section '.rela.dyn' at offset {{.*}} contains 4 entries:
+# RELR:      Relocation section '.rela.dyn' at offset 0x[[ADDR1]] contains 6 entries:
 # RELR-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
-# RELR-NEXT: 0000000000030430  0000000000000411 R_AARCH64_AUTH_RELATIVE           123456789a
-# RELR-NEXT: 0000000000030449  0000000000000411 R_AARCH64_AUTH_RELATIVE           4
-# RELR-NEXT: 0000000000030438  0000000100000244 R_AARCH64_AUTH_ABS64   0000000000000000 zed2 + 0
-# RELR-NEXT: 0000000000030440  0000000200000244 R_AARCH64_AUTH_ABS64   0000000000000000 bar2 + 0
+# RELR-NEXT: 0000000000030460  0000000000000411 R_AARCH64_AUTH_RELATIVE           123456789a
+# RELR-NEXT: 0000000000030468  0000000000000411 R_AARCH64_AUTH_RELATIVE           ffffffedcba98766
+# RELR-NEXT: 0000000000030470  0000000000000411 R_AARCH64_AUTH_RELATIVE           8003043f
+# RELR-NEXT: 0000000000030489  0000000000000411 R_AARCH64_AUTH_RELATIVE           4
+# RELR-NEXT: 0000000000030478  0000000100000244 R_AARCH64_AUTH_ABS64   0000000000000000 zed2 + 1111
+# RELR-NEXT: 0000000000030480  0000000200000244 R_AARCH64_AUTH_ABS64   0000000000000000 bar2 + 0
 # RELR-EMPTY:
-# RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 5 entries:
+# RELR-NEXT: Relocation section '.relr.auth.dyn' at offset 0x[[ADDR2]] contains 5 entries:
 # RELR-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name
-# RELR-NEXT: 0000000000030410  0000000000000403 R_AARCH64_RELATIVE
-# RELR-NEXT: 0000000000030418  0000000000000403 R_AARCH64_RELATIVE
-# RELR-NEXT: 0000000000030420  0000000000000403 R_AARCH64_RELATIVE
-# RELR-NEXT: 0000000000030428  0000000000000403 R_AARCH64_RELATIVE
-# RELR-NEXT: 0000000000030452  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030440  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030448  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030450  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030458  0000000000000403 R_AARCH64_RELATIVE
+# RELR-NEXT: 0000000000030492  0000000000000403 R_AARCH64_RELATIVE
 
-# RUN: llvm-readobj -r --raw-relr %t2 | FileCheck --check-prefix=RAW-RELR %s
+# RUN: llvm-readobj -r --raw-relr main.pie | \
+# RUN:   FileCheck --match-full-lines --check-prefix=RAW-RELR %s
 
 ## SHT_RELR section contains address/bitmap entries
 ## encoding the offsets for relative relocation.
 
-# RAW-RELR:           Section ({{.+}}) .relr.auth.dyn {
-# RAW-RELR-NEXT:      0x30410
-# RAW-RELR-NEXT:      0xF
-# RAW-RELR-NEXT:      0x30452
-# RAW-RELR-NEXT:      }
+# RAW-RELR:          Section ({{.+}}) .relr.auth.dyn {
+# RAW-RELR-NEXT:     0x30440
+# RAW-RELR-NEXT:     0xF
+## 0xF = 0b111100..00
+##        lsb    hsb
+## Bits 1..3 are set, we have relocs at 0x30440 and the next 3 places: 0x30448, 0x3450, 0x30458
+# RAW-RELR-NEXT:     0x30492
+## A single reloc at ^^^^^^^
+# RAW-RELR-NEXT:     }
 
 # HEX:      Hex dump of section '.test':
-# HEX-NEXT: 0x00030410 01000000 2a000020 02000000 2b000000
-##                     ^^^^^^^^ Addend = 1
+# HEX-NEXT: 0x00030440 01000000 2a000020 42040300 2b000000
+##                     ^^^^^^^^ Implicit val = 1 = __ehdr_start + 1
 ##                              ^^^^ Discr = 42
 ##                                    ^^ Key (bits 5..6) = DA
-##                                       ^^^^^^^^ Addend = 2
+##                                       ^^^^^^^^ Implicit val = 0x30442 = 0x30440 + 2 = .test + 2
 ##                                                ^^^^ Discr = 43
 ##                                                      ^^ Key (bits 5..6) = IA
-# HEX-NEXT: 0x00030420 03000000 2c000080 78563412 2d000020
-##                     ^^^^^^^^ Addend = 3
+# HEX-NEXT: 0x00030450 fdffffff 2c000080 78563412 2d000020
+##                     ^^^^^^^^ Implicit val = -3 = __ehdr_start - 3
 ##                              ^^^^ Discr = 44
 ##                                    ^^ Key (bits 5..6) = IA
 ##                                    ^^ Addr diversity (bit 7) = true
-##                                       ^^^^^^^^ Addend = 0x12345678
+##                                       ^^^^^^^^ Implicit val = 0x12345678 = __ehdr_start + 0x12345678
 ##                                                ^^^^ Discr = 45
 ##                                                      ^^ Key (bits 5..6) = DA
-# HEX-NEXT: 0x00030430 00000000 2e000020 00000000 2f000020
-##                     ^^^^^^^^ No implicit addend (rela reloc)
+# HEX-NEXT: 0x00030460 00000000 2e000020 00000000 2f000020
+##                     ^^^^^^^^ No implicit val (rela reloc due val wider than 32 bits)
 ##                              ^^^^ Discr = 46
 ##                                    ^^ Key (bits 5..6) = DA
-##                                       ^^^^^^^^ Addend = 0
+##                                       ^^^^^^^^ No implicit val (rela reloc due to val wider than 32 bits)
 ##                                                ^^^^ Discr = 47
 ##                                                      ^^ Key (bits 5..6) = DA
-# HEX-NEXT: 0x00030440 00000000 30000000 00000000 00310000
-##                     ^^^^^^^^ Addend = 0
+# HEX-NEXT: 0x00030470 00000000 30000020 00000000 31000020
+##                     ^^^^^^^^ No implicit val (rela reloc due val wider than 32 bits)
 ##                              ^^^^ Discr = 48
+##                                    ^^ Key (bits 5..6) = DA
+##                                       ^^^^^^^^ No implicit val (rela reloc due to a preemptible symbol)
+##                                                ^^^^ Discr = 49
+##                                                      ^^ Key (bits 5..6) = DA
+# HEX-NEXT: 0x00030480 00000000 32000000 77000000 00330000
+##                     ^^^^^^^^ No implicit val (rela reloc due to a preemptible symbol)
+##                              ^^^^ Discr = 50
 ##                                    ^^ Key (bits 5..6) = IA
-##                                         ^^^^^^ ^^ No implicit addend (rela reloc)
-##                                                  ^^^^ Discr = 49
-# HEX-NEXT: 0x00030450 20000500 00003200 0020{{\ }}
+##                                         ^^^^^^ ^^ No implicit val (rela reloc due to odd offset)
+##                                                  ^^^^ Discr = 51
+# HEX-NEXT: 0x00030490 20774504 03003400 0020{{\ }}
 ##                     ^^ Key (bits 5..6) = DA
-##                         ^^^^ ^^^^ Addend = 5
-##                                  ^^^^ Discr = 48
+##                         ^^^^ ^^^^ Implicit val = 0x30445 = 0x30440 + 5 = .test + 5
+##                                  ^^^^ Discr = 52
 ##                                         ^^ Key (bits 5..6) = DA
 
+#--- main.s
+
 .section .test, "aw"
 .p2align 3
 .quad (__ehdr_start + 1)@AUTH(da,42)
-.quad (__ehdr_start + 2)@AUTH(ia,43)
-.quad (__ehdr_start + 3)@AUTH(ia,44,addr)
+.quad (.test + 2)@AUTH(ia,43)
+.quad (__ehdr_start - 3)@AUTH(ia,44,addr)
 .quad (__ehdr_start + 0x12345678)@AUTH(da,45)
+## Addend wider than 32 bits, not enough room for storing implicitly, would go to rela
 .quad (__ehdr_start + 0x123456789A)@AUTH(da,46)
-.quad zed2 at AUTH(da,47)
-.quad bar2 at AUTH(ia,48)
-.byte 00
-.quad (__ehdr_start + 4)@AUTH(da,49)
-.byte 00
-.quad (__ehdr_start + 5)@AUTH(da,50)
+## Negative addend wider than 32 bits, not enough room for storing implicitly, would go to rela
+.quad (__ehdr_start - 0x123456789A)@AUTH(da,47)
+## INT32_MAX plus non-zero .test is wider than 32 bits, not enough room for storing implicitly, would go to rela
+.quad (.test + 0x7FFFFFFF)@AUTH(da,48)
+.quad (zed2 + 0x1111)@AUTH(da,49)
+.quad bar2 at AUTH(ia,50)
+.byte 0x77
+.quad (__ehdr_start + 4)@AUTH(da,51)
+.byte 0x77
+.quad (.test + 5)@AUTH(da,52)
+
+#--- empty-relr.s
+
+## During relocation scanning, we might put some AUTH relocs into the packed
+## relocation section when not knowing the final implicit value to be stored in
+## the place to be relocated. If the value turns out to be wider than 32 bits
+## after computing the final layout, we convert the relocation from relr to
+## rela. A side effect is having an empty .relr.auth.dyn section if all the
+## packed relocations were converted to rela.
+## TODO: avoid empty .relr.auth.dyn in the output binary
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 empty-relr.s -o empty-relr.o
+# RUN: ld.lld -pie -z pack-relative-relocs empty-relr.o -o empty-relr
+# RUN: llvm-readelf -S -d -r empty-relr | FileCheck --check-prefixes=EMPTY-RELR %s
+
+# EMPTY-RELR:      Section Headers:
+# EMPTY-RELR-NEXT: Name Type Address Off Size ES Flg Lk Inf Al
+# EMPTY-RELR:      .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000018 18 A 0 0 8
+# EMPTY-RELR:      .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000000 08 A 0 0 8
+
+# EMPTY-RELR:      Dynamic section at offset {{.*}} contains 12 entries
+# EMPTY-RELR-NOT:  (AARCH64_AUTH_RELR)
+# EMPTY-RELR-NOT:  (AARCH64_AUTH_RELRSZ)
+# EMPTY-RELR-NOT:  (AARCH64_AUTH_RELRENT)
+# EMPTY-RELR:      0x0000000000000007 (RELA) 0x[[ADDR1]]
+# EMPTY-RELR-NEXT: 0x0000000000000008 (RELASZ) 24 (bytes)
+# EMPTY-RELR-NEXT: 0x0000000000000009 (RELAENT) 24 (bytes)
+
+# EMPTY-RELR:      Relocation section '.rela.dyn' at offset {{.*}} contains 1 entries:
+# EMPTY-RELR-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
+# EMPTY-RELR-NEXT: 0000000000030320  0000000000000411 R_AARCH64_AUTH_RELATIVE           8003031f
+# EMPTY-RELR-EMPTY:
+# EMPTY-RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 0 entries:
+# EMPTY-RELR-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name
+
+.section .test, "aw"
+.p2align 3
+.quad (.test + 0x7FFFFFFF)@AUTH(da,42)
+
+#--- empty-rela.s
+
+## (See comment in empty-relr.s for context)
+## If all the packed relocation remain in .relr.auth.dyn and none of them is
+## converted to rela while there were no other rela relocs in .rela.dyn, the
+## latter would be empty in the output binary.
+## TODO: avoid empty .rela.dyn in the output binary
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 empty-rela.s -o empty-rela.o
+# RUN: ld.lld -pie -z pack-relative-relocs empty-rela.o -o empty-rela
+# RUN: llvm-readelf -S -d -r empty-rela | FileCheck --check-prefixes=EMPTY-RELA %s
+
+# EMPTY-RELA:      Section Headers:
+# EMPTY-RELA-NEXT: Name Type Address Off Size ES Flg Lk Inf Al
+# EMPTY-RELA:      .rela.dyn RELA {{0*}}[[ADDR1:.*]] {{0*}}[[ADDR1]] 000000 18 A 0 0 8
+# EMPTY-RELA:      .relr.auth.dyn AARCH64_AUTH_RELR {{0*}}[[ADDR2:.*]] {{0*}}[[ADDR2]] 000008 08 A 0 0 8
+
+# EMPTY-RELA:      Dynamic section at offset {{.*}} contains 12 entries
+# EMPTY-RELA-NOT:  (RELR)
+# EMPTY-RELA-NOT:  (RELRSZ)
+# EMPTY-RELA-NOT:  (RELRENT)
+# EMPTY-RELA:      0x0000000070000012 (AARCH64_AUTH_RELR) 0x[[ADDR2]]
+# EMPTY-RELA-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 8 (bytes)
+# EMPTY-RELA-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)
+
+# EMPTY-RELA:      Relocation section '.rela.dyn' at offset {{.*}} contains 0 entries:
+# EMPTY-RELA-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name
+# EMPTY-RELA-EMPTY:
+# EMPTY-RELA-NEXT: Relocation section '.relr.auth.dyn' at offset {{.*}} contains 1 entries:
+# EMPTY-RELA-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name
+# EMPTY-RELA-NEXT: 0000000000030310  0000000000000403 R_AARCH64_RELATIVE
+
+.section .test, "aw"
+.p2align 3
+.quad (.test + 0x12345678)@AUTH(da,42)

>From b215b0d60ac0c2ac29aeb318da7c95725be6ef86 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Fri, 8 Mar 2024 13:47:04 +0300
Subject: [PATCH 20/23] Address review comments

---
 lld/ELF/Driver.cpp                   | 14 +++++----
 lld/ELF/Relocations.cpp              | 19 +++++-------
 lld/ELF/SyntheticSections.h          |  6 ++--
 lld/ELF/Writer.cpp                   | 43 ++++++++++++++--------------
 lld/test/ELF/aarch64-feature-pauth.s |  4 +--
 5 files changed, 42 insertions(+), 44 deletions(-)

diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 860c85a5782e65..a365a3585c9da2 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -46,6 +46,7 @@
 #include "lld/Common/Strings.h"
 #include "lld/Common/TargetOptionsCommandFlags.h"
 #include "lld/Common/Version.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -65,7 +66,6 @@
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/raw_ostream.h"
-#include <algorithm>
 #include <cstdlib>
 #include <tuple>
 #include <utility>
@@ -2590,9 +2590,9 @@ static void readSecurityNotes() {
 
   StringRef referenceFileName;
   if (config->emachine == EM_AARCH64) {
-    auto it = std::find_if(
-        ctx.objectFiles.begin(), ctx.objectFiles.end(),
-        [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag.empty(); });
+    auto it = llvm::find_if(ctx.objectFiles, [](const ELFFileBase *f) {
+      return !f->aarch64PauthAbiTag.empty();
+    });
     if (it != ctx.objectFiles.end()) {
       ctx.aarch64PauthAbiTag = (*it)->aarch64PauthAbiTag;
       referenceFileName = (*it)->getName();
@@ -2652,8 +2652,10 @@ static void readSecurityNotes() {
       errorOrWarn(
           "incompatible values of AArch64 PAuth compatibility info found"
           "\n>>> " +
-          referenceFileName + ": 0x" + toHex(ctx.aarch64PauthAbiTag) +
-          "\n>>> " + toString(f) + ": 0x" + toHex(f->aarch64PauthAbiTag));
+          referenceFileName + ": 0x" +
+          toHex(ctx.aarch64PauthAbiTag, /*LowerCase=*/true) + "\n>>> " +
+          toString(f) + ": 0x" +
+          toHex(f->aarch64PauthAbiTag, /*LowerCase=*/true));
   }
 
   // Force enable Shadow Stack.
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index c6f702dbabaca7..eca232526ee1b7 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -898,9 +898,9 @@ static void addRelativeReloc(InputSectionBase &isec, uint64_t offsetInSec,
     isec.addReloc({expr, type, offsetInSec, addend, &sym});
     if (shard)
       part.relrDyn->relocsVec[parallel::getThreadIndex()].push_back(
-          {&isec, &isec.relocs().back()});
+          {&isec, isec.relocs().size() - 1});
     else
-      part.relrDyn->relocs.push_back({&isec, &isec.relocs().back()});
+      part.relrDyn->relocs.push_back({&isec, isec.relocs().size() - 1});
     return;
   }
   part.relaDyn->addRelativeReloc<shard>(target->relativeRel, isec, offsetInSec,
@@ -1154,17 +1154,12 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
         // relative relocation. Use a symbolic relocation instead.
         if (sym.isPreemptible) {
           part.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
-        } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
-                   isInt<32>(sym.getVA(addend))) {
-          // Implicit addend is below 32-bits so we can use the compressed
-          // relative relocation section. The R_AARCH64_AUTH_RELATIVE has a
-          // smaller addend field as bits [63:32] encode the signing schema.
-          // The final VA might differ from the one calculated now since it
-          // might depend on the final layout. If the final VA does not fit 32
-          // bits, the packed AUTH reloc will be converted to rela in
-          // Writer<ELFT>::finalizeAddressDependentContent().
+        } else if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0) {
+          // When symbol values are determined in
+          // finalizeAddressDependentContent, some relrAuthDyn relocations may
+          // be moved to relaDyn.
           sec->addReloc({expr, type, offset, addend, &sym});
-          part.relrAuthDyn->relocs.push_back({sec, &sec->relocs().back()});
+          part.relrAuthDyn->relocs.push_back({sec, sec->relocs().size() - 1});
         } else {
           part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
                                   DynamicReloc::AddendOnlyWithTargetVA, sym,
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 6b35178c0c21d8..6f13b331f1bd1e 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -603,10 +603,12 @@ class AndroidPackedRelocationSection final : public RelocationBaseSection {
 };
 
 struct RelativeReloc {
-  uint64_t getOffset() const { return inputSec->getVA(reloc->offset); }
+  uint64_t getOffset() const {
+    return inputSec->getVA(inputSec->relocs()[relocIdx].offset);
+  }
 
   const InputSectionBase *inputSec;
-  Relocation *reloc;
+  size_t relocIdx;
 };
 
 class RelrBaseSection : public SyntheticSection {
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index a724b1c3135d9b..faa441ce30d40c 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -24,6 +24,7 @@
 #include "lld/Common/CommonLinkerContext.h"
 #include "lld/Common/Filesystem.h"
 #include "lld/Common/Strings.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/BLAKE3.h"
 #include "llvm/Support/Parallel.h"
@@ -1755,28 +1756,26 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
       in.mipsGot->updateAllocSize();
 
     for (Partition &part : partitions) {
-      // We've put relocations in relrAuthDyn during
+      // The R_AARCH64_AUTH_RELATIVE has a smaller addend field as bits [63:32]
+      // encode the signing schema. We've put relocations in relrAuthDyn during
       // RelocationScanner::processAux, but the target VA for some of them might
-      // be wider than 32 bits which does not fit the place for implicit value
-      // of relr AUTH reloc. We can only know the final VA at this point, so
+      // be wider than 32 bits. We can only know the final VA at this point, so
       // move relocations with large values from relr to rela.
       if (part.relrAuthDyn) {
-        for (auto it = part.relrAuthDyn->relocs.begin();
-             it != part.relrAuthDyn->relocs.end();) {
-          if (isInt<32>(it->reloc->sym->getVA(it->reloc->addend))) {
-            ++it;
-            continue;
-          }
-          part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, it->inputSec,
-                                  it->reloc->offset,
-                                  DynamicReloc::AddendOnlyWithTargetVA,
-                                  *it->reloc->sym, it->reloc->addend, R_ABS});
-          part.relrAuthDyn->relocs.erase(it);
-          // We keep the relocation in the it->inputSec->relocations so pointers
-          // to them in part.relrAuthDyn->relocs items remain valid. See
-          // corresponding comment AArch64::relocate for details.
-          changed = true;
-        }
+        auto it = llvm::remove_if(
+            part.relrAuthDyn->relocs, [&part](const RelativeReloc &elem) {
+              const Relocation &reloc = elem.inputSec->relocs()[elem.relocIdx];
+              if (isInt<32>(reloc.sym->getVA(reloc.addend)))
+                return false;
+              part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, elem.inputSec,
+                                      reloc.offset,
+                                      DynamicReloc::AddendOnlyWithTargetVA,
+                                      *reloc.sym, reloc.addend, R_ABS});
+              // See also AArch64::relocate
+              return true;
+            });
+        changed |= (it != part.relrAuthDyn->relocs.end());
+        part.relrAuthDyn->relocs.erase(it, part.relrAuthDyn->relocs.end());
       }
       changed |= part.relaDyn->updateAllocSize();
       if (part.relrDyn)
@@ -1917,7 +1916,7 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
 // To deal with the above problem, this function is called after
 // scanRelocations is called to remove synthetic sections that turn
 // out to be empty.
-template <class ELFT> static void removeUnusedSyntheticSections() {
+static void removeUnusedSyntheticSections() {
   // All input synthetic sections that can be empty are placed after
   // all regular ones. Reverse iterate to find the first synthetic section
   // after a non-synthetic one which will be our starting point.
@@ -1942,7 +1941,7 @@ template <class ELFT> static void removeUnusedSyntheticSections() {
         // .rela.dyn) or empty .rela.dyn (if no rela relocs were there and no
         // packed AUTH relocs were moved to it) in the output binary.
         if (config->emachine == EM_AARCH64 && config->relrPackDynRelocs)
-          if (auto *relSec = dyn_cast<RelocationSection<ELFT>>(sec))
+          if (auto *relSec = dyn_cast<RelocationBaseSection>(sec))
             if (relSec->name == ".rela.dyn")
               return false;
         unused.insert(sec);
@@ -2151,7 +2150,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   if (in.mipsGot)
     in.mipsGot->build();
 
-  removeUnusedSyntheticSections<ELFT>();
+  removeUnusedSyntheticSections();
   script->diagnoseOrphanHandling();
   script->diagnoseMissingSGSectionAddress();
 
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index 25c43e6ad01808..44a74794822735 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -13,8 +13,8 @@
 # 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 compatibility info found
-# ERR1-NEXT: >>> tag1.o: 0x2A000000000000000{{1|2}}00000000000000
-# ERR1-NEXT: >>> tag2.o: 0x2A000000000000000{{1|2}}00000000000000
+# ERR1-NEXT: >>> tag1.o: 0x2a000000000000000{{1|2}}00000000000000
+# ERR1-NEXT: >>> tag2.o: 0x2a000000000000000{{1|2}}00000000000000
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o
 # RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s

>From d32b8e32fc1c938e5a005997b832d215a308037d Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 18 Mar 2024 12:59:20 +0300
Subject: [PATCH 21/23] Address some review comments

---
 lld/ELF/Arch/AArch64.cpp           | 21 ++++++++-------------
 lld/ELF/Writer.cpp                 | 14 +++++---------
 lld/test/ELF/aarch64-reloc-pauth.s | 30 ++++++++++++------------------
 3 files changed, 25 insertions(+), 40 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 16de7b738dbdde..a60f595f10aeee 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -401,20 +401,15 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
     write64(loc, val);
     break;
   case R_AARCH64_AUTH_ABS64:
-    // - If val is wider than 32 bits, we must have converted the auth relr
-    //   reloc to rela in Writer<ELFT>::finalizeAddressDependentContent(). If
-    //   so, no need to write anything, the rela entry holds all the info.
+    // If val is wider than 32 bits, the relocation must have been moved from
+    // .relr.auth.dyn to .rela.dyn, and the addend write is not needed.
     //
-    // - If val fits 32 bits:
-    //
-    //   - The relocation might still be rela instead of relr, for example, if
-    //     the relr -> rela conversion was performed during an iteration in
-    //     finalizeAddressDependentContent, but further iterations made the val
-    //     fitting 32 bits. In such case, there is no trouble with writing the
-    //     val since it will be treated as garbage and have no effect during
-    //     dynamic linking.
-    //
-    //   - If the relocation is actually relr, write the 32-bit val as expected.
+    // If val fits in 32 bits, we have two potential scenarios:
+    // * True RELR: Write the 32-bit `val`
+    // * RELA: Even if the value now fits in 32 bits, it might have been
+    //   converted from RELR during an iteration in
+    //   finalizeAddressDependentContent(). Writing the value is harmless
+    //   because dynamic linking ignores it.
     if (isInt<32>(val))
       write32(loc, val);
     break;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 5dbb806484f65a..ef51d6eb0fe1c5 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1935,17 +1935,13 @@ static void removeUnusedSyntheticSections() {
         auto *sec = cast<SyntheticSection>(s);
         if (sec->getParent() && sec->isNeeded())
           return false;
-        // Packed AArch64 AUTH relocs might be moved from .relr.auth.dyn to
-        // .rela.dyn further in finalizeAddressDependentContent(). It is called
-        // later since removing unused synthetic sections changes the final
-        // layout. So, .rela.dyn should be kept now in such a case even if it's
-        // currently empty. A possible side effect is having empty
-        // .relr.auth.dyn (if all the packed AUTH relocs were moved to
-        // .rela.dyn) or empty .rela.dyn (if no rela relocs were there and no
-        // packed AUTH relocs were moved to it) in the output binary.
+        // .relr.auth.dyn relocations may be moved to .rela.dyn in
+        // finalizeAddressDependentContent, making .rela.dyn no longer empty.
+        // Conservatively keep .rela.dyn. .relr.auth.dyn can be made empty, but
+        // we would fail to remove it here.
         if (config->emachine == EM_AARCH64 && config->relrPackDynRelocs)
           if (auto *relSec = dyn_cast<RelocationBaseSection>(sec))
-            if (relSec->name == ".rela.dyn")
+            if (relSec == mainPart->relaDyn.get())
               return false;
         unused.insert(sec);
         return true;
diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 370600384e0676..55e8803f3d5711 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -2,11 +2,11 @@
 
 # RUN: rm -rf %t && split-file %s %t && cd %t
 
-# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o main.so.o
-# RUN: ld.lld -shared main.so.o -soname=so -o main.so
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %p/Inputs/shared2.s -o a.o
+# RUN: ld.lld -shared a.o -soname=so -o a.so
 # RUN: llvm-mc -filetype=obj -triple=aarch64 main.s -o main.o
 
-# RUN: ld.lld -pie main.o main.so -o main
+# RUN: ld.lld -pie main.o a.so -o main
 # RUN: llvm-readobj -r main | FileCheck --check-prefix=UNPACKED %s
 
 # UNPACKED:          Section ({{.+}}) .rela.dyn {
@@ -23,7 +23,7 @@
 # UNPACKED-NEXT:       0x304B0 R_AARCH64_AUTH_ABS64 bar2 0x0
 # UNPACKED-NEXT:     }
 
-# RUN: ld.lld main.o main.so -o main.nopie
+# RUN: ld.lld main.o a.so -o main.nopie
 # RUN: llvm-readobj -r main.nopie | FileCheck --check-prefix=NOPIE %s
 
 # NOPIE:      Section ({{.+}}) .rela.dyn {
@@ -40,7 +40,7 @@
 # NOPIE-NEXT:   0x2304A0 R_AARCH64_AUTH_ABS64 bar2 0x0
 # NOPIE-NEXT: }
 
-# RUN: ld.lld -pie -z pack-relative-relocs main.o main.so -o main.pie
+# RUN: ld.lld -pie -z pack-relative-relocs main.o a.so -o main.pie
 # RUN: llvm-readelf -S -d -r -x .test main.pie | FileCheck --check-prefixes=RELR,HEX %s
 
 # RELR:      Section Headers:
@@ -84,7 +84,7 @@
 # RAW-RELR-NEXT:     0x30440
 # RAW-RELR-NEXT:     0xF
 ## 0xF = 0b111100..00
-##        lsb    hsb
+##         lsb    hsb
 ## Bits 1..3 are set, we have relocs at 0x30440 and the next 3 places: 0x30448, 0x3450, 0x30458
 # RAW-RELR-NEXT:     0x30492
 ## A single reloc at ^^^^^^^
@@ -155,13 +155,9 @@
 
 #--- empty-relr.s
 
-## During relocation scanning, we might put some AUTH relocs into the packed
-## relocation section when not knowing the final implicit value to be stored in
-## the place to be relocated. If the value turns out to be wider than 32 bits
-## after computing the final layout, we convert the relocation from relr to
-## rela. A side effect is having an empty .relr.auth.dyn section if all the
-## packed relocations were converted to rela.
-## TODO: avoid empty .relr.auth.dyn in the output binary
+## .relr.auth.dyn relocations that do not fit 32 bits are moved to .rela.dyn.
+## In this case .relr.auth.dyn will be made empty, but
+## removeUnusedSyntheticSections fails to remove the section.
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64 empty-relr.s -o empty-relr.o
 # RUN: ld.lld -pie -z pack-relative-relocs empty-relr.o -o empty-relr
@@ -193,11 +189,9 @@
 
 #--- empty-rela.s
 
-## (See comment in empty-relr.s for context)
-## If all the packed relocation remain in .relr.auth.dyn and none of them is
-## converted to rela while there were no other rela relocs in .rela.dyn, the
-## latter would be empty in the output binary.
-## TODO: avoid empty .rela.dyn in the output binary
+## .relr.auth.dyn relocations that do not fit 32 bits are moved to .rela.dyn.
+## If this scenario does not happen, .rela.dyn will remain empty,
+## but removeUnusedSyntheticSections fails to remove the section.
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64 empty-rela.s -o empty-rela.o
 # RUN: ld.lld -pie -z pack-relative-relocs empty-rela.o -o empty-rela

>From 978ed06259a3b6ea035dde2c07581f62c45cfd4a Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 18 Mar 2024 17:36:26 +0300
Subject: [PATCH 22/23] Use `.note.gnu.property` instead of
 `.note.AARCH64-PAUTH-ABI-tag`

---
 lld/ELF/InputFiles.cpp               | 85 +++++++------------------
 lld/ELF/SyntheticSections.cpp        | 58 ++++++++---------
 lld/ELF/SyntheticSections.h          | 11 ----
 lld/ELF/Writer.cpp                   |  7 +-
 lld/test/ELF/aarch64-feature-pauth.s | 95 ++++++++++++++++++----------
 5 files changed, 114 insertions(+), 142 deletions(-)

diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index e0639f8528ba3e..89dc1afa5e9533 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -914,25 +914,18 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
     handleSectionGroup<ELFT>(this->sections, entries);
 }
 
-// If a source file is compiled with x86 hardware-assisted call flow control
-// enabled, the generated object file contains feature flags indicating that
-// fact. This function reads the feature flags and returns it.
-//
-// Essentially we want to read a single 32-bit value in this function, but this
-// function is rather complicated because the value is buried deep inside a
-// .note.gnu.property section.
-//
-// The section consists of one or more NOTE records. Each NOTE record consists
-// of zero or more type-length-value fields. We want to find a field of a
-// certain type. It seems a bit too much to just store a 32-bit value, perhaps
-// the ABI is unnecessarily complicated.
-template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
+// Read the following info from the .note.gnu.property section and write it to
+// the corresponding fields in `ObjFile`:
+// - Feature flags (32 bits) representing x86 or AArch64 features for
+//   hardware-assisted call flow control;
+// - AArch64 PAuth ABI compatibility info (16 bytes).
+template <class ELFT>
+void readGnuProperty(const InputSection &sec, ObjFile<ELFT> &f) {
   using Elf_Nhdr = typename ELFT::Nhdr;
   using Elf_Note = typename ELFT::Note;
 
-  uint32_t featuresSet = 0;
   ArrayRef<uint8_t> data = sec.content();
-  auto reportFatal = [&](const uint8_t *place, const char *msg) {
+  auto reportFatal = [&](const uint8_t *place, const Twine &msg) {
     fatal(toString(sec.file) + ":(" + sec.name + "+0x" +
           Twine::utohexstr(place - sec.content().data()) + "): " + msg);
   };
@@ -971,7 +964,20 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
         // accumulate the bits set.
         if (size < 4)
           reportFatal(place, "FEATURE_1_AND entry is too short");
-        featuresSet |= read32<ELFT::TargetEndianness>(desc.data());
+        f.andFeatures |= read32<ELFT::TargetEndianness>(desc.data());
+      } else if (config->emachine == EM_AARCH64 &&
+                 type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) {
+        if (!f.aarch64PauthAbiTag.empty())
+          reportFatal(data.data(),
+                      "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are "
+                      "not supported");
+        if (size != 16)
+          reportFatal(
+              data.data(),
+              Twine("GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too ") +
+                  (size < 16 ? "short" : "long") +
+                  ": expected 16 bytes, but got " + Twine(size));
+        f.aarch64PauthAbiTag = desc;
       }
 
       // Padding is present in the note descriptor, if necessary.
@@ -981,45 +987,6 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
     // Go to next NOTE record to look for more FEATURE_1_AND descriptions.
     data = data.slice(nhdr->getSize(sec.addralign));
   }
-
-  return featuresSet;
-}
-
-// Extract compatibility info for aarch64 pointer authentication from the
-// .note.AARCH64-PAUTH-ABI-tag section and write it to the corresponding ObjFile
-// field. See the following ABI documentation:
-// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking
-template <class ELFT>
-static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile<ELFT> &f) {
-  using Elf_Nhdr = typename ELFT::Nhdr;
-  using Elf_Note = typename ELFT::Note;
-  ArrayRef<uint8_t> data = sec.content();
-
-  auto *nhdr = reinterpret_cast<const Elf_Nhdr *>(data.data());
-  if (data.size() < sizeof(Elf_Nhdr) ||
-      data.size() < nhdr->getSize(sec.addralign)) {
-    errorOrWarn(toString(&sec) + ": section is too short");
-    return;
-  }
-
-  Elf_Note note(*nhdr);
-  if (nhdr->n_type != NT_ARM_TYPE_PAUTH_ABI_TAG)
-    errorOrWarn(toString(&sec) + ": invalid type field value " +
-                Twine(nhdr->n_type) + " (" + Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) +
-                " expected)");
-  if (note.getName() != "ARM")
-    errorOrWarn(toString(&sec) + ": invalid name field value " +
-                note.getName() + " (ARM expected)");
-
-  ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
-  if (desc.size() < 16) {
-    errorOrWarn(toString(&sec) +
-                ": AArch64 PAuth compatibility info is too short "
-                "(at least 16 bytes expected)");
-    return;
-  }
-
-  f.aarch64PauthAbiTag = desc;
 }
 
 template <class ELFT>
@@ -1076,13 +1043,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
     // .note.gnu.property containing a single AND'ed bitmap, we discard an input
     // file's .note.gnu.property section.
     if (name == ".note.gnu.property") {
-      this->andFeatures = readAndFeatures<ELFT>(InputSection(*this, sec, name));
-      return &InputSection::discarded;
-    }
-
-    if (config->emachine == EM_AARCH64 &&
-        name == ".note.AARCH64-PAUTH-ABI-tag") {
-      readAArch64PauthAbiTag<ELFT>(InputSection(*this, sec, name), *this);
+      readGnuProperty<ELFT>(InputSection(*this, sec, name), *this);
       return &InputSection::discarded;
     }
 
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index faab4bdc83748e..9a8f54b42b8417 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -314,44 +314,42 @@ GnuPropertySection::GnuPropertySection()
                        config->wordsize, ".note.gnu.property") {}
 
 void GnuPropertySection::writeTo(uint8_t *buf) {
+  write32(buf, 4);                          // Name size
+  write32(buf + 4, getSize() - 16);         // Content size
+  write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type
+  memcpy(buf + 12, "GNU", 4);               // Name string
+
   uint32_t featureAndType = config->emachine == EM_AARCH64
                                 ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
                                 : GNU_PROPERTY_X86_FEATURE_1_AND;
 
-  write32(buf, 4);                                   // Name size
-  write32(buf + 4, config->is64 ? 16 : 12);          // Content size
-  write32(buf + 8, NT_GNU_PROPERTY_TYPE_0);          // Type
-  memcpy(buf + 12, "GNU", 4);                        // Name string
-  write32(buf + 16, featureAndType);                 // Feature type
-  write32(buf + 20, 4);                              // Feature size
-  write32(buf + 24, config->andFeatures);            // Feature flags
-  if (config->is64)
-    write32(buf + 28, 0); // Padding
-}
+  unsigned offset = 16;
 
-size_t GnuPropertySection::getSize() const { return config->is64 ? 32 : 28; }
-
-AArch64PauthAbiTag::AArch64PauthAbiTag()
-    : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE,
-                       config->wordsize, ".note.AARCH64-PAUTH-ABI-tag") {}
-
-bool AArch64PauthAbiTag::isNeeded() const {
-  return !ctx.aarch64PauthAbiTag.empty();
-}
+  if (config->andFeatures != 0) {
+    write32(buf + offset + 0, featureAndType);      // Feature type
+    write32(buf + offset + 4, 4);                   // Feature size
+    write32(buf + offset + 8, config->andFeatures); // Feature flags
+    if (config->is64)
+      write32(buf + offset + 12, 0); // Padding
+    offset += 16;
+  }
 
-void AArch64PauthAbiTag::writeTo(uint8_t *buf) {
-  ArrayRef<uint8_t> data = ctx.aarch64PauthAbiTag;
-  write32(buf, 4);                             // Name size
-  write32(buf + 4, data.size());               // Content size
-  write32(buf + 8, NT_ARM_TYPE_PAUTH_ABI_TAG); // Type
-  memcpy(buf + 12, "ARM", 4);                  // Name string
-  memcpy(buf + 16, data.data(), data.size());
-  memset(buf + 16 + data.size(), 0, getSize() - 16 - data.size()); // Padding
+  if (!ctx.aarch64PauthAbiTag.empty()) {
+    write32(buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH);
+    write32(buf + offset + 4, ctx.aarch64PauthAbiTag.size());
+    memcpy(buf + offset + 8, ctx.aarch64PauthAbiTag.data(),
+           ctx.aarch64PauthAbiTag.size());
+  }
 }
 
-size_t AArch64PauthAbiTag::getSize() const {
-  return alignToPowerOf2(16 + ctx.aarch64PauthAbiTag.size(),
-                         config->is64 ? 8 : 4);
+size_t GnuPropertySection::getSize() const {
+  uint32_t contentSize = 0;
+  if (config->andFeatures != 0)
+    contentSize += config->is64 ? 16 : 12;
+  if (!ctx.aarch64PauthAbiTag.empty())
+    contentSize += 4 + 4 + ctx.aarch64PauthAbiTag.size();
+  assert(contentSize != 0);
+  return contentSize + 16;
 }
 
 BuildIdSection::BuildIdSection()
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 6f13b331f1bd1e..44ec306895549a 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -144,16 +144,6 @@ class GnuPropertySection final : public SyntheticSection {
   size_t getSize() const override;
 };
 
-// .note.AARCH64-PAUTH-ABI-tag section. See
-// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking
-class AArch64PauthAbiTag final : public SyntheticSection {
-public:
-  AArch64PauthAbiTag();
-  void writeTo(uint8_t *buf) override;
-  size_t getSize() const override;
-  bool isNeeded() const override;
-};
-
 // .note.gnu.build-id section.
 class BuildIdSection : public SyntheticSection {
   // First 16 bytes are a header.
@@ -1378,7 +1368,6 @@ struct InStruct {
   std::unique_ptr<StringTableSection> strTab;
   std::unique_ptr<SymbolTableBaseSection> symTab;
   std::unique_ptr<SymtabShndxSection> symTabShndx;
-  std::unique_ptr<AArch64PauthAbiTag> aarch64PauthAbiTag;
 
   void reset();
 };
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index ef51d6eb0fe1c5..c155ae709da65f 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -579,14 +579,9 @@ template <class ELFT> void elf::createSyntheticSections() {
   in.iplt = std::make_unique<IpltSection>();
   add(*in.iplt);
 
-  if (config->andFeatures)
+  if (config->andFeatures || !ctx.aarch64PauthAbiTag.empty())
     add(*make<GnuPropertySection>());
 
-  if (!ctx.aarch64PauthAbiTag.empty()) {
-    in.aarch64PauthAbiTag = std::make_unique<AArch64PauthAbiTag>();
-    add(*in.aarch64PauthAbiTag);
-  }
-
   // .note.GNU-stack is always added when we are creating a re-linkable
   // object file. Other linkers are using the presence of this marker
   // section to control the executable-ness of the stack area, but that
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index 44a74794822735..a0bc823b477ad4 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -7,7 +7,7 @@
 # RUN: ld.lld -shared tag1.o tag1a.o -o tagok.so
 # RUN: llvm-readelf -n tagok.so | FileCheck --check-prefix OK %s
 
-# OK: AArch64 PAuth ABI tag: platform 0x2a, version 0x1
+# OK: AArch64 PAuth ABI tag: platform 0x2a (unknown), version 0x1
 
 # 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
@@ -16,66 +16,95 @@
 # ERR1-NEXT: >>> tag1.o: 0x2a000000000000000{{1|2}}00000000000000
 # ERR1-NEXT: >>> tag2.o: 0x2a000000000000000{{1|2}}00000000000000
 
-# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-errs.s -o errs.o
-# RUN: not ld.lld errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s
+# 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
 
-# ERR2:      error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid type field value 42 (1 expected)
-# ERR2-NEXT: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid name field value XXX (ARM expected)
-# ERR2-NEXT: error: errs.o:(.note.AARCH64-PAUTH-ABI-tag): AArch64 PAuth compatibility info is too short (at least 16 bytes expected)
+# ERR2: error: short.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too short: expected 16 bytes, but got 12
 
-# 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 ERR3 %s
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-long.s -o long.o
+# RUN: not ld.lld long.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR3 %s
+
+# ERR3: error: long.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too long: expected 16 bytes, but got 24
 
-# ERR3: error: short.o:(.note.AARCH64-PAUTH-ABI-tag): section is too short
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-multiple.s -o multiple.o
+# RUN: not ld.lld multiple.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s
+# ERR4: error: multiple.o:(.note.gnu.property+0x0): multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are not supported
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o
 # RUN: cp noinfo1.o noinfo2.o
-# RUN: not ld.lld -z pauth-report=error tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s
+# RUN: not ld.lld -z pauth-report=error tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR5 %s
 # RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s
 # RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null
 
-# ERR4:      error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
-# ERR4-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
+# ERR5:      error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
+# ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
 # WARN:      warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
 # WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
 
 #--- abi-tag-short.s
 
-.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.section ".note.gnu.property", "a"
 .long 4
-.long 8
+.long 20
+.long 5
+.asciz "GNU"
+.long 0xc0000001
+.long 12
+.quad 2
+.long 31
 
-#--- abi-tag-errs.s
+#--- abi-tag-long.s
 
-.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.section ".note.gnu.property", "a"
 .long 4
-.long 8
-.long 42
-.asciz "XXX"
-
-.quad 42
+.long 32
+.long 5
+.asciz "GNU"
+.long 0xc0000001
+.long 24
+.quad 2
+.quad 31
+.quad 0
+
+#--- abi-tag-multiple.s
+
+.section ".note.gnu.property", "a"
+.long 4
+.long 48
+.long 5
+.asciz "GNU"
+.long 0xc0000001
+.long 16
+.quad 42 // platform
+.quad 1  // version
+.long 0xc0000001
+.long 16
+.quad 42 // platform
+.quad 1  // version
 
 #--- abi-tag1.s
 
-.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.section ".note.gnu.property", "a"
 .long 4
+.long 24
+.long 5
+.asciz "GNU"
+.long 0xc0000001
 .long 16
-.long 1
-.asciz "ARM"
-
-.quad 42         // platform
-.quad 1          // version
+.quad 42 // platform
+.quad 1  // version
 
 #--- abi-tag2.s
 
-.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.section ".note.gnu.property", "a"
 .long 4
+.long 24
+.long 5
+.asciz "GNU"
+.long 0xc0000001
 .long 16
-.long 1
-.asciz "ARM"
-
-.quad 42         // platform
-.quad 2          // version
+.quad 42 // platform
+.quad 2  // version
 
 #--- no-info.s
 

>From a340445269d8ab85ba8a2aab6188e6e7e7221336 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 18 Mar 2024 19:13:52 +0300
Subject: [PATCH 23/23] Support both `.note.gnu.property` and
 `.note.AARCH64-PAUTH-ABI-tag`

---
 lld/ELF/Config.h                     |   4 +
 lld/ELF/InputFiles.cpp               |  42 ++++++++
 lld/ELF/SyntheticSections.cpp        |  18 ++++
 lld/ELF/SyntheticSections.h          |  10 ++
 lld/ELF/Writer.cpp                   |  10 +-
 lld/test/ELF/aarch64-feature-pauth.s | 138 ++++++++++++++++++++++-----
 6 files changed, 197 insertions(+), 25 deletions(-)

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index f7d0923f083422..3c5321bbd84248 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -502,6 +502,10 @@ struct Ctx {
   llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &);
 
   ArrayRef<uint8_t> aarch64PauthAbiTag;
+  enum class AArch64PAuthELFMarkingWay : uint8_t {
+    GNUProperty,
+    Note,
+  } aarch64PauthElfMarkingWay = AArch64PAuthELFMarkingWay::Note;
 };
 
 LLVM_LIBRARY_VISIBILITY extern Ctx ctx;
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 89dc1afa5e9533..cf6ec1cf3d6302 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -989,6 +989,42 @@ void readGnuProperty(const InputSection &sec, ObjFile<ELFT> &f) {
   }
 }
 
+// Read AArch64 PAuth ABI compatibility info from the
+// .note.AARCH64-PAUTH-ABI-tag section and write it to the corresponding field
+// in `ObjFile`.
+template <class ELFT>
+static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile<ELFT> &f) {
+  using Elf_Nhdr = typename ELFT::Nhdr;
+  using Elf_Note = typename ELFT::Note;
+  ArrayRef<uint8_t> data = sec.content();
+
+  auto *nhdr = reinterpret_cast<const Elf_Nhdr *>(data.data());
+  if (data.size() < sizeof(Elf_Nhdr) ||
+      data.size() < nhdr->getSize(sec.addralign)) {
+    errorOrWarn(toString(&sec) + ": section is too short");
+    return;
+  }
+
+  Elf_Note note(*nhdr);
+  if (nhdr->n_type != NT_ARM_TYPE_PAUTH_ABI_TAG)
+    errorOrWarn(toString(&sec) + ": invalid type field value " +
+                Twine(nhdr->n_type) + " (" + Twine(NT_ARM_TYPE_PAUTH_ABI_TAG) +
+                " expected)");
+  if (note.getName() != "ARM")
+    errorOrWarn(toString(&sec) + ": invalid name field value " +
+                note.getName() + " (ARM expected)");
+
+  ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
+  if (desc.size() != 16) {
+    errorOrWarn(toString(&sec) + ": AArch64 PAuth compatibility info is too " +
+                (desc.size() < 16 ? "short" : "long") +
+                ": expected 16 bytes, but got " + Twine(desc.size()));
+    return;
+  }
+
+  f.aarch64PauthAbiTag = desc;
+}
+
 template <class ELFT>
 InputSectionBase *ObjFile<ELFT>::getRelocTarget(uint32_t idx,
                                                 const Elf_Shdr &sec,
@@ -1047,6 +1083,12 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
       return &InputSection::discarded;
     }
 
+    if (config->emachine == EM_AARCH64 &&
+        name == ".note.AARCH64-PAUTH-ABI-tag") {
+      readAArch64PauthAbiTag<ELFT>(InputSection(*this, sec, name), *this);
+      return &InputSection::discarded;
+    }
+
     // Split stacks is a feature to support a discontiguous stack,
     // commonly used in the programming language Go. For the details,
     // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 9a8f54b42b8417..e6071d7b0a641c 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -352,6 +352,24 @@ size_t GnuPropertySection::getSize() const {
   return contentSize + 16;
 }
 
+AArch64PauthAbiTag::AArch64PauthAbiTag()
+    : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE,
+                       config->wordsize, ".note.AARCH64-PAUTH-ABI-tag") {}
+
+bool AArch64PauthAbiTag::isNeeded() const {
+  return !ctx.aarch64PauthAbiTag.empty() &&
+         ctx.aarch64PauthElfMarkingWay == Ctx::AArch64PAuthELFMarkingWay::Note;
+}
+
+void AArch64PauthAbiTag::writeTo(uint8_t *buf) {
+  ArrayRef<uint8_t> data = ctx.aarch64PauthAbiTag;
+  write32(buf, 4);                             // Name size
+  write32(buf + 4, data.size());               // Content size
+  write32(buf + 8, NT_ARM_TYPE_PAUTH_ABI_TAG); // Type
+  memcpy(buf + 12, "ARM", 4);                  // Name string
+  memcpy(buf + 16, data.data(), data.size());
+}
+
 BuildIdSection::BuildIdSection()
     : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"),
       hashSize(getHashSize()) {}
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 44ec306895549a..fd1fbde357a228 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -144,6 +144,15 @@ class GnuPropertySection final : public SyntheticSection {
   size_t getSize() const override;
 };
 
+// .note.AARCH64-PAUTH-ABI-tag section.
+class AArch64PauthAbiTag final : public SyntheticSection {
+public:
+  AArch64PauthAbiTag();
+  void writeTo(uint8_t *buf) override;
+  size_t getSize() const override { return 32; }
+  bool isNeeded() const override;
+};
+
 // .note.gnu.build-id section.
 class BuildIdSection : public SyntheticSection {
   // First 16 bytes are a header.
@@ -1368,6 +1377,7 @@ struct InStruct {
   std::unique_ptr<StringTableSection> strTab;
   std::unique_ptr<SymbolTableBaseSection> symTab;
   std::unique_ptr<SymtabShndxSection> symTabShndx;
+  std::unique_ptr<AArch64PauthAbiTag> aarch64PauthAbiTag;
 
   void reset();
 };
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c155ae709da65f..17e0542de38c1b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -579,9 +579,17 @@ template <class ELFT> void elf::createSyntheticSections() {
   in.iplt = std::make_unique<IpltSection>();
   add(*in.iplt);
 
-  if (config->andFeatures || !ctx.aarch64PauthAbiTag.empty())
+  if (config->andFeatures || (!ctx.aarch64PauthAbiTag.empty() &&
+                              ctx.aarch64PauthElfMarkingWay ==
+                                  Ctx::AArch64PAuthELFMarkingWay::GNUProperty))
     add(*make<GnuPropertySection>());
 
+  if (!ctx.aarch64PauthAbiTag.empty() &&
+      ctx.aarch64PauthElfMarkingWay == Ctx::AArch64PAuthELFMarkingWay::Note) {
+    in.aarch64PauthAbiTag = std::make_unique<AArch64PauthAbiTag>();
+    add(*in.aarch64PauthAbiTag);
+  }
+
   // .note.GNU-stack is always added when we are creating a re-linkable
   // object file. Other linkers are using the presence of this marker
   // section to control the executable-ness of the stack area, but that
diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s
index a0bc823b477ad4..a0c32dd578932a 100644
--- a/lld/test/ELF/aarch64-feature-pauth.s
+++ b/lld/test/ELF/aarch64-feature-pauth.s
@@ -2,46 +2,136 @@
 
 # RUN: rm -rf %t && split-file %s %t && cd %t
 
-# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag1.s -o tag1.o
-# RUN: cp tag1.o tag1a.o
-# RUN: ld.lld -shared tag1.o tag1a.o -o tagok.so
-# RUN: llvm-readelf -n tagok.so | FileCheck --check-prefix OK %s
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu gnu-prop1.s -o gnu-prop1.o
+# RUN: cp gnu-prop1.o gnu-prop1a.o
+# RUN: ld.lld -shared gnu-prop1.o gnu-prop1a.o -o gnu-prop-ok.so
+# RUN: llvm-readelf -n gnu-prop-ok.so | FileCheck --check-prefix OK-GNU %s
 
-# OK: AArch64 PAuth ABI tag: platform 0x2a (unknown), version 0x1
+# OK-GNU: AArch64 PAuth ABI tag: platform 0x2a (unknown), version 0x1
 
-# 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
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu gnu-prop2.s -o gnu-prop2.o
+# RUN: not ld.lld gnu-prop1.o gnu-prop1a.o gnu-prop2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR1 %s
 
 # ERR1:      error: incompatible values of AArch64 PAuth compatibility info found
-# ERR1-NEXT: >>> tag1.o: 0x2a000000000000000{{1|2}}00000000000000
-# ERR1-NEXT: >>> tag2.o: 0x2a000000000000000{{1|2}}00000000000000
+# ERR1-NEXT: >>> gnu-prop1.o: 0x2a000000000000000{{1|2}}00000000000000
+# ERR1-NEXT: >>> gnu-prop2.o: 0x2a000000000000000{{1|2}}00000000000000
 
-# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o short.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu gnu-prop-short.s -o short.o
 # RUN: not ld.lld short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR2 %s
 
 # ERR2: error: short.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too short: expected 16 bytes, but got 12
 
-# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-long.s -o long.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu gnu-prop-long.s -o long.o
 # RUN: not ld.lld long.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR3 %s
 
 # ERR3: error: long.o:(.note.gnu.property+0x0): GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry is too long: expected 16 bytes, but got 24
 
-# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-multiple.s -o multiple.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu gnu-prop-multiple.s -o multiple.o
 # RUN: not ld.lld multiple.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR4 %s
 # ERR4: error: multiple.o:(.note.gnu.property+0x0): multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are not supported
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu no-info.s -o noinfo1.o
 # RUN: cp noinfo1.o noinfo2.o
-# RUN: not ld.lld -z pauth-report=error tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR5 %s
-# RUN: ld.lld -z pauth-report=warning tag1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN %s
-# RUN: ld.lld -z pauth-report=none tag1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null
+# RUN: not ld.lld -z pauth-report=error gnu-prop1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR5 %s
+# RUN: ld.lld -z pauth-report=warning gnu-prop1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN1 %s
+# RUN: ld.lld -z pauth-report=none gnu-prop1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null
 
-# ERR5:      error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
-# ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
-# WARN:      warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
-# WARN-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while tag1.o has one
+# ERR5:      error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while gnu-prop1.o has one
+# ERR5-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while gnu-prop1.o has one
+# WARN1:      warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while gnu-prop1.o has one
+# WARN1-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while gnu-prop1.o has one
 
-#--- abi-tag-short.s
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu note1.s -o note1.o
+# RUN: cp note1.o note1a.o
+# RUN: ld.lld -shared note1.o note1a.o -o note-ok.so
+# RUN: llvm-readelf -n note-ok.so | FileCheck --check-prefix OK-NOTE %s
+
+# OK-NOTE: AArch64 PAuth ABI tag: platform 0x2a (unknown), version 0x1
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu note2.s -o note2.o
+# RUN: not ld.lld note1.o note1a.o note2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR6 %s
+
+# ERR6:      error: incompatible values of AArch64 PAuth compatibility info found
+# ERR6-NEXT: >>> note1.o: 0x2a000000000000000{{1|2}}00000000000000
+# ERR6-NEXT: >>> note2.o: 0x2a000000000000000{{1|2}}00000000000000
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu note-errs.s -o note-errs.o
+# RUN: not ld.lld note-errs.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR7 %s
+
+# ERR7:      error: note-errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid type field value 42 (1 expected)
+# ERR7-NEXT: error: note-errs.o:(.note.AARCH64-PAUTH-ABI-tag): invalid name field value XXX (ARM expected)
+# ERR7-NEXT: error: note-errs.o:(.note.AARCH64-PAUTH-ABI-tag): AArch64 PAuth compatibility info is too short: expected 16 bytes, but got 8
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu note-short.s -o note-short.o
+# RUN: not ld.lld note-short.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR8 %s
+
+# ERR8: error: note-short.o:(.note.AARCH64-PAUTH-ABI-tag): section is too short
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu note-long.s -o note-long.o
+# RUN: not ld.lld note-long.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR9 %s
+
+# ERR9: error: note-long.o:(.note.AARCH64-PAUTH-ABI-tag): AArch64 PAuth compatibility info is too long: expected 16 bytes, but got 24
+
+# RUN: not ld.lld -z pauth-report=error note1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix ERR10 %s
+# RUN: ld.lld -z pauth-report=warning note1.o noinfo1.o noinfo2.o -o /dev/null 2>&1 | FileCheck --check-prefix WARN2 %s
+# RUN: ld.lld -z pauth-report=none note1.o noinfo1.o noinfo2.o --fatal-warnings -o /dev/null
+
+# ERR10:      error: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while note1.o has one
+# ERR10-NEXT: error: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while note1.o has one
+# WARN2:      warning: noinfo1.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while note1.o has one
+# WARN2-NEXT: warning: noinfo2.o: -z pauth-report: file does not have AArch64 PAuth compatibility info while note1.o has one
+
+#--- note-short.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 8
+
+#--- note-long.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 24
+.long 1
+.asciz "ARM"
+
+.quad 42
+.quad 1
+.quad 0
+
+#--- note-errs.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 8
+.long 42
+.asciz "XXX"
+
+.quad 42
+
+#--- note1.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 16
+.long 1
+.asciz "ARM"
+
+.quad 42         // platform
+.quad 1          // version
+
+#--- note2.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 16
+.long 1
+.asciz "ARM"
+
+.quad 42         // platform
+.quad 2          // version
+
+#--- gnu-prop-short.s
 
 .section ".note.gnu.property", "a"
 .long 4
@@ -53,7 +143,7 @@
 .quad 2
 .long 31
 
-#--- abi-tag-long.s
+#--- gnu-prop-long.s
 
 .section ".note.gnu.property", "a"
 .long 4
@@ -66,7 +156,7 @@
 .quad 31
 .quad 0
 
-#--- abi-tag-multiple.s
+#--- gnu-prop-multiple.s
 
 .section ".note.gnu.property", "a"
 .long 4
@@ -82,7 +172,7 @@
 .quad 42 // platform
 .quad 1  // version
 
-#--- abi-tag1.s
+#--- gnu-prop1.s
 
 .section ".note.gnu.property", "a"
 .long 4
@@ -94,7 +184,7 @@
 .quad 42 // platform
 .quad 1  // version
 
-#--- abi-tag2.s
+#--- gnu-prop2.s
 
 .section ".note.gnu.property", "a"
 .long 4



More information about the llvm-commits mailing list