diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 1270f27a8d96e..ff7ef2dce5c79 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1357,6 +1357,8 @@ SyntheticSection *EhInputSection::getParent() const { // .eh_frame is a sequence of CIE or FDE records. // This function splits an input section into records and returns them. +// In rare cases (.eh_frame pieces are reordered by a linker script), the +// relocations may be unordered. template void EhInputSection::split() { const RelsOrRelas elfRels = relsOrRelas(); if (elfRels.areRelocsCrel()) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 9d514fe258af6..84b9b5e983662 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -390,22 +390,17 @@ namespace { class OffsetGetter { public: OffsetGetter() = default; - explicit OffsetGetter(InputSectionBase &sec) { - if (auto *eh = dyn_cast(&sec)) { - cies = eh->cies; - fdes = eh->fdes; - i = cies.begin(); - j = fdes.begin(); - } + explicit OffsetGetter(EhInputSection &sec) { + cies = sec.cies; + fdes = sec.fdes; + i = cies.begin(); + j = fdes.begin(); } // Translates offsets in input sections to offsets in output sections. // Given offset must increase monotonically. We assume that Piece is // sorted by inputOff. uint64_t get(Ctx &ctx, uint64_t off) { - if (cies.empty()) - return off; - while (j != fdes.end() && j->inputOff <= off) ++j; auto it = j; @@ -435,13 +430,12 @@ class OffsetGetter { class RelocationScanner { public: RelocationScanner(Ctx &ctx) : ctx(ctx) {} - template - void scanSection(InputSectionBase &s, bool isEH = false); + template void scanSection(InputSectionBase &s); + template void scanEhSection(EhInputSection &s); private: Ctx &ctx; InputSectionBase *sec; - OffsetGetter getter; // End of relocations, used by Mips/PPC64. const void *end = nullptr; @@ -1496,9 +1490,7 @@ void RelocationScanner::scan(typename Relocs::const_iterator &i) { } } // Get an offset in an output section this relocation is applied to. - uint64_t offset = getter.get(ctx, rel.r_offset); - if (offset == uint64_t(-1)) - return; + uint64_t offset = rel.r_offset; RelExpr expr = ctx.target->getRelExpr(type, sym, sec->content().data() + offset); @@ -1634,13 +1626,10 @@ void RelocationScanner::scanSectionImpl(Relocs rels) { if (ctx.arg.emachine == EM_PPC64) checkPPC64TLSRelax(*sec, rels); - // For EhInputSection, OffsetGetter expects the relocations to be sorted by - // r_offset. In rare cases (.eh_frame pieces are reordered by a linker - // script), the relocations may be unordered. // On SystemZ, all sections need to be sorted by r_offset, to allow TLS // relaxation to be handled correctly - see SystemZ::getTlsGdRelaxSkip. SmallVector storage; - if (isa(sec) || ctx.arg.emachine == EM_S390) + if (ctx.arg.emachine == EM_S390) rels = sortRels(rels, storage); if constexpr (RelTy::IsCrel) { @@ -1665,11 +1654,9 @@ void RelocationScanner::scanSectionImpl(Relocs rels) { }); } -template -void RelocationScanner::scanSection(InputSectionBase &s, bool isEH) { +template void RelocationScanner::scanSection(InputSectionBase &s) { sec = &s; - getter = OffsetGetter(s); - const RelsOrRelas rels = s.template relsOrRelas(!isEH); + const RelsOrRelas rels = s.template relsOrRelas(); if (rels.areRelocsCrel()) scanSectionImpl(rels.crels); else if (rels.areRelocsRel()) @@ -1678,6 +1665,27 @@ void RelocationScanner::scanSection(InputSectionBase &s, bool isEH) { scanSectionImpl(rels.relas); } +template void RelocationScanner::scanEhSection(EhInputSection &s) { + sec = &s; + OffsetGetter getter(s); + auto rels = s.rels; + s.relocations.reserve(rels.size()); + for (auto &r : rels) { + // Ignore R_*_NONE and other marker relocations. + if (r.expr == R_NONE) + continue; + uint64_t offset = getter.get(ctx, r.offset); + // Skip if the relocation offset is within a dead piece. + if (offset == uint64_t(-1)) + continue; + Symbol *sym = r.sym; + if (sym->isUndefined() && + maybeReportUndefined(ctx, cast(*sym), *sec, offset)) + continue; + process(r.expr, r.type, offset, *sym, r.addend); + } +} + template void elf::scanRelocations(Ctx &ctx) { // Scan all relocations. Each relocation goes through a series of tests to // determine if it needs special treatment, such as creating GOT, PLT, @@ -1710,7 +1718,7 @@ template void elf::scanRelocations(Ctx &ctx) { RelocationScanner scanner(ctx); for (Partition &part : ctx.partitions) { for (EhInputSection *sec : part.ehFrame->sections) - scanner.template scanSection(*sec, /*isEH=*/true); + scanner.template scanEhSection(*sec); if (part.armExidx && part.armExidx->isLive()) for (InputSection *sec : part.armExidx->exidxSections) if (sec->isLive())