diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -112,6 +112,7 @@
   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 @@
   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
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -269,6 +269,7 @@
   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
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -537,6 +537,7 @@
     "nognustack",
     "nokeep-text-section-prefix",
     "nopack-relative-relocs",
+    "nopack-relative-auth-relocs",
     "norelro",
     "noseparate-code",
     "nostart-stop-gc",
@@ -545,6 +546,7 @@
     "origin",
     "pac-plt",
     "pack-relative-relocs",
+    "pack-relative-auth-relocs",
     "rel",
     "rela",
     "relro",
@@ -1576,6 +1578,9 @@
         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/Relocations.cpp b/lld/ELF/Relocations.cpp
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1438,6 +1438,34 @@
     }
   }
 
+  if (config->emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
+    assert(RelTy::IsRela); // Assume that AArch64 uses rela
+    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 {
+      // Check if an implicit addend to be stored is a 32-bit integer since only
+      // bits 0..31 are left for that when using R_AARCH64_AUTH_RELATIVE
+      // relocations. The higher bits 32..63 store the signing schema encoding.
+      // For comments regarding relr, see addRelativeReloc.
+      if (part.relrAuthDyn && sec->addralign >= 2 && offset % 2 == 0 &&
+          isInt<32>(sym.getVA(addend))) {
+        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
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -543,7 +543,8 @@
   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 +600,7 @@
 
 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 +618,7 @@
   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; }
@@ -1309,6 +1310,7 @@
   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;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1405,6 +1405,12 @@
     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
@@ -1716,10 +1722,13 @@
   }
 }
 
-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() {
@@ -1987,8 +1996,8 @@
 }
 
 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/Writer.cpp b/lld/ELF/Writer.cpp
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -397,6 +397,12 @@
       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>();
@@ -1657,6 +1663,8 @@
       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();
     }
@@ -2102,6 +2110,10 @@
         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-ptrauth.s b/lld/test/ELF/aarch64-ptrauth.s
new file mode 100644
--- /dev/null
+++ b/lld/test/ELF/aarch64-ptrauth.s
@@ -0,0 +1,157 @@
+// REQUIRES: aarch64
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %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-unknown-linux %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:       0x0000000070000006 AARCH64_AUTH_RELR    [[ADDR]]
+// RELR-HEADERS:       0x0000000070000008 AARCH64_AUTH_RELRSZ  16 (bytes)
+// RELR-HEADERS:       0x0000000070000007 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@AUTH(da,42)
+.quad bar2@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@AUTH(ia,42)
+.quad bar2@AUTH(ia,42)
+.quad (bar2 + 1)@AUTH(ia,42)
+.quad (bar2 + 1)@AUTH(ia,42)
+.quad bar2@AUTH(ia,42)
+
diff --git a/llvm/include/llvm/BinaryFormat/DynamicTags.def b/llvm/include/llvm/BinaryFormat/DynamicTags.def
--- a/llvm/include/llvm/BinaryFormat/DynamicTags.def
+++ b/llvm/include/llvm/BinaryFormat/DynamicTags.def
@@ -132,6 +132,14 @@
 AARCH64_DYNAMIC_TAG(AARCH64_MEMTAG_GLOBALS, 0x7000000d)
 AARCH64_DYNAMIC_TAG(AARCH64_MEMTAG_GLOBALSSZ, 0x7000000f)
 
+// AArch64 specific dynamic table entries for RELR auth relocations as described here:
+// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#dynamic-section
+// FIXME: this should be 0x70000005, but it overlaps with AARCH64_VARIANT_PCS
+// See https://reviews.llvm.org/D93044 when it was first introduced.
+AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELRSZ, 0x70000008)
+AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELR, 0x70000006)
+AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELRENT, 0x70000007)
+
 // Hexagon specific dynamic table entries
 HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000)
 HEXAGON_DYNAMIC_TAG(HEXAGON_VER, 0x70000001)
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1056,6 +1056,9 @@
   SHT_ARM_ATTRIBUTES = 0x70000003U,
   SHT_ARM_DEBUGOVERLAY = 0x70000004U,
   SHT_ARM_OVERLAYSECTION = 0x70000005U,
+  // Special aarch64-specific section for MTE support, as described in:
+  // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types
+  SHT_AARCH64_AUTH_RELR = 0x70000004U,
   // Special aarch64-specific sections for MTE support, as described in:
   // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#7section-types
   SHT_AARCH64_MEMTAG_GLOBALS_STATIC = 0x70000007U,
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
@@ -135,6 +135,7 @@
 ELF_RELOC(R_AARCH64_TLSDESC,                         0x407)
 ELF_RELOC(R_AARCH64_IRELATIVE,                       0x408)
 ELF_RELOC(R_AARCH64_AUTH_ABS64,                      0xe100)
+ELF_RELOC(R_AARCH64_AUTH_RELATIVE,                   0xe200)
 
 // ELF_RELOC(R_AARCH64_P32_NONE,                         0)
 ELF_RELOC(R_AARCH64_P32_ABS32,                       0x001)
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -299,6 +299,7 @@
     STRINGIFY_ENUM_CASE(ELF, SHT_GROUP);
     STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX);
     STRINGIFY_ENUM_CASE(ELF, SHT_RELR);
