From 98164d4706115b3ed850be84bb4647c56d2b2eaf Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 12 Aug 2025 22:18:15 -0700 Subject: [PATCH] Revert "[ELF] -r: Synthesize R_RISCV_ALIGN at input section start" (#151639) This reverts commit 6f53f1c8d2bdd13e30da7d1b85ed6a3ae4c4a856. synthesiedAligns is not cleared, leading to stray relocations for unrelated sections. Revert for now. --- lld/ELF/Arch/RISCV.cpp | 124 ----------------------- lld/ELF/LinkerScript.cpp | 14 +-- lld/ELF/OutputSections.cpp | 14 +-- lld/ELF/Target.h | 3 - lld/test/ELF/riscv-relocatable-align.s | 130 ------------------------- 5 files changed, 4 insertions(+), 281 deletions(-) delete mode 100644 lld/test/ELF/riscv-relocatable-align.s diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 71201b0e1604..ba0584bb1799 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -45,21 +45,7 @@ public: uint64_t val) const override; void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; bool relaxOnce(int pass) const override; - template - bool synthesizeAlignForInput(uint64_t &dot, InputSection *sec, - Relocs rels); - template - void finalizeSynthesizeAligns(uint64_t &dot, InputSection *sec, - Relocs rels); - template - bool synthesizeAlignAux(uint64_t &dot, InputSection *sec); - bool synthesizeAlign(uint64_t &dot, InputSection *sec) override; void finalizeRelax(int passes) const override; - - // The following two variables are used by synthesized ALIGN relocations. - InputSection *baseSec = nullptr; - // r_offset and r_addend pairs. - SmallVector, 0> synthesizedAligns; }; } // end anonymous namespace @@ -970,116 +956,6 @@ bool RISCV::relaxOnce(int pass) const { return changed; } -// If the section alignment is >= 4, advance `dot` to insert NOPs and synthesize -// an ALIGN relocation. Otherwise, return false to use default handling. -template -bool RISCV::synthesizeAlignForInput(uint64_t &dot, InputSection *sec, - Relocs rels) { - if (!baseSec) { - // Record the first input section with RELAX relocations. We will synthesize - // ALIGN relocations here. - for (auto rel : rels) { - if (rel.getType(false) == R_RISCV_RELAX) { - baseSec = sec; - break; - } - } - } else if (sec->addralign >= 4) { - // If the alignment is >= 4 and the section does not start with an ALIGN - // relocation, synthesize one. - bool hasAlignRel = llvm::any_of(rels, [](const RelTy &rel) { - return rel.r_offset == 0 && rel.getType(false) == R_RISCV_ALIGN; - }); - if (!hasAlignRel) { - synthesizedAligns.emplace_back(dot - baseSec->getVA(), - sec->addralign - 2); - dot += sec->addralign - 2; - return true; - } - } - return false; -} - -// Finalize the relocation section by appending synthesized ALIGN relocations -// after processing all input sections. -template -void RISCV::finalizeSynthesizeAligns(uint64_t &dot, InputSection *sec, - Relocs rels) { - auto *f = cast>(baseSec->file); - auto shdr = f->template getELFShdrs()[baseSec->relSecIdx]; - // Create a copy of InputSection. - sec = make(*f, shdr, baseSec->name); - auto *baseRelSec = cast(f->getSections()[baseSec->relSecIdx]); - *sec = *baseRelSec; - baseSec = nullptr; - - // Allocate buffer for original and synthesized relocations in RELA format. - // If CREL is used, OutputSection::finalizeNonAllocCrel will convert RELA to - // CREL. - auto newSize = rels.size() + synthesizedAligns.size(); - auto *relas = makeThreadLocalN(newSize); - sec->size = newSize * sizeof(typename ELFT::Rela); - sec->content_ = reinterpret_cast(relas); - sec->type = SHT_RELA; - // Copy original relocations to the new buffer, potentially converting CREL to - // RELA. - for (auto [i, r] : llvm::enumerate(rels)) { - relas[i].r_offset = r.r_offset; - relas[i].setSymbolAndType(r.getSymbol(0), r.getType(0), false); - if constexpr (RelTy::HasAddend) - relas[i].r_addend = r.r_addend; - } - // Append synthesized ALIGN relocations to the buffer. - for (auto [i, r] : llvm::enumerate(synthesizedAligns)) { - auto &rela = relas[rels.size() + i]; - rela.r_offset = r.first; - rela.setSymbolAndType(0, R_RISCV_ALIGN, false); - rela.r_addend = r.second; - } - // Replace the old relocation section with the new one in the output section. - // addOrphanSections ensures that the output relocation section is processed - // after osec. - for (SectionCommand *cmd : sec->getParent()->commands) { - auto *isd = dyn_cast(cmd); - if (!isd) - continue; - for (auto *&isec : isd->sections) - if (isec == baseRelSec) - isec = sec; - } -} - -template -bool RISCV::synthesizeAlignAux(uint64_t &dot, InputSection *sec) { - bool ret = false; - if (sec) { - invokeOnRelocs(*sec, ret = synthesizeAlignForInput, dot, sec); - } else if (baseSec) { - invokeOnRelocs(*baseSec, finalizeSynthesizeAligns, dot, sec); - } - return ret; -} - -// Without linker relaxation enabled for a particular relocatable file or -// section, the assembler will not generate R_RISCV_ALIGN relocations for -// alignment directives. This becomes problematic in a two-stage linking -// process: ld -r a.o b.o -o ab.o; ld ab.o -o ab. This function synthesizes an -// R_RISCV_ALIGN relocation at section start when needed. -// -// When called with an input section (`sec` is not null): If the section -// alignment is >= 4, advance `dot` to insert NOPs and synthesize an ALIGN -// relocation. -// -// When called after all input sections are processed (`sec` is null): The -// output relocation section is updated with all the newly synthesized ALIGN -// relocations. -bool RISCV::synthesizeAlign(uint64_t &dot, InputSection *sec) { - assert(ctx.arg.relocatable); - if (ctx.arg.is64) - return synthesizeAlignAux(dot, sec); - return synthesizeAlignAux(dot, sec); -} - void RISCV::finalizeRelax(int passes) const { llvm::TimeTraceScope timeScope("Finalize RISC-V relaxation"); Log(ctx) << "relaxation passes: " << passes; diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index e9ce4e26f3ed..a5d08f4979da 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -1230,9 +1230,6 @@ bool LinkerScript::assignOffsets(OutputSection *sec) { if (sec->firstInOverlay) state->overlaySize = 0; - bool synthesizeAlign = ctx.arg.relocatable && ctx.arg.relax && - (sec->flags & SHF_EXECINSTR) && - ctx.arg.emachine == EM_RISCV; // We visited SectionsCommands from processSectionCommands to // layout sections. Now, we visit SectionsCommands again to fix // section offsets. @@ -1263,10 +1260,7 @@ bool LinkerScript::assignOffsets(OutputSection *sec) { if (isa(isec)) continue; const uint64_t pos = dot; - // If synthesized ALIGN may be needed, call maybeSynthesizeAlign and - // disable the default handling if the return value is true. - if (!(synthesizeAlign && ctx.target->synthesizeAlign(dot, isec))) - dot = alignToPowerOf2(dot, isec->addralign); + dot = alignToPowerOf2(dot, isec->addralign); isec->outSecOff = dot - sec->addr; dot += isec->getSize(); @@ -1282,12 +1276,6 @@ bool LinkerScript::assignOffsets(OutputSection *sec) { if (ctx.in.relroPadding && sec == ctx.in.relroPadding->getParent()) expandOutputSection(alignToPowerOf2(dot, ctx.arg.commonPageSize) - dot); - if (synthesizeAlign) { - const uint64_t pos = dot; - ctx.target->synthesizeAlign(dot, nullptr); - expandOutputSection(dot - pos); - } - // Non-SHF_ALLOC sections do not affect the addresses of other OutputSections // as they are not part of the process image. if (!(sec->flags & SHF_ALLOC)) { diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 0b50f6d68ce5..1020dd9f2569 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -889,17 +889,9 @@ void OutputSection::sortInitFini() { std::array OutputSection::getFiller(Ctx &ctx) { if (filler) return *filler; - if (!(flags & SHF_EXECINSTR)) - return {0, 0, 0, 0}; - if (ctx.arg.relocatable && ctx.arg.emachine == EM_RISCV) { - // See RISCV::maybeSynthesizeAlign: Synthesized NOP bytes and ALIGN - // relocations might be needed between two input sections. Use a NOP for the - // filler. - if (ctx.arg.eflags & EF_RISCV_RVC) - return {1, 0, 1, 0}; - return {0x13, 0, 0, 0}; - } - return ctx.target->trapInstr; + if (flags & SHF_EXECINSTR) + return ctx.target->trapInstr; + return {0, 0, 0, 0}; } void OutputSection::checkDynRelAddends(Ctx &ctx) { diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index e121fa1183e9..fdc0c20f9cd0 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -96,9 +96,6 @@ public: // Do a linker relaxation pass and return true if we changed something. virtual bool relaxOnce(int pass) const { return false; } - virtual bool synthesizeAlign(uint64_t &dot, InputSection *sec) { - return false; - } // Do finalize relaxation after collecting relaxation infos. virtual void finalizeRelax(int passes) const {} diff --git a/lld/test/ELF/riscv-relocatable-align.s b/lld/test/ELF/riscv-relocatable-align.s deleted file mode 100644 index 9a782ed47850..000000000000 --- a/lld/test/ELF/riscv-relocatable-align.s +++ /dev/null @@ -1,130 +0,0 @@ -# RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax a.s -o ac.o -# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax b.s -o bc.o -# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax b1.s -o b1c.o -# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax c.s -o cc.o -# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c d.s -o dc.o - -## No RELAX. Don't synthesize ALIGN. -# RUN: ld.lld -r bc.o dc.o -o bd.ro -# RUN: llvm-readelf -r bd.ro | FileCheck %s --check-prefix=NOREL - -# NOREL: no relocations - -# RUN: ld.lld -r bc.o bc.o ac.o bc.o b1c.o cc.o dc.o -o out.ro -# RUN: llvm-objdump -dr -M no-aliases out.ro | FileCheck %s - -# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax a.s -o a.o -# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax b.s -o b.o -# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax d.s -o d.o -# RUN: ld.lld -r a.o b.o d.o -o out0.ro -# RUN: ld.lld -Ttext=0x10000 out0.ro -o out0 -# RUN: llvm-objdump -dr -M no-aliases out0 | FileCheck %s --check-prefix=CHECK1 - -# CHECK: : -# CHECK-NEXT: 0: 00158513 addi a0, a1, 0x1 -# CHECK-NEXT: 4: 0001 c.nop -# CHECK-NEXT: 6: 0001 c.nop -# CHECK-EMPTY: -# CHECK-NEXT: : -# CHECK-NEXT: 8: 00158513 addi a0, a1, 0x1 -# CHECK-EMPTY: -# CHECK-NEXT: <_start>: -# CHECK-NEXT: c: 00000097 auipc ra, 0x0 -# CHECK-NEXT: 000000000000000c: R_RISCV_CALL_PLT foo -# CHECK-NEXT: 000000000000000c: R_RISCV_RELAX *ABS* -# CHECK-NEXT: 10: 000080e7 jalr ra, 0x0(ra) <_start> -# CHECK-NEXT: 14: 0001 c.nop -# CHECK-NEXT: 0000000000000014: R_RISCV_ALIGN *ABS*+0x6 -# CHECK-NEXT: 16: 0001 c.nop -# CHECK-NEXT: 18: 0001 c.nop -# CHECK-EMPTY: -# CHECK-NEXT: : -# CHECK-NEXT: 1a: 00158513 addi a0, a1, 0x1 -# CHECK-NEXT: 1e: 0001 c.nop -# CHECK-NEXT: 20: 0001 c.nop -# CHECK-NEXT: 0000000000000020: R_RISCV_ALIGN *ABS*+0x6 -# CHECK-NEXT: 22: 0001 c.nop -# CHECK-NEXT: 24: 00000013 addi zero, zero, 0x0 -# CHECK-EMPTY: -# CHECK-NEXT: : -# CHECK-NEXT: 28: 00158513 addi a0, a1, 0x1 -# CHECK-EMPTY: -# CHECK-NEXT: : -# CHECK-NEXT: 2c: 00000097 auipc ra, 0x0 -# CHECK-NEXT: 000000000000002c: R_RISCV_CALL_PLT foo -# CHECK-NEXT: 000000000000002c: R_RISCV_RELAX *ABS* -# CHECK-NEXT: 30: 000080e7 jalr ra, 0x0(ra) -# CHECK-NEXT: 34: 0001 c.nop -# CHECK-NEXT: 0000000000000034: R_RISCV_ALIGN *ABS*+0x2 -# CHECK-EMPTY: -# CHECK-NEXT: : -# CHECK-NEXT: 36: 00258513 addi a0, a1, 0x2 - -# CHECK1: <_start>: -# CHECK1-NEXT: 010000ef jal ra, 0x10010 -# CHECK1-NEXT: 00000013 addi zero, zero, 0x0 -# CHECK1-EMPTY: -# CHECK1-NEXT: : -# CHECK1-NEXT: 00158513 addi a0, a1, 0x1 -# CHECK1-EMPTY: -# CHECK1-NEXT: : -# CHECK1-NEXT: 00258513 addi a0, a1, 0x2 - -## Test CREL. -# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax --crel a.s -o acrel.o -# RUN: ld.lld -r acrel.o bc.o -o out1.ro -# RUN: llvm-objdump -dr -M no-aliases out1.ro | FileCheck %s --check-prefix=CHECK2 - -# CHECK2: <_start>: -# CHECK2-NEXT: 0: 00000097 auipc ra, 0x0 -# CHECK2-NEXT: 0000000000000000: R_RISCV_CALL_PLT foo -# CHECK2-NEXT: 0000000000000000: R_RISCV_RELAX *ABS* -# CHECK2-NEXT: 4: 000080e7 jalr ra, 0x0(ra) <_start> -# CHECK2-NEXT: 8: 0001 c.nop -# CHECK2-NEXT: 0000000000000008: R_RISCV_ALIGN *ABS*+0x6 -# CHECK2-NEXT: a: 0001 c.nop -# CHECK2-NEXT: c: 0001 c.nop -# CHECK2-EMPTY: -# CHECK2-NEXT: : -# CHECK2-NEXT: e: 00158513 addi a0, a1, 0x1 - -#--- a.s -.globl _start -_start: - call foo - -.section .text1,"ax" -.globl foo -foo: - -#--- b.s -## Needs synthesized ALIGN -.option push -.option norelax -.balign 8 -b0: - addi a0, a1, 1 -.option pop - -#--- b1.s -.option push -.option norelax - .reloc ., R_RISCV_ALIGN, 6 - addi x0, x0, 0 - c.nop -.balign 8 -b0: - addi a0, a1, 1 -.option pop - -#--- c.s -.balign 2 -c0: - call foo - -#--- d.s -## Needs synthesized ALIGN -.balign 4 -d0: - addi a0, a1, 2