[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