diff options
Diffstat (limited to 'ELF/MarkLive.cpp')
-rw-r--r-- | ELF/MarkLive.cpp | 122 |
1 files changed, 66 insertions, 56 deletions
diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp index 8d129fc3ff138..ee499265886e3 100644 --- a/ELF/MarkLive.cpp +++ b/ELF/MarkLive.cpp @@ -22,6 +22,7 @@ #include "InputSection.h" #include "LinkerScript.h" +#include "Memory.h" #include "OutputSections.h" #include "Strings.h" #include "SymbolTable.h" @@ -44,51 +45,59 @@ using namespace lld::elf; namespace { // A resolved relocation. The Sec and Offset fields are set if the relocation // was resolved to an offset within a section. -template <class ELFT> struct ResolvedReloc { - InputSectionBase<ELFT> *Sec; - typename ELFT::uint Offset; +struct ResolvedReloc { + InputSectionBase *Sec; + uint64_t Offset; }; } // end anonymous namespace template <class ELFT> -static typename ELFT::uint getAddend(InputSectionBase<ELFT> &Sec, +static typename ELFT::uint getAddend(InputSectionBase &Sec, const typename ELFT::Rel &Rel) { return Target->getImplicitAddend(Sec.Data.begin() + Rel.r_offset, - Rel.getType(Config->Mips64EL)); + Rel.getType(Config->IsMips64EL)); } template <class ELFT> -static typename ELFT::uint getAddend(InputSectionBase<ELFT> &Sec, +static typename ELFT::uint getAddend(InputSectionBase &Sec, const typename ELFT::Rela &Rel) { return Rel.r_addend; } +// There are normally few input sections whose names are valid C +// identifiers, so we just store a std::vector instead of a multimap. +static DenseMap<StringRef, std::vector<InputSectionBase *>> CNamedSections; + template <class ELFT, class RelT> -static ResolvedReloc<ELFT> resolveReloc(InputSectionBase<ELFT> &Sec, - RelT &Rel) { - SymbolBody &B = Sec.getFile()->getRelocTargetSym(Rel); - auto *D = dyn_cast<DefinedRegular<ELFT>>(&B); - if (!D || !D->Section) - return {nullptr, 0}; - typename ELFT::uint Offset = D->Value; - if (D->isSection()) - Offset += getAddend(Sec, Rel); - return {D->Section->Repl, Offset}; +static void resolveReloc(InputSectionBase &Sec, RelT &Rel, + std::function<void(ResolvedReloc)> Fn) { + SymbolBody &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel); + if (auto *D = dyn_cast<DefinedRegular>(&B)) { + if (!D->Section) + return; + typename ELFT::uint Offset = D->Value; + if (D->isSection()) + Offset += getAddend<ELFT>(Sec, Rel); + Fn({cast<InputSectionBase>(D->Section)->Repl, Offset}); + } else if (auto *U = dyn_cast<Undefined>(&B)) { + for (InputSectionBase *Sec : CNamedSections.lookup(U->getName())) + Fn({Sec, 0}); + } } // Calls Fn for each section that Sec refers to via relocations. template <class ELFT> -static void forEachSuccessor(InputSection<ELFT> &Sec, - std::function<void(ResolvedReloc<ELFT>)> Fn) { +static void forEachSuccessor(InputSection &Sec, + std::function<void(ResolvedReloc)> Fn) { if (Sec.AreRelocsRela) { - for (const typename ELFT::Rela &Rel : Sec.relas()) - Fn(resolveReloc(Sec, Rel)); + for (const typename ELFT::Rela &Rel : Sec.template relas<ELFT>()) + resolveReloc<ELFT>(Sec, Rel, Fn); } else { - for (const typename ELFT::Rel &Rel : Sec.rels()) - Fn(resolveReloc(Sec, Rel)); + for (const typename ELFT::Rel &Rel : Sec.template rels<ELFT>()) + resolveReloc<ELFT>(Sec, Rel, Fn); } - if (Sec.DependentSection) - Fn({Sec.DependentSection, 0}); + for (InputSectionBase *IS : Sec.DependentSections) + Fn({IS, 0}); } // The .eh_frame section is an unfortunate special case. @@ -106,9 +115,8 @@ static void forEachSuccessor(InputSection<ELFT> &Sec, // the gc pass. With that we would be able to also gc some sections holding // LSDAs and personality functions if we found that they were unused. template <class ELFT, class RelTy> -static void -scanEhFrameSection(EhInputSection<ELFT> &EH, ArrayRef<RelTy> Rels, - std::function<void(ResolvedReloc<ELFT>)> Enqueue) { +static void scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels, + std::function<void(ResolvedReloc)> Enqueue) { const endianness E = ELFT::TargetEndianness; for (unsigned I = 0, N = EH.Pieces.size(); I < N; ++I) { EhSectionPiece &Piece = EH.Pieces[I]; @@ -118,7 +126,7 @@ scanEhFrameSection(EhInputSection<ELFT> &EH, ArrayRef<RelTy> Rels, if (read32<E>(Piece.data().data() + 4) == 0) { // This is a CIE, we only need to worry about the first relocation. It is // known to point to the personality function. - Enqueue(resolveReloc(EH, Rels[FirstRelI])); + resolveReloc<ELFT>(EH, Rels[FirstRelI], Enqueue); continue; } // This is a FDE. The relocations point to the described function or to @@ -129,37 +137,37 @@ scanEhFrameSection(EhInputSection<ELFT> &EH, ArrayRef<RelTy> Rels, const RelTy &Rel = Rels[I2]; if (Rel.r_offset >= PieceEnd) break; - ResolvedReloc<ELFT> R = resolveReloc(EH, Rels[I2]); - if (!R.Sec || R.Sec == &InputSection<ELFT>::Discarded) - continue; - if (R.Sec->Flags & SHF_EXECINSTR) - continue; - Enqueue({R.Sec, 0}); + resolveReloc<ELFT>(EH, Rels[I2], [&](ResolvedReloc R) { + if (!R.Sec || R.Sec == &InputSection::Discarded) + return; + if (R.Sec->Flags & SHF_EXECINSTR) + return; + Enqueue({R.Sec, 0}); + }); } } } template <class ELFT> -static void -scanEhFrameSection(EhInputSection<ELFT> &EH, - std::function<void(ResolvedReloc<ELFT>)> Enqueue) { +static void scanEhFrameSection(EhInputSection &EH, + std::function<void(ResolvedReloc)> Enqueue) { if (!EH.NumRelocations) return; // Unfortunately we need to split .eh_frame early since some relocations in // .eh_frame keep other section alive and some don't. - EH.split(); + EH.split<ELFT>(); if (EH.AreRelocsRela) - scanEhFrameSection(EH, EH.relas(), Enqueue); + scanEhFrameSection<ELFT>(EH, EH.template relas<ELFT>(), Enqueue); else - scanEhFrameSection(EH, EH.rels(), Enqueue); + scanEhFrameSection<ELFT>(EH, EH.template rels<ELFT>(), Enqueue); } // We do not garbage-collect two types of sections: // 1) Sections used by the loader (.init, .fini, .ctors, .dtors or .jcr) // 2) Non-allocatable sections which typically contain debugging information -template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) { +template <class ELFT> static bool isReserved(InputSectionBase *Sec) { switch (Sec->Type) { case SHT_FINI_ARRAY: case SHT_INIT_ARRAY: @@ -170,12 +178,7 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) { if (!(Sec->Flags & SHF_ALLOC)) return true; - // We do not want to reclaim sections if they can be referred - // by __start_* and __stop_* symbols. StringRef S = Sec->Name; - if (isValidCIdentifier(S)) - return true; - return S.startswith(".ctors") || S.startswith(".dtors") || S.startswith(".init") || S.startswith(".fini") || S.startswith(".jcr"); @@ -186,14 +189,15 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) { // Starting from GC-root sections, this function visits all reachable // sections to set their "Live" bits. template <class ELFT> void elf::markLive() { - SmallVector<InputSection<ELFT> *, 256> Q; + SmallVector<InputSection *, 256> Q; + CNamedSections.clear(); - auto Enqueue = [&](ResolvedReloc<ELFT> R) { + auto Enqueue = [&](ResolvedReloc R) { // Skip over discarded sections. This in theory shouldn't happen, because // the ELF spec doesn't allow a relocation to point to a deduplicated // COMDAT section directly. Unfortunately this happens in practice (e.g. // .eh_frame) so we need to add a check. - if (!R.Sec || R.Sec == &InputSection<ELFT>::Discarded) + if (R.Sec == &InputSection::Discarded) return; // We don't gc non alloc sections. @@ -203,20 +207,20 @@ template <class ELFT> void elf::markLive() { // Usually, a whole section is marked as live or dead, but in mergeable // (splittable) sections, each piece of data has independent liveness bit. // So we explicitly tell it which offset is in use. - if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(R.Sec)) + if (auto *MS = dyn_cast<MergeInputSection>(R.Sec)) MS->markLiveAt(R.Offset); if (R.Sec->Live) return; R.Sec->Live = true; // Add input section to the queue. - if (InputSection<ELFT> *S = dyn_cast<InputSection<ELFT>>(R.Sec)) + if (InputSection *S = dyn_cast<InputSection>(R.Sec)) Q.push_back(S); }; auto MarkSymbol = [&](const SymbolBody *Sym) { - if (auto *D = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym)) - Enqueue({D->Section, D->Value}); + if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym)) + Enqueue({cast<InputSectionBase>(D->Section), D->Value}); }; // Add GC root symbols. @@ -234,14 +238,20 @@ template <class ELFT> void elf::markLive() { // Preserve special sections and those which are specified in linker // script KEEP command. - for (InputSectionBase<ELFT> *Sec : Symtab<ELFT>::X->Sections) { + for (InputSectionBase *Sec : InputSections) { // .eh_frame is always marked as live now, but also it can reference to // sections that contain personality. We preserve all non-text sections // referred by .eh_frame here. - if (auto *EH = dyn_cast_or_null<EhInputSection<ELFT>>(Sec)) + if (auto *EH = dyn_cast_or_null<EhInputSection>(Sec)) scanEhFrameSection<ELFT>(*EH, Enqueue); - if (isReserved(Sec) || Script<ELFT>::X->shouldKeep(Sec)) + if (Sec->Flags & SHF_LINK_ORDER) + continue; + if (isReserved<ELFT>(Sec) || Script->shouldKeep(Sec)) Enqueue({Sec, 0}); + else if (isValidCIdentifier(Sec->Name)) { + CNamedSections[Saver.save("__start_" + Sec->Name)].push_back(Sec); + CNamedSections[Saver.save("__end_" + Sec->Name)].push_back(Sec); + } } // Mark all reachable sections. |