Remove ResolvedReloc.

ResolvedReloc struct is always passed to a callback function and not
stored anywhere. That is, in effect, we use the struct to pack multiple
arguments to one argument, which doesn't make much sense. This patch
removes the struct and passes the members to the callback directly.

llvm-svn: 310620
This commit is contained in:
Rui Ueyama 2017-08-10 16:21:04 +00:00
parent bea30c6286
commit 27fbd1e14a

View File

@ -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);