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.
This commit is contained in:
parent
856290d1c1
commit
98164d4706
@ -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 <class ELFT, class RelTy>
|
||||
bool synthesizeAlignForInput(uint64_t &dot, InputSection *sec,
|
||||
Relocs<RelTy> rels);
|
||||
template <class ELFT, class RelTy>
|
||||
void finalizeSynthesizeAligns(uint64_t &dot, InputSection *sec,
|
||||
Relocs<RelTy> rels);
|
||||
template <class ELFT>
|
||||
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<std::pair<uint64_t, uint64_t>, 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 <class ELFT, class RelTy>
|
||||
bool RISCV::synthesizeAlignForInput(uint64_t &dot, InputSection *sec,
|
||||
Relocs<RelTy> 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 <class ELFT, class RelTy>
|
||||
void RISCV::finalizeSynthesizeAligns(uint64_t &dot, InputSection *sec,
|
||||
Relocs<RelTy> rels) {
|
||||
auto *f = cast<ObjFile<ELFT>>(baseSec->file);
|
||||
auto shdr = f->template getELFShdrs<ELFT>()[baseSec->relSecIdx];
|
||||
// Create a copy of InputSection.
|
||||
sec = make<InputSection>(*f, shdr, baseSec->name);
|
||||
auto *baseRelSec = cast<InputSection>(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<typename ELFT::Rela>(newSize);
|
||||
sec->size = newSize * sizeof(typename ELFT::Rela);
|
||||
sec->content_ = reinterpret_cast<uint8_t *>(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<InputSectionDescription>(cmd);
|
||||
if (!isd)
|
||||
continue;
|
||||
for (auto *&isec : isd->sections)
|
||||
if (isec == baseRelSec)
|
||||
isec = sec;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
bool RISCV::synthesizeAlignAux(uint64_t &dot, InputSection *sec) {
|
||||
bool ret = false;
|
||||
if (sec) {
|
||||
invokeOnRelocs(*sec, ret = synthesizeAlignForInput<ELFT>, dot, sec);
|
||||
} else if (baseSec) {
|
||||
invokeOnRelocs(*baseSec, finalizeSynthesizeAligns<ELFT>, 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<ELF64LE>(dot, sec);
|
||||
return synthesizeAlignAux<ELF32LE>(dot, sec);
|
||||
}
|
||||
|
||||
void RISCV::finalizeRelax(int passes) const {
|
||||
llvm::TimeTraceScope timeScope("Finalize RISC-V relaxation");
|
||||
Log(ctx) << "relaxation passes: " << passes;
|
||||
|
@ -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<PotentialSpillSection>(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)) {
|
||||
|
@ -889,17 +889,9 @@ void OutputSection::sortInitFini() {
|
||||
std::array<uint8_t, 4> 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) {
|
||||
|
@ -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 {}
|
||||
|
||||
|
@ -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: <b0>:
|
||||
# CHECK-NEXT: 0: 00158513 addi a0, a1, 0x1
|
||||
# CHECK-NEXT: 4: 0001 c.nop
|
||||
# CHECK-NEXT: 6: 0001 c.nop
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: <b0>:
|
||||
# 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: <b0>:
|
||||
# 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: <b0>:
|
||||
# CHECK-NEXT: 28: 00158513 addi a0, a1, 0x1
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: <c0>:
|
||||
# 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) <c0>
|
||||
# CHECK-NEXT: 34: 0001 c.nop
|
||||
# CHECK-NEXT: 0000000000000034: R_RISCV_ALIGN *ABS*+0x2
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: <d0>:
|
||||
# CHECK-NEXT: 36: 00258513 addi a0, a1, 0x2
|
||||
|
||||
# CHECK1: <_start>:
|
||||
# CHECK1-NEXT: 010000ef jal ra, 0x10010 <foo>
|
||||
# CHECK1-NEXT: 00000013 addi zero, zero, 0x0
|
||||
# CHECK1-EMPTY:
|
||||
# CHECK1-NEXT: <b0>:
|
||||
# CHECK1-NEXT: 00158513 addi a0, a1, 0x1
|
||||
# CHECK1-EMPTY:
|
||||
# CHECK1-NEXT: <d0>:
|
||||
# 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: <b0>:
|
||||
# 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
|
Loading…
x
Reference in New Issue
Block a user