[ELF] Always separate relative relocations regardless of -z combreloc (#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.
This commit is contained in:
Fangrui Song 2026-03-22 20:22:44 -07:00 committed by GitHub
parent 076226f378
commit dc4df5da88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 17 deletions

View File

@ -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;

View File

@ -495,7 +495,7 @@ public:
/// 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);

View File

@ -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