[llvm-branch-commits] [lld] [ELF] Include sharded relocations in RelocationBaseSection::getSize (PR #173285)
Jessica Clarke via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Dec 24 03:04:33 PST 2025
https://github.com/jrtc27 updated https://github.com/llvm/llvm-project/pull/173285
>From b65b9570750b44e565a078fd92adca971515679a Mon Sep 17 00:00:00 2001
From: Jessica Clarke <jrtc27 at jrtc27.com>
Date: Mon, 22 Dec 2025 17:08:05 +0000
Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
=?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5
---
lld/ELF/SyntheticSections.h | 7 ++++++-
lld/test/ELF/aarch64-pauth-rela-iplt-end.s | 20 ++++++++++++++++++++
2 files changed, 26 insertions(+), 1 deletion(-)
create mode 100644 lld/test/ELF/aarch64-pauth-rela-iplt-end.s
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 16bdda8ef75bb..47d87e76357f3 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -528,7 +528,12 @@ class RelocationBaseSection : public SyntheticSection {
return !relocs.empty() ||
llvm::any_of(relocsVec, [](auto &v) { return !v.empty(); });
}
- size_t getSize() const override { return relocs.size() * this->entsize; }
+ size_t getSize() const override {
+ size_t count = relocs.size();
+ for (const auto &v : relocsVec)
+ count += v.size();
+ return count * this->entsize;
+ }
size_t getRelativeRelocCount() const { return numRelativeRelocs; }
void mergeRels();
void partitionRels();
diff --git a/lld/test/ELF/aarch64-pauth-rela-iplt-end.s b/lld/test/ELF/aarch64-pauth-rela-iplt-end.s
new file mode 100644
index 0000000000000..b2c7fe0c61c99
--- /dev/null
+++ b/lld/test/ELF/aarch64-pauth-rela-iplt-end.s
@@ -0,0 +1,20 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: ld.lld --static %t.o -o %t
+# RUN: llvm-readelf -S -s -d %t | FileCheck %s
+
+## Verify that R_AARCH64_AUTH_RELATIVE relocations are included within the
+## bounds of __rela_iplt_start/end, as relative relocations still emitted for
+## static PDEs due to needing run-time signing. Historically this would not be
+## the case if added to .rela.dyn with sharding.
+
+# CHECK: .rela.dyn RELA 0000000000200158 000158 000018 18 A 0 0 8
+# CHECK: 0000000000200158 0 NOTYPE LOCAL HIDDEN 1 __rela_iplt_start
+# CHECK: 0000000000200170 0 NOTYPE LOCAL HIDDEN 1 __rela_iplt_end
+
+adrp x0, __rela_iplt_start
+adrp x0, __rela_iplt_end
+
+.data
+foo:
+.quad foo at AUTH(da,42)
>From 53daf0e1f0be9ee5a218ea8b39f7ee6268b2e2ab Mon Sep 17 00:00:00 2001
From: Jessica Clarke <jrtc27 at jrtc27.com>
Date: Wed, 24 Dec 2025 10:54:41 +0000
Subject: [PATCH 2/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
=?UTF-8?q?anges=20introduced=20through=20rebase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5
[skip ci]
---
lld/ELF/Relocations.cpp | 47 ++++++++++++++++-------------------
lld/ELF/SyntheticSections.cpp | 6 ++++-
lld/ELF/SyntheticSections.h | 32 +++++++++++++++++++++---
lld/ELF/Writer.cpp | 17 +++----------
4 files changed, 58 insertions(+), 44 deletions(-)
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 5c23c76c80f9e..d60216da2b03f 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -705,39 +705,36 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
RelExpr expr, RelType type) {
Partition &part = isec.getPartition(ctx);
- if (sym.isTagged()) {
- part.relaDyn->addRelativeReloc<shard>(ctx.target->relativeRel, isec,
- offsetInSec, sym, addend, type, expr);
- // With MTE globals, we always want to derive the address tag by `ldg`-ing
- // the symbol. When we have a RELATIVE relocation though, we no longer have
- // a reference to the symbol. Because of this, when we have an addend that
- // puts the result of the RELATIVE relocation out-of-bounds of the symbol
- // (e.g. the addend is outside of [0, sym.getSize()]), the AArch64 MemtagABI
- // says we should store the offset to the start of the symbol in the target
- // field. This is described in further detail in:
- // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#841extended-semantics-of-r_aarch64_relative
- if (addend < 0 || static_cast<uint64_t>(addend) >= sym.getSize())
- isec.relocations.push_back({R_ADDEND_NEG, type, offsetInSec, addend, &sym});
- return;
- }
-
// Add a relative relocation. If relrDyn section is enabled, and the
// relocation offset is guaranteed to be even, add the relocation to
// the relrDyn section, otherwise add it to the relaDyn section.
// relrDyn sections don't support odd offsets. Also, relrDyn sections
// don't store the addend values, so we must write it to the relocated
// address.
- if (part.relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
- isec.addReloc({expr, type, offsetInSec, addend, &sym});
- if (shard)
- part.relrDyn->relocsVec[parallel::getThreadIndex()].push_back(
- {&isec, isec.relocs().size() - 1});
- else
- part.relrDyn->relocs.push_back({&isec, isec.relocs().size() - 1});
+ //
+ // MTE globals may need to store the original addend as well so cannot use
+ // relrDyn. TODO: It should be unambiguous when not using R_ADDEND_NEG below?
+ RelrBaseSection *relrDyn = part.relrDyn.get();
+ if (sym.isTagged())
+ relrDyn = nullptr;
+ if (relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
+ relrDyn->addRelativeReloc<shard>(isec, offsetInSec, sym, addend, type,
+ expr);
return;
}
part.relaDyn->addRelativeReloc<shard>(ctx.target->relativeRel, isec,
offsetInSec, sym, addend, type, expr);
+ // With MTE globals, we always want to derive the address tag by `ldg`-ing
+ // the symbol. When we have a RELATIVE relocation though, we no longer have
+ // a reference to the symbol. Because of this, when we have an addend that
+ // puts the result of the RELATIVE relocation out-of-bounds of the symbol
+ // (e.g. the addend is outside of [0, sym.getSize()]), the AArch64 MemtagABI
+ // says we should store the offset to the start of the symbol in the target
+ // field. This is described in further detail in:
+ // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#841extended-semantics-of-r_aarch64_relative
+ if (sym.isTagged() &&
+ (addend < 0 || static_cast<uint64_t>(addend) >= sym.getSize()))
+ isec.addReloc({R_ADDEND_NEG, type, offsetInSec, addend, &sym});
}
template <class PltSection, class GotPltSection>
@@ -1014,8 +1011,8 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
// When symbol values are determined in
// finalizeAddressDependentContent, some .relr.auth.dyn relocations
// may be moved to .rela.dyn.
- sec->addReloc({expr, type, offset, addend, &sym});
- part.relrAuthDyn->relocs.push_back({sec, sec->relocs().size() - 1});
+ part.relrAuthDyn->addRelativeReloc(*sec, offset, sym, addend, type,
+ expr);
} else {
part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, false,
sym, addend, R_ABS});
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 1e9d44fa37bea..c81f649861a73 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -674,7 +674,6 @@ GotSection::GotSection(Ctx &ctx)
numEntries = ctx.target->gotHeaderEntriesNum;
}
-void GotSection::addConstant(const Relocation &r) { relocations.push_back(r); }
void GotSection::addEntry(const Symbol &sym) {
assert(sym.auxIdx == ctx.symAux.size() - 1);
ctx.symAux.back().gotIdx = numEntries++;
@@ -1708,6 +1707,9 @@ void RelocationBaseSection::partitionRels() {
}
void RelocationBaseSection::finalizeContents() {
+ mergeRels();
+ // Compute DT_RELACOUNT to be used by part.dynamic.
+ partitionRels();
SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
// When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE
@@ -1797,6 +1799,8 @@ void RelrBaseSection::mergeRels() {
relocsVec.clear();
}
+void RelrBaseSection::finalizeContents() { mergeRels(); }
+
template <class ELFT>
AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection(
Ctx &ctx, StringRef name, unsigned concurrency)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 16bdda8ef75bb..8971d5f6c2349 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -113,7 +113,7 @@ class GotSection final : public SyntheticSection {
bool isNeeded() const override;
void writeTo(uint8_t *buf) override;
- void addConstant(const Relocation &r);
+ void addConstant(const Relocation &r) { addReloc(r); }
void addEntry(const Symbol &sym);
void addAuthEntry(const Symbol &sym);
bool addTlsDescEntry(const Symbol &sym);
@@ -530,14 +530,14 @@ class RelocationBaseSection : public SyntheticSection {
}
size_t getSize() const override { return relocs.size() * this->entsize; }
size_t getRelativeRelocCount() const { return numRelativeRelocs; }
- void mergeRels();
- void partitionRels();
void finalizeContents() override;
int32_t dynamicTag, sizeDynamicTag;
SmallVector<DynamicReloc, 0> relocs;
protected:
+ void mergeRels();
+ void partitionRels();
void computeRels();
// Used when parallel relocation scanning adds relocations. The elements
// will be moved into relocs by mergeRel().
@@ -592,15 +592,39 @@ struct RelativeReloc {
class RelrBaseSection : public SyntheticSection {
public:
RelrBaseSection(Ctx &, unsigned concurrency, bool isAArch64Auth = false);
- void mergeRels();
+ /// Add a dynamic relocation without writing an addend to the output section.
+ /// This overload can be used if the addends are written directly instead of
+ /// using relocations on the input section.
+ template <bool shard = false> void addReloc(const RelativeReloc &reloc) {
+ relocs.push_back(reloc);
+ }
+ /// Add a relative dynamic relocation that uses the target address of \p sym
+ /// (i.e. InputSection::getRelocTargetVA()) + \p addend as the addend.
+ template <bool shard = false>
+ void addRelativeReloc(InputSectionBase &isec, uint64_t offsetInSec,
+ Symbol &sym, int64_t addend, RelType addendRelType,
+ RelExpr expr) {
+ assert(expr != R_ADDEND && "expected non-addend relocation expression");
+ isec.addReloc({expr, addendRelType, offsetInSec, addend, &sym});
+ addReloc<shard>({&isec, isec.relocs().size() - 1});
+ }
bool isNeeded() const override {
return !relocs.empty() ||
llvm::any_of(relocsVec, [](auto &v) { return !v.empty(); });
}
+ void finalizeContents() override;
SmallVector<RelativeReloc, 0> relocs;
+
+protected:
+ void mergeRels();
SmallVector<SmallVector<RelativeReloc, 0>, 0> relocsVec;
};
+template <>
+inline void RelrBaseSection::addReloc<true>(const RelativeReloc &reloc) {
+ relocsVec[llvm::parallel::getThreadIndex()].push_back(reloc);
+}
+
// RelrSection is used to encode offsets for relative relocations.
// Proposal for adding SHT_RELR sections to generic-abi is here:
// https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index db5626e701ad6..57202f42cce5b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2111,20 +2111,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Dynamic section must be the last one in this list and dynamic
// symbol table section (dynSymTab) must be the first one.
for (Partition &part : ctx.partitions) {
- if (part.relaDyn) {
- part.relaDyn->mergeRels();
- // Compute DT_RELACOUNT to be used by part.dynamic.
- part.relaDyn->partitionRels();
- finalizeSynthetic(ctx, part.relaDyn.get());
- }
- if (part.relrDyn) {
- part.relrDyn->mergeRels();
- finalizeSynthetic(ctx, part.relrDyn.get());
- }
- if (part.relrAuthDyn) {
- part.relrAuthDyn->mergeRels();
- finalizeSynthetic(ctx, part.relrAuthDyn.get());
- }
+ finalizeSynthetic(ctx, part.relaDyn.get());
+ finalizeSynthetic(ctx, part.relrDyn.get());
+ finalizeSynthetic(ctx, part.relrAuthDyn.get());
finalizeSynthetic(ctx, part.dynSymTab.get());
finalizeSynthetic(ctx, part.gnuHashTab.get());
More information about the llvm-branch-commits
mailing list