summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/MarkLive.cpp76
1 files changed, 36 insertions, 40 deletions
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index 38dda922553..448d44269c0 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -42,15 +42,6 @@ using namespace llvm::support::endian;
using namespace lld;
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.
-struct ResolvedReloc {
- InputSectionBase *Sec;
- uint64_t Offset;
-};
-} // end anonymous namespace
-
template <class ELFT>
static typename ELFT::uint getAddend(InputSectionBase &Sec,
const typename ELFT::Rel &Rel) {
@@ -70,7 +61,7 @@ static DenseMap<StringRef, std::vector<InputSectionBase *>> CNamedSections;
template <class ELFT, class RelT>
static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
- std::function<void(ResolvedReloc)> Fn) {
+ std::function<void(InputSectionBase *, uint64_t)> Fn) {
SymbolBody &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);
if (auto *Sym = dyn_cast<DefinedCommon>(&B)) {
@@ -81,22 +72,23 @@ static void resolveReloc(InputSectionBase &Sec, RelT &Rel,
if (auto *D = dyn_cast<DefinedRegular>(&B)) {
if (!D->Section)
return;
- typename ELFT::uint Offset = D->Value;
+ uint64_t Offset = D->Value;
if (D->isSection())
Offset += getAddend<ELFT>(Sec, Rel);
- Fn({cast<InputSectionBase>(D->Section), Offset});
+ Fn(cast<InputSectionBase>(D->Section), Offset);
return;
}
if (auto *U = dyn_cast<Undefined>(&B))
for (InputSectionBase *Sec : CNamedSections.lookup(U->getName()))
- Fn({Sec, 0});
+ Fn(Sec, 0);
}
// Calls Fn for each section that Sec refers to via relocations.
template <class ELFT>
-static void forEachSuccessor(InputSection &Sec,
- std::function<void(ResolvedReloc)> Fn) {
+static void
+forEachSuccessor(InputSection &Sec,
+ std::function<void(InputSectionBase *, uint64_t)> Fn) {
if (Sec.AreRelocsRela) {
for (const typename ELFT::Rela &Rel : Sec.template relas<ELFT>())
resolveReloc<ELFT>(Sec, Rel, Fn);
@@ -104,8 +96,9 @@ static void forEachSuccessor(InputSection &Sec,
for (const typename ELFT::Rel &Rel : Sec.template rels<ELFT>())
resolveReloc<ELFT>(Sec, Rel, Fn);
}
+
for (InputSectionBase *IS : Sec.DependentSections)
- Fn({IS, 0});
+ Fn(IS, 0);
}
// The .eh_frame section is an unfortunate special case.
@@ -123,9 +116,11 @@ static void forEachSuccessor(InputSection &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 &EH, ArrayRef<RelTy> Rels,
- std::function<void(ResolvedReloc)> Enqueue) {
+static void
+scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels,
+ std::function<void(InputSectionBase *, uint64_t)> Fn) {
const endianness E = ELFT::TargetEndianness;
+
for (unsigned I = 0, N = EH.Pieces.size(); I < N; ++I) {
EhSectionPiece &Piece = EH.Pieces[I];
unsigned FirstRelI = Piece.FirstRelocation;
@@ -134,7 +129,7 @@ static void scanEhFrameSection(EhInputSection &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.
- resolveReloc<ELFT>(EH, Rels[FirstRelI], Enqueue);
+ resolveReloc<ELFT>(EH, Rels[FirstRelI], Fn);
continue;
}
// This is a FDE. The relocations point to the described function or to
@@ -145,20 +140,20 @@ static void scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels,
const RelTy &Rel = Rels[I2];
if (Rel.r_offset >= PieceEnd)
break;
- 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});
- });
+ resolveReloc<ELFT>(EH, Rels[I2],
+ [&](InputSectionBase *Sec, uint64_t Offset) {
+ if (Sec && Sec != &InputSection::Discarded &&
+ !(Sec->Flags & SHF_EXECINSTR))
+ Fn(Sec, 0);
+ });
}
}
}
template <class ELFT>
-static void scanEhFrameSection(EhInputSection &EH,
- std::function<void(ResolvedReloc)> Enqueue) {
+static void
+scanEhFrameSection(EhInputSection &EH,
+ std::function<void(InputSectionBase *, uint64_t)> Fn) {
if (!EH.NumRelocations)
return;
@@ -167,9 +162,9 @@ static void scanEhFrameSection(EhInputSection &EH,
EH.split<ELFT>();
if (EH.AreRelocsRela)
- scanEhFrameSection<ELFT>(EH, EH.template relas<ELFT>(), Enqueue);
+ scanEhFrameSection<ELFT>(EH, EH.template relas<ELFT>(), Fn);
else
- scanEhFrameSection<ELFT>(EH, EH.template rels<ELFT>(), Enqueue);
+ scanEhFrameSection<ELFT>(EH, EH.template rels<ELFT>(), Fn);
}
// We do not garbage-collect two types of sections:
@@ -200,36 +195,37 @@ template <class ELFT> void elf::markLive() {
SmallVector<InputSection *, 256> Q;
CNamedSections.clear();
- auto Enqueue = [&](ResolvedReloc R) {
+ auto Enqueue = [&](InputSectionBase *Sec, uint64_t Offset) {
// 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 == &InputSection::Discarded)
+ if (Sec == &InputSection::Discarded)
return;
// We don't gc non alloc sections.
- if (!(R.Sec->Flags & SHF_ALLOC))
+ if (!(Sec->Flags & SHF_ALLOC))
return;
// 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>(R.Sec))
- MS->markLiveAt(R.Offset);
+ if (auto *MS = dyn_cast<MergeInputSection>(Sec))
+ MS->markLiveAt(Offset);
- if (R.Sec->Live)
+ if (Sec->Live)
return;
- R.Sec->Live = true;
+ Sec->Live = true;
+
// Add input section to the queue.
- if (InputSection *S = dyn_cast<InputSection>(R.Sec))
+ if (InputSection *S = dyn_cast<InputSection>(Sec))
Q.push_back(S);
};
auto MarkSymbol = [&](SymbolBody *Sym) {
if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym)) {
if (auto *IS = cast_or_null<InputSectionBase>(D->Section))
- Enqueue({IS, D->Value});
+ Enqueue(IS, D->Value);
return;
}
if (auto *S = dyn_cast_or_null<DefinedCommon>(Sym))
@@ -262,7 +258,7 @@ template <class ELFT> void elf::markLive() {
if (Sec->Flags & SHF_LINK_ORDER)
continue;
if (isReserved<ELFT>(Sec) || Script->shouldKeep(Sec))
- Enqueue({Sec, 0});
+ Enqueue(Sec, 0);
else if (isValidCIdentifier(Sec->Name)) {
CNamedSections[Saver.save("__start_" + Sec->Name)].push_back(Sec);
CNamedSections[Saver.save("__stop_" + Sec->Name)].push_back(Sec);
OpenPOWER on IntegriCloud