+    STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_AUTH_RELR);
     STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL);
     STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA);
     STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELR);
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -669,6 +669,7 @@
   ECase(SHT_GROUP);
   ECase(SHT_SYMTAB_SHNDX);
   ECase(SHT_RELR);
+  ECase(SHT_AARCH64_AUTH_RELR);
   ECase(SHT_ANDROID_REL);
   ECase(SHT_ANDROID_RELA);
   ECase(SHT_ANDROID_RELR);
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -2077,21 +2077,40 @@
       break;
     case ELF::DT_RELR:
     case ELF::DT_ANDROID_RELR:
+    case ELF::DT_AARCH64_AUTH_RELR:
       DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
       break;
     case ELF::DT_RELRSZ:
     case ELF::DT_ANDROID_RELRSZ:
+    case ELF::DT_AARCH64_AUTH_RELRSZ:
       DynRelrRegion.Size = Dyn.getVal();
-      DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ
-                                        ? "DT_RELRSZ value"
-                                        : "DT_ANDROID_RELRSZ value";
+      DynRelrRegion.SizePrintName = [&Dyn]() {
+        switch (Dyn.d_tag) {
+        case ELF::DT_RELRSZ:
+          return "DT_RELRSZ value";
+        case ELF::DT_ANDROID_RELRSZ:
+          return "DT_ANDROID_RELRSZ value";
+        case ELF::DT_AARCH64_AUTH_RELRSZ:
+          return "DT_AARCH64_AUTH_RELRSZ value";
+        }
+        llvm_unreachable("Unexpected Dyn.d_tag value");
+      }();
       break;
     case ELF::DT_RELRENT:
     case ELF::DT_ANDROID_RELRENT:
+    case ELF::DT_AARCH64_AUTH_RELRENT:
       DynRelrRegion.EntSize = Dyn.getVal();
-      DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT
-                                           ? "DT_RELRENT value"
-                                           : "DT_ANDROID_RELRENT value";
+      DynRelrRegion.EntSizePrintName = [&Dyn]() {
+        switch (Dyn.d_tag) {
+        case ELF::DT_RELRENT:
+          return "DT_RELRENT value";
+        case ELF::DT_ANDROID_RELRENT:
+          return "DT_ANDROID_RELRENT value";
+        case ELF::DT_AARCH64_AUTH_RELRENT:
+          return "DT_AARCH64_AUTH_RELRENT value";
+        }
+        llvm_unreachable("Unexpected Dyn.d_tag value");
+      }();
       break;
     case ELF::DT_PLTREL:
       if (Dyn.getVal() == DT_REL)
@@ -2454,6 +2473,8 @@
   case DT_PREINIT_ARRAYSZ:
   case DT_RELRSZ:
   case DT_RELRENT:
+  case DT_AARCH64_AUTH_RELRSZ:
+  case DT_AARCH64_AUTH_RELRENT:
   case DT_ANDROID_RELSZ:
   case DT_ANDROID_RELASZ:
     return std::to_string(Value) + " (bytes)";
@@ -3788,7 +3809,8 @@
 template <class ELFT>
 static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType) {
   bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;
-  bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR;
+  bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR ||
+                SType == ELF::SHT_AARCH64_AUTH_RELR;
   if (ELFT::Is64Bits)
     OS << "    ";
   else
@@ -3821,7 +3843,8 @@
   return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA ||
          Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_REL ||
          Sec.sh_type == ELF::SHT_ANDROID_RELA ||
-         Sec.sh_type == ELF::SHT_ANDROID_RELR;
+         Sec.sh_type == ELF::SHT_ANDROID_RELR ||
+         Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR;
 }
 
 template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
@@ -3837,8 +3860,9 @@
       return RelasOrErr->size();
     }
 
-    if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR ||
-                           Sec.sh_type == ELF::SHT_ANDROID_RELR)) {
+    if (!opts::RawRelr &&
+        (Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_RELR ||
+         Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)) {
       Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec);
       if (!RelrsOrErr)
         return RelrsOrErr.takeError();
@@ -6172,11 +6196,12 @@
                               toString(std::move(E)));
   };
 
-  // SHT_RELR/SHT_ANDROID_RELR sections do not have an associated symbol table.
-  // For them we should not treat the value of the sh_link field as an index of
-  // a symbol table.
+  // SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR sections do not have an
+  // associated symbol table. For them we should not treat the value of the
+  // sh_link field as an index of a symbol table.
   const Elf_Shdr *SymTab;
-  if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR) {
+  if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR &&
+      Sec.sh_type != ELF::SHT_AARCH64_AUTH_RELR) {
     Expected<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Sec.sh_link);
     if (!SymTabOrErr) {
       Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for");
@@ -6205,6 +6230,7 @@
     }
     break;
   case ELF::SHT_RELR:
+  case ELF::SHT_AARCH64_AUTH_RELR:
   case ELF::SHT_ANDROID_RELR: {
     Expected<Elf_Relr_Range> RangeOrErr = Obj.relrs(Sec);
     if (!RangeOrErr) {