Skip to content

Commit 3554c78

Browse files
authored
ELF: Use preprocessed relocations for EhInputSection scanning
.eh_frame sections require special sub-section processing, specifically, CIEs are de-duplicated and FDEs are garbage collected. Create a specialized scanEhSection() function utilizing the just-added EhInputSection::rels. OffsetGetter is moved to scanEhSection. This improves separation of concerns between InputSection and EhInputSection processing. This removes another `relsOrRelas` call using `supportsCrel=false`. DWARF.cpp now has the last call. Pull Request: #161091
1 parent 2f9ae0b commit 3554c78

File tree

2 files changed

+35
-25
lines changed

2 files changed

+35
-25
lines changed

lld/ELF/InputSection.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,8 @@ SyntheticSection *EhInputSection::getParent() const {
13571357

13581358
// .eh_frame is a sequence of CIE or FDE records.
13591359
// This function splits an input section into records and returns them.
1360+
// In rare cases (.eh_frame pieces are reordered by a linker script), the
1361+
// relocations may be unordered.
13601362
template <class ELFT> void EhInputSection::split() {
13611363
const RelsOrRelas<ELFT> elfRels = relsOrRelas<ELFT>();
13621364
if (elfRels.areRelocsCrel())

lld/ELF/Relocations.cpp

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -390,22 +390,17 @@ namespace {
390390
class OffsetGetter {
391391
public:
392392
OffsetGetter() = default;
393-
explicit OffsetGetter(InputSectionBase &sec) {
394-
if (auto *eh = dyn_cast<EhInputSection>(&sec)) {
395-
cies = eh->cies;
396-
fdes = eh->fdes;
397-
i = cies.begin();
398-
j = fdes.begin();
399-
}
393+
explicit OffsetGetter(EhInputSection &sec) {
394+
cies = sec.cies;
395+
fdes = sec.fdes;
396+
i = cies.begin();
397+
j = fdes.begin();
400398
}
401399

402400
// Translates offsets in input sections to offsets in output sections.
403401
// Given offset must increase monotonically. We assume that Piece is
404402
// sorted by inputOff.
405403
uint64_t get(Ctx &ctx, uint64_t off) {
406-
if (cies.empty())
407-
return off;
408-
409404
while (j != fdes.end() && j->inputOff <= off)
410405
++j;
411406
auto it = j;
@@ -435,13 +430,12 @@ class OffsetGetter {
435430
class RelocationScanner {
436431
public:
437432
RelocationScanner(Ctx &ctx) : ctx(ctx) {}
438-
template <class ELFT>
439-
void scanSection(InputSectionBase &s, bool isEH = false);
433+
template <class ELFT> void scanSection(InputSectionBase &s);
434+
template <class ELFT> void scanEhSection(EhInputSection &s);
440435

441436
private:
442437
Ctx &ctx;
443438
InputSectionBase *sec;
444-
OffsetGetter getter;
445439

446440
// End of relocations, used by Mips/PPC64.
447441
const void *end = nullptr;
@@ -1496,9 +1490,7 @@ void RelocationScanner::scan(typename Relocs<RelTy>::const_iterator &i) {
14961490
}
14971491
}
14981492
// Get an offset in an output section this relocation is applied to.
1499-
uint64_t offset = getter.get(ctx, rel.r_offset);
1500-
if (offset == uint64_t(-1))
1501-
return;
1493+
uint64_t offset = rel.r_offset;
15021494

15031495
RelExpr expr =
15041496
ctx.target->getRelExpr(type, sym, sec->content().data() + offset);
@@ -1634,13 +1626,10 @@ void RelocationScanner::scanSectionImpl(Relocs<RelTy> rels) {
16341626
if (ctx.arg.emachine == EM_PPC64)
16351627
checkPPC64TLSRelax<RelTy>(*sec, rels);
16361628

1637-
// For EhInputSection, OffsetGetter expects the relocations to be sorted by
1638-
// r_offset. In rare cases (.eh_frame pieces are reordered by a linker
1639-
// script), the relocations may be unordered.
16401629
// On SystemZ, all sections need to be sorted by r_offset, to allow TLS
16411630
// relaxation to be handled correctly - see SystemZ::getTlsGdRelaxSkip.
16421631
SmallVector<RelTy, 0> storage;
1643-
if (isa<EhInputSection>(sec) || ctx.arg.emachine == EM_S390)
1632+
if (ctx.arg.emachine == EM_S390)
16441633
rels = sortRels(rels, storage);
16451634

16461635
if constexpr (RelTy::IsCrel) {
@@ -1665,11 +1654,9 @@ void RelocationScanner::scanSectionImpl(Relocs<RelTy> rels) {
16651654
});
16661655
}
16671656

1668-
template <class ELFT>
1669-
void RelocationScanner::scanSection(InputSectionBase &s, bool isEH) {
1657+
template <class ELFT> void RelocationScanner::scanSection(InputSectionBase &s) {
16701658
sec = &s;
1671-
getter = OffsetGetter(s);
1672-
const RelsOrRelas<ELFT> rels = s.template relsOrRelas<ELFT>(!isEH);
1659+
const RelsOrRelas<ELFT> rels = s.template relsOrRelas<ELFT>();
16731660
if (rels.areRelocsCrel())
16741661
scanSectionImpl<ELFT>(rels.crels);
16751662
else if (rels.areRelocsRel())
@@ -1678,6 +1665,27 @@ void RelocationScanner::scanSection(InputSectionBase &s, bool isEH) {
16781665
scanSectionImpl<ELFT>(rels.relas);
16791666
}
16801667

1668+
template <class ELFT> void RelocationScanner::scanEhSection(EhInputSection &s) {
1669+
sec = &s;
1670+
OffsetGetter getter(s);
1671+
auto rels = s.rels;
1672+
s.relocations.reserve(rels.size());
1673+
for (auto &r : rels) {
1674+
// Ignore R_*_NONE and other marker relocations.
1675+
if (r.expr == R_NONE)
1676+
continue;
1677+
uint64_t offset = getter.get(ctx, r.offset);
1678+
// Skip if the relocation offset is within a dead piece.
1679+
if (offset == uint64_t(-1))
1680+
continue;
1681+
Symbol *sym = r.sym;
1682+
if (sym->isUndefined() &&
1683+
maybeReportUndefined(ctx, cast<Undefined>(*sym), *sec, offset))
1684+
continue;
1685+
process(r.expr, r.type, offset, *sym, r.addend);
1686+
}
1687+
}
1688+
16811689
template <class ELFT> void elf::scanRelocations(Ctx &ctx) {
16821690
// Scan all relocations. Each relocation goes through a series of tests to
16831691
// determine if it needs special treatment, such as creating GOT, PLT,
@@ -1710,7 +1718,7 @@ template <class ELFT> void elf::scanRelocations(Ctx &ctx) {
17101718
RelocationScanner scanner(ctx);
17111719
for (Partition &part : ctx.partitions) {
17121720
for (EhInputSection *sec : part.ehFrame->sections)
1713-
scanner.template scanSection<ELFT>(*sec, /*isEH=*/true);
1721+
scanner.template scanEhSection<ELFT>(*sec);
17141722
if (part.armExidx && part.armExidx->isLive())
17151723
for (InputSection *sec : part.armExidx->exidxSections)
17161724
if (sec->isLive())

0 commit comments

Comments
 (0)