Eliminate LayoutInputSection class
Previously we used LayoutInputSection class to correctly assign
symbols defined in linker script. This patch removes it and uses
pointer to preceding input section in SymbolAssignment class instead.
Differential revision: https://reviews.llvm.org/D23661
llvm-svn: 280348
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index aad9bc7..321c880 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -30,14 +30,10 @@
template <class ELFT>
InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
- const Elf_Shdr *Header,
- Kind SectionKind)
- : Header(Header), File(File), SectionKind(SectionKind), Repl(this),
- Compressed(Header->sh_flags & SHF_COMPRESSED) {
- // The garbage collector sets sections' Live bits.
- // If GC is disabled, all sections are considered live by default.
- Live = !Config->GcSections;
-
+ const Elf_Shdr *Hdr, Kind SectionKind)
+ : InputSectionData(SectionKind, Hdr->sh_flags & SHF_COMPRESSED,
+ !Config->GcSections),
+ Header(Hdr), File(File), Repl(this) {
// The ELF spec states that a value of 0 means the section has
// no alignment constraits.
Alignment = std::max<uintX_t>(Header->sh_addralign, 1);
@@ -71,7 +67,6 @@
typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
switch (SectionKind) {
case Regular:
- case Layout:
return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
case EHFrame:
// The file crtbeginT.o has relocations pointing to the start of an empty
@@ -131,7 +126,7 @@
template <class ELFT>
bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
- return S->SectionKind == Base::Regular || S->SectionKind == Base::Layout;
+ return S->SectionKind == Base::Regular;
}
template <class ELFT>
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index a12b591..3b7c201 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -30,8 +30,33 @@
template <class ELFT> class OutputSection;
template <class ELFT> class OutputSectionBase;
+// We need non-template input section class to store symbol layout
+// in linker script parser structures, where we do not have ELFT
+// template parameter. For each scripted output section symbol we
+// store pointer to preceding InputSectionData object or nullptr,
+// if symbol should be placed at the very beginning of the output
+// section
+class InputSectionData {
+public:
+ enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions, MipsAbiFlags };
+
+ // The garbage collector sets sections' Live bits.
+ // If GC is disabled, all sections are considered live by default.
+ InputSectionData(Kind SectionKind, bool Compressed, bool Live)
+ : SectionKind(SectionKind), Live(Live), Compressed(Compressed) {}
+
+ Kind SectionKind;
+ uint32_t Alignment;
+ // Used for garbage collection.
+ bool Live;
+
+ bool Compressed;
+ // If a section is compressed, this vector has uncompressed section data.
+ SmallVector<char, 0> Uncompressed;
+};
+
// This corresponds to a section of an input file.
-template <class ELFT> class InputSectionBase {
+template <class ELFT> class InputSectionBase : public InputSectionData {
protected:
typedef typename ELFT::Chdr Elf_Chdr;
typedef typename ELFT::Rel Elf_Rel;
@@ -44,30 +69,12 @@
// The file this section is from.
ObjectFile<ELFT> *File;
- // If a section is compressed, this vector has uncompressed section data.
- SmallVector<char, 0> Uncompressed;
-
public:
- enum Kind {
- Regular,
- EHFrame,
- Merge,
- MipsReginfo,
- MipsOptions,
- MipsAbiFlags,
- Layout
- };
- Kind SectionKind;
-
- InputSectionBase() : Repl(this) {}
+ InputSectionBase() : InputSectionData(Regular, false, false), Repl(this) {}
InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
Kind SectionKind);
OutputSectionBase<ELFT> *OutSec = nullptr;
- uint32_t Alignment;
-
- // Used for garbage collection.
- bool Live;
// This pointer points to the "real" instance of this instance.
// Usually Repl == this. However, if ICF merges two sections,
@@ -96,8 +103,6 @@
void relocate(uint8_t *Buf, uint8_t *BufEnd);
std::vector<Relocation<ELFT>> Relocations;
-
- bool Compressed;
};
template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded;
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index b3a1c45..9afd5ba 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -133,54 +133,6 @@
return Ret;
}
-// You can define new symbols using linker scripts. For example,
-// ".text { abc.o(.text); foo = .; def.o(.text); }" defines symbol
-// foo just after abc.o's text section contents. This class is to
-// handle such symbol definitions.
-//
-// In order to handle scripts like the above one, we want to
-// keep symbol definitions in output sections. Because output sections
-// can contain only input sections, we wrap symbol definitions
-// with dummy input sections. This class serves that purpose.
-template <class ELFT>
-class elf::LayoutInputSection : public InputSectionBase<ELFT> {
-public:
- explicit LayoutInputSection(SymbolAssignment *Cmd);
- static bool classof(const InputSectionBase<ELFT> *S);
- SymbolAssignment *Cmd;
-
-private:
- typename ELFT::Shdr Hdr;
-};
-
-template <class ELFT>
-static InputSectionBase<ELFT> *
-getNonLayoutSection(std::vector<InputSectionBase<ELFT> *> &Vec) {
- for (InputSectionBase<ELFT> *S : Vec)
- if (!isa<LayoutInputSection<ELFT>>(S))
- return S;
- return nullptr;
-}
-
-template <class T> static T *zero(T *Val) {
- memset(Val, 0, sizeof(*Val));
- return Val;
-}
-
-template <class ELFT>
-LayoutInputSection<ELFT>::LayoutInputSection(SymbolAssignment *Cmd)
- : InputSectionBase<ELFT>(nullptr, zero(&Hdr),
- InputSectionBase<ELFT>::Layout),
- Cmd(Cmd) {
- this->Live = true;
- Hdr.sh_type = SHT_NOBITS;
-}
-
-template <class ELFT>
-bool LayoutInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
- return S->SectionKind == InputSectionBase<ELFT>::Layout;
-}
-
template <class ELFT>
static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
return A->getSectionName() < B->getSectionName();
@@ -236,12 +188,13 @@
std::vector<InputSectionBase<ELFT> *>
LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
std::vector<InputSectionBase<ELFT> *> Ret;
+ DenseSet<InputSectionBase<ELFT> *> SectionIndex;
for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) {
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) {
if (shouldDefine<ELFT>(OutCmd))
addSynthetic<ELFT>(OutCmd);
- Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection<ELFT>(OutCmd));
+ OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back();
continue;
}
@@ -253,7 +206,12 @@
std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortInner));
if (Cmd->SortOuter)
std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortOuter));
- Ret.insert(Ret.end(), V.begin(), V.end());
+
+ // Add all input sections corresponding to rule 'Cmd' to
+ // resulting vector. We do not add duplicate input sections.
+ for (InputSectionBase<ELFT> *S : V)
+ if (SectionIndex.insert(S).second)
+ Ret.push_back(S);
}
return Ret;
}
@@ -284,13 +242,12 @@
}
std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd);
- InputSectionBase<ELFT> *Head = getNonLayoutSection<ELFT>(V);
- if (!Head)
+ if (V.empty())
continue;
OutputSectionBase<ELFT> *OutSec;
bool IsNew;
- std::tie(OutSec, IsNew) = Factory.create(Head, Cmd->Name);
+ std::tie(OutSec, IsNew) = Factory.create(V.front(), Cmd->Name);
if (IsNew)
OutputSections->push_back(OutSec);
@@ -298,8 +255,7 @@
for (InputSectionBase<ELFT> *Sec : V) {
if (Subalign)
Sec->Alignment = Subalign;
- if (!Sec->OutSec)
- OutSec->addSection(Sec);
+ OutSec->addSection(Sec);
}
}
}
@@ -359,31 +315,49 @@
addStartEndSymbols(Cmd, Sec);
return;
}
-
typedef typename ELFT::uint uintX_t;
uintX_t Off = 0;
+ auto ItCmd = Cmd->Commands.begin();
- for (InputSection<ELFT> *I : OutSec->Sections) {
- if (auto *L = dyn_cast<LayoutInputSection<ELFT>>(I)) {
- uintX_t Value = L->Cmd->Expression(Sec->getVA() + Off) - Sec->getVA();
- if (L->Cmd->Name == ".") {
+ // Assigns values to all symbols following the given
+ // input section 'D' in output section 'Sec'. When symbols
+ // are in the beginning of output section the value of 'D'
+ // is nullptr.
+ auto AssignSuccessors = [&](InputSectionData *D) {
+ for (; ItCmd != Cmd->Commands.end(); ++ItCmd) {
+ auto *AssignCmd = dyn_cast<SymbolAssignment>(ItCmd->get());
+ if (!AssignCmd)
+ continue;
+ if (D != AssignCmd->GoesAfter)
+ break;
+
+ uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
+ if (AssignCmd->Name == ".") {
+ // Update to location counter means update to section size.
Off = Value;
- } else if (auto *Sym =
- cast_or_null<DefinedSynthetic<ELFT>>(L->Cmd->Sym)) {
- // shouldDefine could have returned false, so we need to check Sym,
- // for non-null value.
+ Sec->setSize(Off);
+ continue;
+ }
+
+ if (DefinedSynthetic<ELFT> *Sym =
+ cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
Sym->Section = OutSec;
Sym->Value = Value;
}
- } else {
- Off = alignTo(Off, I->Alignment);
- I->OutSecOff = Off;
- Off += I->getSize();
}
+ };
+
+ AssignSuccessors(nullptr);
+ for (InputSection<ELFT> *I : OutSec->Sections) {
+ Off = alignTo(Off, I->Alignment);
+ I->OutSecOff = Off;
+ Off += I->getSize();
// Update section size inside for-loop, so that SIZEOF
// works correctly in the case below:
// .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
Sec->setSize(Off);
+ // Add symbols following current input section.
+ AssignSuccessors(I);
}
}
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index a866470..a5e3d9e 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -26,7 +26,7 @@
template <class ELFT> class InputSectionBase;
template <class ELFT> class OutputSectionBase;
template <class ELFT> class OutputSectionFactory;
-template <class ELFT> class LayoutInputSection;
+class InputSectionData;
typedef std::function<uint64_t(uint64_t)> Expr;
@@ -66,6 +66,7 @@
// Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
bool Provide = false;
bool Hidden = false;
+ InputSectionData *GoesAfter = nullptr;
};
// Linker scripts allow additional constraints to be put on ouput sections.
@@ -178,8 +179,6 @@
std::vector<size_t> getPhdrIndices(StringRef SectionName);
size_t getPhdrIndex(StringRef PhdrName);
- llvm::SpecificBumpPtrAllocator<LayoutInputSection<ELFT>> LAlloc;
-
uintX_t Dot;
};
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 0ec12d0..9874708 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -1825,8 +1825,6 @@
case InputSectionBase<ELFT>::MipsAbiFlags:
Sec = new MipsAbiFlagsOutputSection<ELFT>();
break;
- case InputSectionBase<ELFT>::Layout:
- llvm_unreachable("Invalid section type");
}
Out<ELFT>::Pool.emplace_back(Sec);
return {Sec, true};