[lld] [PAC][lld] Properly handle `.relr.auth.dyn` -> `.rela.dyn` movement (PR #195649)

Daniil Kovalev via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 1 02:48:55 PDT 2026


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

>From 216cb89ec4798bf0ba1fa02fb4fb605d6a3731a4 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 29 Apr 2026 19:20:45 +0300
Subject: [PATCH 1/3] [PAC][lld] Properly handle `.relr.auth.dyn` ->
 `.rela.dyn` movement

Address the following issues reported in #171475:

1. Proper adjustment of `__rela_iplt_end` address if a move from
   `.relr.auth.dyn` to `.rela.dyn` took place

2. Set `__rela_iplt_start` properly if prior to such movement from
   `.relr.auth.dyn`, the `.rela.dyn` was empty

3. Allocate enough space for both RELA* and AARCH64_AUTH_RELR* tags in
   the `.dynamic` section in case we end up with both `.relr.auth.dyn`
   and `.rela.dyn`. If one of the sections becomes empty - just pad the
   `.dynamic` section with null tags in the end.
---
 lld/ELF/SyntheticSections.cpp      |  15 ++-
 lld/ELF/SyntheticSections.h        |   3 +-
 lld/ELF/Writer.cpp                 |  27 ++---
 lld/test/ELF/aarch64-reloc-pauth.s | 156 +++++++++++++++++++++++++++--
 4 files changed, 173 insertions(+), 28 deletions(-)

diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index c4807e1e150b5..633966182e8cf 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1174,8 +1174,8 @@ static uint64_t addPltRelSz(Ctx &ctx) { return ctx.in.relaPlt->getSize(); }
 
 // Add remaining entries to complete .dynamic contents.
 template <class ELFT>
-std::vector<std::pair<int32_t, uint64_t>>
-DynamicSection<ELFT>::computeContents() {
+std::vector<std::pair<int32_t, uint64_t>> DynamicSection<ELFT>::computeContents(
+    bool afterFinalizeAddressDependentContents) {
   elf::Partition &part = getPartition(ctx);
   bool isMain = part.name.empty();
   std::vector<std::pair<int32_t, uint64_t>> entries;
@@ -1257,7 +1257,9 @@ DynamicSection<ELFT>::computeContents() {
   if (!ctx.arg.shared && !ctx.arg.relocatable && !ctx.arg.zRodynamic)
     addInt(DT_DEBUG, 0);
 
-  if (part.relaDyn->isNeeded()) {
+  if (part.relaDyn->isNeeded() ||
+      (!afterFinalizeAddressDependentContents && part.relrAuthDyn &&
+       part.relrAuthDyn->getParent() && !part.relrAuthDyn->relocs.empty())) {
     addInSec(part.relaDyn->dynamicTag, *part.relaDyn);
     entries.emplace_back(part.relaDyn->sizeDynamicTag,
                          addRelaSz(ctx, *part.relaDyn));
@@ -1440,13 +1442,16 @@ DynamicSection<ELFT>::computeContents() {
 template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
   if (OutputSection *sec = getPartition(ctx).dynStrTab->getParent())
     getParent()->link = sec->sectionIndex;
-  this->size = computeContents().size() * this->entsize;
+  this->size =
+      computeContents(/*afterFinalizeAddressDependentContents=*/false).size() *
+      this->entsize;
 }
 
 template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) {
   auto *p = reinterpret_cast<Elf_Dyn *>(buf);
 
-  for (std::pair<int32_t, uint64_t> kv : computeContents()) {
+  for (std::pair<int32_t, uint64_t> kv :
+       computeContents(/*afterFinalizeAddressDependentContents=*/true)) {
     p->d_tag = kv.first;
     p->d_un.d_val = kv.second;
     ++p;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 92dcbb922aa58..eee77cbf87148 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -483,7 +483,8 @@ template <class ELFT> class DynamicSection final : public SyntheticSection {
   size_t getSize() const override { return size; }
 
 private:
-  std::vector<std::pair<int32_t, uint64_t>> computeContents();
+  std::vector<std::pair<int32_t, uint64_t>>
+  computeContents(bool afterFinalizeAddressDependentContents);
 };
 
 class RelocationBaseSection : public SyntheticSection {
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index ad5cf39c72163..51fcbbf48a9e6 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -867,17 +867,6 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
     ctx.sym.globalOffsetTable->section = sec;
   }
 
-  // .rela_iplt_{start,end} mark the start and the end of the section containing
-  // IRELATIVE relocations.
-  if (ctx.sym.relaIpltStart) {
-    auto &dyn = getIRelativeSection(ctx);
-    if (dyn.isNeeded()) {
-      ctx.sym.relaIpltStart->section = &dyn;
-      ctx.sym.relaIpltEnd->section = &dyn;
-      ctx.sym.relaIpltEnd->value = dyn.getSize();
-    }
-  }
-
   PhdrEntry *last = nullptr;
   OutputSection *lastRO = nullptr;
   auto isLarge = [&ctx = ctx](OutputSection *osec) {
@@ -1793,7 +1782,8 @@ static void removeUnusedSyntheticSections(Ctx &ctx) {
         // Conservatively keep .rela.dyn. .relr.auth.dyn can be made empty, but
         // we would fail to remove it here.
         if (ctx.arg.emachine == EM_AARCH64 && ctx.arg.relrPackDynRelocs &&
-            sec == ctx.mainPart->relaDyn.get())
+            sec == ctx.mainPart->relaDyn.get() && ctx.mainPart->relrAuthDyn &&
+            ctx.mainPart->relrAuthDyn->isNeeded())
           return false;
         unused.insert(sec);
         return true;
@@ -2149,6 +2139,19 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   //    values. They also might change after adding the thunks.
   finalizeAddressDependentContent();
 
+  // .rela_iplt_{start,end} mark the start and the end of the section containing
+  // IRELATIVE relocations. This must be called after
+  // finalizeAddressDependentContent() because it might move relocations from
+  // .relr.auth.dyn to .rela.dyn.
+  if (ctx.sym.relaIpltStart) {
+    auto &dyn = getIRelativeSection(ctx);
+    if (dyn.isNeeded()) {
+      ctx.sym.relaIpltStart->section = &dyn;
+      ctx.sym.relaIpltEnd->section = &dyn;
+      ctx.sym.relaIpltEnd->value = dyn.getSize();
+    }
+  }
+
   // All information needed for OutputSection part of Map file is available.
   if (errCount(ctx))
     return;
diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 6b4d23d37babc..1b96bc7fc27df 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -41,17 +41,22 @@
 # NOPIE-NEXT: }
 
 # 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
+# RUN: llvm-readelf -S -d -r -x .dynamic -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:      .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[[ADDR2]]
-# RELR-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 24 (bytes)
+# RELR:      Dynamic section at offset 0x340 contains 16 entries
+# RELR:      0x0000000000000007 (RELA)                 0x[[ADDR1]]
+# RELR-NEXT: 0x0000000000000008 (RELASZ)               144 (bytes)
+# RELR-NEXT: 0x0000000000000009 (RELAENT)              24 (bytes)
+# RELR-NEXT: 0x0000000070000012 (AARCH64_AUTH_RELR)    0x[[ADDR2]]
+# RELR-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ)  24 (bytes)
 # RELR-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)
+# RELR:      0x0000000000000000 (NULL)                 0x0
+# RELR-EMPTY:
 
 ## Decoded SHT_RELR section is same as UNPACKED,
 ## but contains only the relative relocations.
@@ -74,6 +79,10 @@
 # RELR-NEXT:  0000000000030458 $d + 0x18
 # RELR-NEXT: 0002: 0000000000030492 0000000000030492 $d + 0x52
 
+# HEX:      Hex dump of section '.dynamic':
+# HEX:      0x00020430 00000000 00000000 00000000 00000000
+# HEX-EMPTY:
+
 # HEX:      Hex dump of section '.test':
 # HEX-NEXT: 0x00030440 01000000 2a000020 42040300 2b000000
 ##                     ^^^^^^^^ Implicit val = 1 = __ehdr_start + 1
@@ -145,28 +154,43 @@
 
 # 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
+# RUN: llvm-readelf -S -d -r -x.dynamic 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:      Dynamic section at offset 0x260 contains 12 entries
+# EMPTY-RELR-NOT:  (RELR)
+# EMPTY-RELR-NOT:  (RELRSZ)
+# EMPTY-RELR-NOT:  (RELRENT)
 # 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:      0x0000000000000000 (NULL) 0x0
+# EMPTY-RELR-EMPTY:
 
 # 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-NEXT: 0000000000030350  0000000000000411 R_AARCH64_AUTH_RELATIVE           8003034f
 # EMPTY-RELR-EMPTY:
 # EMPTY-RELR-NEXT: Relocation section '.relr.auth.dyn' at offset {{.+}} contains 0 entries:
 # EMPTY-RELR-NEXT: Index: Entry Address Symbolic Address
 
+## The .dynamic section has enough space pre-allocated for the case when both
+## .rela.dyn and .relr.auth.dyn sections are present. Since .relr.auth.dyn becomes
+## empty for this test, this space is filled with NULL tags.
+# EMPTY-RELR:      Hex dump of section '.dynamic':
+# EMPTY-RELR:      0x00020310 00000000 00000000 00000000 00000000
+# EMPTY-RELR-NEXT: 0x00020320 00000000 00000000 00000000 00000000
+# EMPTY-RELR-NEXT: 0x00020330 00000000 00000000 00000000 00000000
+# EMPTY-RELR-NEXT: 0x00020340 00000000 00000000 00000000 00000000
+# EMPTY-RELR-EMPTY:
+
 .section .test, "aw"
 .p2align 3
 .quad (.test + 0x7FFFFFFF)@AUTH(da,42)
@@ -179,7 +203,7 @@
 
 # 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
+# RUN: llvm-readelf -S -d -r -x.dynamic empty-rela | FileCheck --check-prefixes=EMPTY-RELA %s
 # RUN: ld.lld -r -z pack-relative-relocs empty-rela.o -o empty-rela.ro
 # RUN: llvm-readelf -S empty-rela.ro | FileCheck --check-prefixes=EMPTY-RELA-RO %s
 
@@ -188,23 +212,135 @@
 # 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:      Dynamic section at offset 0x250 contains 12 entries
 # EMPTY-RELA-NOT:  (RELR)
 # EMPTY-RELA-NOT:  (RELRSZ)
 # EMPTY-RELA-NOT:  (RELRENT)
+# EMPTY-RELA-NOT:  (RELA)
+# EMPTY-RELA-NOT:  (RELASZ)
+# EMPTY-RELA-NOT:  (RELAENT)
 # 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:      0x0000000000000000 (NULL) 0x0
+# EMPTY-RELA-EMPTY:
 
 # 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: Index: Entry Address Symbolic Address
-# EMPTY-RELA-NEXT: 0000: 0000000000030310 0000000000030310 $d
+# EMPTY-RELA-NEXT: 0000: 0000000000030340 0000000000030340 $d
+
+## The .dynamic section has enough space pre-allocated for the case when both
+## .rela.dyn and .relr.auth.dyn sections are present. Since .rela.dyn becomes
+## empty for this test, this space is filled with NULL tags.
+# EMPTY-RELA:      Hex dump of section '.dynamic':
+# EMPTY-RELA:      0x00020300 00000000 00000000 00000000 00000000
+# EMPTY-RELA-NEXT: 0x00020310 00000000 00000000 00000000 00000000
+# EMPTY-RELA-NEXT: 0x00020320 00000000 00000000 00000000 00000000
+# EMPTY-RELA-NEXT: 0x00020330 00000000 00000000 00000000 00000000
+# EMPTY-RELA-EMPTY:
 
 # EMPTY-RELA-RO-NOT: .rela.dyn
 
 .section .test, "aw"
 .p2align 3
 .quad (.test + 0x12345678)@AUTH(da,42)
+
+#--- dynamic-section-growth.s
+
+## .relr.auth.dyn relocations that do not fit 32 bits are moved to .rela.dyn.
+## If some relocations are moved to the previously empty .rela.dyn and some stay
+## in .relr.auth.dyn, the dynamic section needs contain tags for both these
+## sections and have enough space for storing these tags.
+## See also https://github.com/llvm/llvm-project/issues/171475
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 dynamic-section-growth.s -o dynamic-section-growth.o
+# RUN: ld.lld -shared -z pack-relative-relocs dynamic-section-growth.o -o dynamic-section-growth.so
+# RUN: llvm-readelf -S -d -r -x.dynamic dynamic-section-growth.so | FileCheck --check-prefix=DYN-GROW %s
+
+# DYN-GROW:     .rela.dyn         RELA            0000000000000248 000248 000018 18   A  0   0  8
+# DYN-GROW:     .relr.auth.dyn    AARCH64_AUTH_RELR 0000000000000260 000260 000008 08   A  0   0  8
+# DYN-GROW:     .dynamic          DYNAMIC         0000000000020268 000268 0000d0 10  WA  4   0  8
+
+# DYN-GROW:      Dynamic section at offset 0x268 contains 13 entries:
+# DYN-GROW:      0x0000000000000007 (RELA)                 0x248
+# DYN-GROW-NEXT: 0x0000000000000008 (RELASZ)               24 (bytes)
+# DYN-GROW-NEXT: 0x0000000000000009 (RELAENT)              24 (bytes)
+# DYN-GROW-NEXT: 0x0000000070000012 (AARCH64_AUTH_RELR)    0x260
+# DYN-GROW-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ)  8 (bytes)
+# DYN-GROW-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 8 (bytes)
+# DYN-GROW:      0x0000000000000000 (NULL)                 0x0
+# DYN-GROW-EMPTY:
+
+# DYN-GROW:      Relocation section '.rela.dyn' at offset 0x248 contains 1 entries:
+# DYN-GROW-NEXT:     Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
+# DYN-GROW-NEXT: 0000000000030340  0000000000000411 R_AARCH64_AUTH_RELATIVE           100030338
+# DYN-GROW-EMPTY:
+
+# DYN-GROW:      Relocation section '.relr.auth.dyn' at offset 0x260 contains 1 entries:
+# DYN-GROW-NEXT: Index: Entry            Address           Symbolic Address
+# DYN-GROW-NEXT: 0000:  0000000000030338 0000000000030338  foo
+# DYN-GROW-EMPTY:
+
+# DYN-GROW:      Hex dump of section '.dynamic':
+# DYN-GROW:      0x00020328 00000000 00000000 00000000 00000000
+# DYN-GROW-EMPTY:
+
+.data
+.balign 8
+foo:
+## Can stay in .relr.auth.dyn
+.quad foo at AUTH(da,42)
+## Will be moved to .rela.dyn
+.quad foo+0x100000000 at AUTH(da,42)
+
+#--- rela-iplt-end.s
+
+## See https://github.com/llvm/llvm-project/issues/171475
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 rela-iplt-end.s -o rela-iplt-end.o
+# RUN: ld.lld -static -z pack-relative-relocs rela-iplt-end.o -o rela-iplt-end
+# RUN: llvm-readelf -S -s rela-iplt-end | FileCheck --check-prefix=IPLT-END %s
+
+## Ensure that the end address covers 0x30 bytes for both relocations
+# IPLT-END:      .rela.dyn         RELA            00000000002001c8 0001c8 000030 18   A  0   0  8
+# IPLT-END:      00000000002001c8     0 NOTYPE  LOCAL  HIDDEN      1 __rela_iplt_start
+# IPLT-END-NEXT: 00000000002001f8     0 NOTYPE  LOCAL  HIDDEN      1 __rela_iplt_end
+
+adrp x0, __rela_iplt_start
+adrp x0, __rela_iplt_end
+
+.data
+.balign 8
+foo:
+## Will be moved to .rela.dyn
+.quad foo+0x100000000 at AUTH(da,42)
+
+## Extra relocation in a section with alignment 1 to force it into .rela.dyn
+## up-front.
+.section .data.rel.ro, "aw"
+.quad foo at AUTH(da,42)
+
+#--- rela-iplt-start.s
+
+## See https://github.com/llvm/llvm-project/issues/171475
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 rela-iplt-start.s -o rela-iplt-start.o
+# RUN: ld.lld -static -z pack-relative-relocs rela-iplt-start.o -o rela-iplt-start
+# RUN: llvm-readelf -S -s rela-iplt-start | FileCheck --check-prefix=IPLT-START %s
+
+## Ensure that the __rela_iplt* addresses are properly set given that initially .rela.dyn is empty (before moving relocs from .relr.auth.dyn)
+# IPLT-START:      .rela.dyn         RELA            0000000000200158 000158 000018 18   A  0   0  8
+# IPLT-START:      0000000000200158     0 NOTYPE  LOCAL  HIDDEN      1 __rela_iplt_start
+# IPLT-START-NEXT: 0000000000200170     0 NOTYPE  LOCAL  HIDDEN      1 __rela_iplt_end
+
+adrp x0, __rela_iplt_start
+adrp x0, __rela_iplt_end
+
+.data
+.balign 8
+foo:
+## Will be moved to .rela.dyn
+.quad foo+0x100000000 at AUTH(da,42)

>From da1f8ff77726bb4ffbe06b5354ee427ee4c0e878 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 18 May 2026 17:40:07 +0300
Subject: [PATCH 2/3] Address review comments

---
 lld/ELF/SyntheticSections.cpp      | 15 +++++----------
 lld/ELF/SyntheticSections.h        |  3 +--
 lld/ELF/Writer.cpp                 |  5 +++++
 lld/test/ELF/aarch64-reloc-pauth.s | 10 ++--------
 4 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 633966182e8cf..c4807e1e150b5 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1174,8 +1174,8 @@ static uint64_t addPltRelSz(Ctx &ctx) { return ctx.in.relaPlt->getSize(); }
 
 // Add remaining entries to complete .dynamic contents.
 template <class ELFT>
-std::vector<std::pair<int32_t, uint64_t>> DynamicSection<ELFT>::computeContents(
-    bool afterFinalizeAddressDependentContents) {
+std::vector<std::pair<int32_t, uint64_t>>
+DynamicSection<ELFT>::computeContents() {
   elf::Partition &part = getPartition(ctx);
   bool isMain = part.name.empty();
   std::vector<std::pair<int32_t, uint64_t>> entries;
@@ -1257,9 +1257,7 @@ std::vector<std::pair<int32_t, uint64_t>> DynamicSection<ELFT>::computeContents(
   if (!ctx.arg.shared && !ctx.arg.relocatable && !ctx.arg.zRodynamic)
     addInt(DT_DEBUG, 0);
 
-  if (part.relaDyn->isNeeded() ||
-      (!afterFinalizeAddressDependentContents && part.relrAuthDyn &&
-       part.relrAuthDyn->getParent() && !part.relrAuthDyn->relocs.empty())) {
+  if (part.relaDyn->isNeeded()) {
     addInSec(part.relaDyn->dynamicTag, *part.relaDyn);
     entries.emplace_back(part.relaDyn->sizeDynamicTag,
                          addRelaSz(ctx, *part.relaDyn));
@@ -1442,16 +1440,13 @@ std::vector<std::pair<int32_t, uint64_t>> DynamicSection<ELFT>::computeContents(
 template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
   if (OutputSection *sec = getPartition(ctx).dynStrTab->getParent())
     getParent()->link = sec->sectionIndex;
-  this->size =
-      computeContents(/*afterFinalizeAddressDependentContents=*/false).size() *
-      this->entsize;
+  this->size = computeContents().size() * this->entsize;
 }
 
 template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) {
   auto *p = reinterpret_cast<Elf_Dyn *>(buf);
 
-  for (std::pair<int32_t, uint64_t> kv :
-       computeContents(/*afterFinalizeAddressDependentContents=*/true)) {
+  for (std::pair<int32_t, uint64_t> kv : computeContents()) {
     p->d_tag = kv.first;
     p->d_un.d_val = kv.second;
     ++p;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index eee77cbf87148..92dcbb922aa58 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -483,8 +483,7 @@ template <class ELFT> class DynamicSection final : public SyntheticSection {
   size_t getSize() const override { return size; }
 
 private:
-  std::vector<std::pair<int32_t, uint64_t>>
-  computeContents(bool afterFinalizeAddressDependentContents);
+  std::vector<std::pair<int32_t, uint64_t>> computeContents();
 };
 
 class RelocationBaseSection : public SyntheticSection {
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 51fcbbf48a9e6..96852281ebb2f 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1592,6 +1592,11 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
         changed |= part.relrDyn->updateAllocSize(ctx);
       if (part.relrAuthDyn)
         changed |= part.relrAuthDyn->updateAllocSize(ctx);
+      if (part.relrAuthDyn && part.dynamic && part.dynamic->getParent()) {
+        size_t oldSize = part.dynamic->getSize();
+        finalizeSynthetic(ctx, part.dynamic.get());
+        changed |= (oldSize != part.dynamic->getSize());
+      }
       if (part.memtagGlobalDescriptors)
         changed |= part.memtagGlobalDescriptors->updateAllocSize(ctx);
       if (part.ehFrameHdr && part.ehFrameHdr->isNeeded())
diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 1b96bc7fc27df..300c134d05948 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -176,7 +176,7 @@
 
 # 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: 0000000000030350  0000000000000411 R_AARCH64_AUTH_RELATIVE           8003034f
+# 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: Index: Entry Address Symbolic Address
@@ -186,9 +186,6 @@
 ## empty for this test, this space is filled with NULL tags.
 # EMPTY-RELR:      Hex dump of section '.dynamic':
 # EMPTY-RELR:      0x00020310 00000000 00000000 00000000 00000000
-# EMPTY-RELR-NEXT: 0x00020320 00000000 00000000 00000000 00000000
-# EMPTY-RELR-NEXT: 0x00020330 00000000 00000000 00000000 00000000
-# EMPTY-RELR-NEXT: 0x00020340 00000000 00000000 00000000 00000000
 # EMPTY-RELR-EMPTY:
 
 .section .test, "aw"
@@ -230,16 +227,13 @@
 # EMPTY-RELA-EMPTY:
 # EMPTY-RELA-NEXT: Relocation section '.relr.auth.dyn' at offset {{.+}} contains 1 entries:
 # EMPTY-RELA-NEXT: Index: Entry Address Symbolic Address
-# EMPTY-RELA-NEXT: 0000: 0000000000030340 0000000000030340 $d
+# EMPTY-RELA-NEXT: 0000: 0000000000030310 0000000000030310 $d
 
 ## The .dynamic section has enough space pre-allocated for the case when both
 ## .rela.dyn and .relr.auth.dyn sections are present. Since .rela.dyn becomes
 ## empty for this test, this space is filled with NULL tags.
 # EMPTY-RELA:      Hex dump of section '.dynamic':
 # EMPTY-RELA:      0x00020300 00000000 00000000 00000000 00000000
-# EMPTY-RELA-NEXT: 0x00020310 00000000 00000000 00000000 00000000
-# EMPTY-RELA-NEXT: 0x00020320 00000000 00000000 00000000 00000000
-# EMPTY-RELA-NEXT: 0x00020330 00000000 00000000 00000000 00000000
 # EMPTY-RELA-EMPTY:
 
 # EMPTY-RELA-RO-NOT: .rela.dyn

>From 4176fb6ee0b8c5891c15e5a2bdc2ce4fb6d01301 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 1 Jun 2026 12:47:15 +0300
Subject: [PATCH 3/3] Address review comments

---
 lld/test/ELF/aarch64-reloc-pauth.s | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/lld/test/ELF/aarch64-reloc-pauth.s b/lld/test/ELF/aarch64-reloc-pauth.s
index 300c134d05948..708fffd7aba75 100644
--- a/lld/test/ELF/aarch64-reloc-pauth.s
+++ b/lld/test/ELF/aarch64-reloc-pauth.s
@@ -248,7 +248,6 @@
 ## If some relocations are moved to the previously empty .rela.dyn and some stay
 ## in .relr.auth.dyn, the dynamic section needs contain tags for both these
 ## sections and have enough space for storing these tags.
-## See also https://github.com/llvm/llvm-project/issues/171475
 
 # RUN: llvm-mc -filetype=obj -triple=aarch64 dynamic-section-growth.s -o dynamic-section-growth.o
 # RUN: ld.lld -shared -z pack-relative-relocs dynamic-section-growth.o -o dynamic-section-growth.so
@@ -292,13 +291,11 @@ foo:
 
 #--- rela-iplt-end.s
 
-## See https://github.com/llvm/llvm-project/issues/171475
-
 # RUN: llvm-mc -filetype=obj -triple=aarch64 rela-iplt-end.s -o rela-iplt-end.o
-# RUN: ld.lld -static -z pack-relative-relocs rela-iplt-end.o -o rela-iplt-end
+# RUN: ld.lld -z pack-relative-relocs rela-iplt-end.o -o rela-iplt-end
 # RUN: llvm-readelf -S -s rela-iplt-end | FileCheck --check-prefix=IPLT-END %s
 
-## Ensure that the end address covers 0x30 bytes for both relocations
+## Ensure that the end address covers 0x30 bytes for both relocations.
 # IPLT-END:      .rela.dyn         RELA            00000000002001c8 0001c8 000030 18   A  0   0  8
 # IPLT-END:      00000000002001c8     0 NOTYPE  LOCAL  HIDDEN      1 __rela_iplt_start
 # IPLT-END-NEXT: 00000000002001f8     0 NOTYPE  LOCAL  HIDDEN      1 __rela_iplt_end
@@ -312,20 +309,17 @@ foo:
 ## Will be moved to .rela.dyn
 .quad foo+0x100000000 at AUTH(da,42)
 
-## Extra relocation in a section with alignment 1 to force it into .rela.dyn
-## up-front.
+## Extra relocation in a section with alignment 1 to force it into .rela.dyn up-front.
 .section .data.rel.ro, "aw"
 .quad foo at AUTH(da,42)
 
 #--- rela-iplt-start.s
 
-## See https://github.com/llvm/llvm-project/issues/171475
-
 # RUN: llvm-mc -filetype=obj -triple=aarch64 rela-iplt-start.s -o rela-iplt-start.o
-# RUN: ld.lld -static -z pack-relative-relocs rela-iplt-start.o -o rela-iplt-start
+# RUN: ld.lld -z pack-relative-relocs rela-iplt-start.o -o rela-iplt-start
 # RUN: llvm-readelf -S -s rela-iplt-start | FileCheck --check-prefix=IPLT-START %s
 
-## Ensure that the __rela_iplt* addresses are properly set given that initially .rela.dyn is empty (before moving relocs from .relr.auth.dyn)
+## Ensure that the __rela_iplt* addresses are properly set given that initially .rela.dyn is empty (before moving relocs from .relr.auth.dyn).
 # IPLT-START:      .rela.dyn         RELA            0000000000200158 000158 000018 18   A  0   0  8
 # IPLT-START:      0000000000200158     0 NOTYPE  LOCAL  HIDDEN      1 __rela_iplt_start
 # IPLT-START-NEXT: 0000000000200170     0 NOTYPE  LOCAL  HIDDEN      1 __rela_iplt_end



More information about the llvm-commits mailing list