[lld] [ELF] Always separate relative relocations regardless of -z combreloc (PR #187964)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun Mar 22 20:09:21 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/187964
Remove the combreloc guard from addReloc and mergeRels so that
relative relocations are always routed to relativeRelocs, even with -z
nocombreloc or --pack-dyn-relocs=android.
Update AndroidPackedRelocationSection::updateAllocSize to iterate
both relativeRelocs and relocs.
>From 56aab5f58d35f7a725211d95f137611e30d61c4e Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 22 Mar 2026 16:38:52 -0700
Subject: [PATCH] [ELF] Always separate relative relocations regardless of -z
combreloc
Remove the combreloc guard from addReloc and mergeRels so that
relative relocations are always routed to relativeRelocs, even with -z
nocombreloc or --pack-dyn-relocs=android.
Update AndroidPackedRelocationSection::updateAllocSize to iterate
both relativeRelocs and relocs.
---
lld/ELF/SyntheticSections.cpp | 31 ++++++++++++++++---------------
lld/ELF/SyntheticSections.h | 2 +-
lld/test/ELF/combreloc.s | 2 +-
3 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 38d9eeacf0cf6..8157365f89b30 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1519,9 +1519,11 @@ void RelocationBaseSection::mergeRels() {
void RelocationBaseSection::finalizeContents() {
mergeRels();
- // Cache the count for DT_RELACOUNT. This must not change after
- // DynamicSection::finalizeContents sizes the .dynamic section.
- numRelativeRelocs = relativeRelocs.size();
+ // Cache the count for DT_RELACOUNT. DynamicSection<ELFT>::computeContents
+ // uses ctx.arg.zCombreloc (not the per-section combreloc) to decide whether
+ // to emit DT_RELACOUNT, so this must match.
+ if (combreloc)
+ numRelativeRelocs = relativeRelocs.size();
SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
// When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE
@@ -1685,23 +1687,22 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
// The format header includes the number of relocations and the initial
// offset (we set this to zero because the first relocation group will
// perform the initial adjustment).
- add(relocs.size());
+ add(relativeRelocs.size() + relocs.size());
add(0);
- std::vector<Elf_Rela> relatives, nonRelatives;
-
- for (const DynamicReloc &rel : relocs) {
+ SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
+ auto makeRela = [&](const DynamicReloc &rel) {
Elf_Rela r;
r.r_offset = rel.getOffset();
- r.setSymbolAndType(rel.getSymIndex(getPartition(ctx).dynSymTab.get()),
- rel.type, false);
+ r.setSymbolAndType(rel.getSymIndex(symTab), rel.type, false);
r.r_addend = ctx.arg.isRela ? rel.computeAddend(ctx) : 0;
-
- if (r.getType(ctx.arg.isMips64EL) == ctx.target->relativeRel)
- relatives.push_back(r);
- else
- nonRelatives.push_back(r);
- }
+ return r;
+ };
+ std::vector<Elf_Rela> relatives, nonRelatives;
+ for (const DynamicReloc &rel : relativeRelocs)
+ relatives.push_back(makeRela(rel));
+ for (const DynamicReloc &rel : relocs)
+ nonRelatives.push_back(makeRela(rel));
llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) {
return a.r_offset < b.r_offset;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 0373518ecd421..92dcbb922aa58 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -495,7 +495,7 @@ class RelocationBaseSection : public SyntheticSection {
/// This overload can be used if the addends are written directly instead of
/// using relocations on the input section (e.g. MipsGotSection::writeTo()).
template <bool shard = false> void addReloc(const DynamicReloc &reloc) {
- if (combreloc && reloc.type == relativeRel)
+ if (reloc.type == relativeRel)
relativeRelocs.push_back(reloc);
else
relocs.push_back(reloc);
diff --git a/lld/test/ELF/combreloc.s b/lld/test/ELF/combreloc.s
index 59dedceb633fc..08e404c66676e 100644
--- a/lld/test/ELF/combreloc.s
+++ b/lld/test/ELF/combreloc.s
@@ -31,12 +31,12 @@
# NOCOMB-NOT: RELACOUNT
# NOCOMB: Relocations [
# NOCOMB-NEXT: Section ({{.*}}) .rela.dyn {
+# NOCOMB-NEXT: 0x3418 R_X86_64_RELATIVE - 0x3420
# NOCOMB-NEXT: 0x33F8 R_X86_64_64 aaa 0x0
# NOCOMB-NEXT: 0x3400 R_X86_64_64 ccc 0x0
# NOCOMB-NEXT: 0x3408 R_X86_64_64 bbb 0x0
# NOCOMB-NEXT: 0x3410 R_X86_64_64 aaa 0x0
# NOCOMB-NEXT: 0x23F0 R_X86_64_GLOB_DAT aaa 0x0
-# NOCOMB-NEXT: 0x3418 R_X86_64_RELATIVE - 0x3420
# NOCOMB-NEXT: }
.globl aaa, bbb, ccc
More information about the llvm-commits
mailing list