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
This commit is contained in:
Eugene Leviant 2016-09-01 09:55:57 +00:00
parent 40d7f5c277
commit 97403d15ee
5 changed files with 76 additions and 105 deletions

View File

@ -30,14 +30,10 @@ using namespace lld::elf;
template <class ELFT> template <class ELFT>
InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File, InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
const Elf_Shdr *Header, const Elf_Shdr *Hdr, Kind SectionKind)
Kind SectionKind) : InputSectionData(SectionKind, Hdr->sh_flags & SHF_COMPRESSED,
: Header(Header), File(File), SectionKind(SectionKind), Repl(this), !Config->GcSections),
Compressed(Header->sh_flags & SHF_COMPRESSED) { Header(Hdr), File(File), Repl(this) {
// The garbage collector sets sections' Live bits.
// If GC is disabled, all sections are considered live by default.
Live = !Config->GcSections;
// The ELF spec states that a value of 0 means the section has // The ELF spec states that a value of 0 means the section has
// no alignment constraits. // no alignment constraits.
Alignment = std::max<uintX_t>(Header->sh_addralign, 1); Alignment = std::max<uintX_t>(Header->sh_addralign, 1);
@ -71,7 +67,6 @@ template <class ELFT>
typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const { typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
switch (SectionKind) { switch (SectionKind) {
case Regular: case Regular:
case Layout:
return cast<InputSection<ELFT>>(this)->OutSecOff + Offset; return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
case EHFrame: case EHFrame:
// The file crtbeginT.o has relocations pointing to the start of an empty // The file crtbeginT.o has relocations pointing to the start of an empty
@ -131,7 +126,7 @@ InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F,
template <class ELFT> template <class ELFT>
bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { 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> template <class ELFT>

View File

@ -30,8 +30,33 @@ template <class ELFT> class ObjectFile;
template <class ELFT> class OutputSection; template <class ELFT> class OutputSection;
template <class ELFT> class OutputSectionBase; 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. // This corresponds to a section of an input file.
template <class ELFT> class InputSectionBase { template <class ELFT> class InputSectionBase : public InputSectionData {
protected: protected:
typedef typename ELFT::Chdr Elf_Chdr; typedef typename ELFT::Chdr Elf_Chdr;
typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rel Elf_Rel;
@ -44,30 +69,12 @@ protected:
// The file this section is from. // The file this section is from.
ObjectFile<ELFT> *File; ObjectFile<ELFT> *File;
// If a section is compressed, this vector has uncompressed section data.
SmallVector<char, 0> Uncompressed;
public: public:
enum Kind { InputSectionBase() : InputSectionData(Regular, false, false), Repl(this) {}
Regular,
EHFrame,
Merge,
MipsReginfo,
MipsOptions,
MipsAbiFlags,
Layout
};
Kind SectionKind;
InputSectionBase() : Repl(this) {}
InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header, InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
Kind SectionKind); Kind SectionKind);
OutputSectionBase<ELFT> *OutSec = nullptr; OutputSectionBase<ELFT> *OutSec = nullptr;
uint32_t Alignment;
// Used for garbage collection.
bool Live;
// This pointer points to the "real" instance of this instance. // This pointer points to the "real" instance of this instance.
// Usually Repl == this. However, if ICF merges two sections, // Usually Repl == this. However, if ICF merges two sections,
@ -96,8 +103,6 @@ public:
void relocate(uint8_t *Buf, uint8_t *BufEnd); void relocate(uint8_t *Buf, uint8_t *BufEnd);
std::vector<Relocation<ELFT>> Relocations; std::vector<Relocation<ELFT>> Relocations;
bool Compressed;
}; };
template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded; template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded;

View File

@ -133,54 +133,6 @@ LinkerScript<ELFT>::getInputSections(const InputSectionDescription *I) {
return Ret; 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> template <class ELFT>
static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) { static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
return A->getSectionName() < B->getSectionName(); return A->getSectionName() < B->getSectionName();
@ -236,12 +188,13 @@ template <class ELFT>
std::vector<InputSectionBase<ELFT> *> std::vector<InputSectionBase<ELFT> *>
LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) { LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
std::vector<InputSectionBase<ELFT> *> Ret; std::vector<InputSectionBase<ELFT> *> Ret;
DenseSet<InputSectionBase<ELFT> *> SectionIndex;
for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) { for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) {
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) { if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) {
if (shouldDefine<ELFT>(OutCmd)) if (shouldDefine<ELFT>(OutCmd))
addSynthetic<ELFT>(OutCmd); addSynthetic<ELFT>(OutCmd);
Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection<ELFT>(OutCmd)); OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back();
continue; continue;
} }
@ -253,7 +206,12 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortInner)); std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortInner));
if (Cmd->SortOuter) if (Cmd->SortOuter)
std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(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; return Ret;
} }
@ -284,13 +242,12 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
} }
std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd); std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd);
InputSectionBase<ELFT> *Head = getNonLayoutSection<ELFT>(V); if (V.empty())
if (!Head)
continue; continue;
OutputSectionBase<ELFT> *OutSec; OutputSectionBase<ELFT> *OutSec;
bool IsNew; bool IsNew;
std::tie(OutSec, IsNew) = Factory.create(Head, Cmd->Name); std::tie(OutSec, IsNew) = Factory.create(V.front(), Cmd->Name);
if (IsNew) if (IsNew)
OutputSections->push_back(OutSec); OutputSections->push_back(OutSec);
@ -298,8 +255,7 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
for (InputSectionBase<ELFT> *Sec : V) { for (InputSectionBase<ELFT> *Sec : V) {
if (Subalign) if (Subalign)
Sec->Alignment = Subalign; Sec->Alignment = Subalign;
if (!Sec->OutSec) OutSec->addSection(Sec);
OutSec->addSection(Sec);
} }
} }
} }
@ -359,31 +315,49 @@ void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase<ELFT> *Sec) {
addStartEndSymbols(Cmd, Sec); addStartEndSymbols(Cmd, Sec);
return; return;
} }
typedef typename ELFT::uint uintX_t; typedef typename ELFT::uint uintX_t;
uintX_t Off = 0; uintX_t Off = 0;
auto ItCmd = Cmd->Commands.begin();
for (InputSection<ELFT> *I : OutSec->Sections) { // Assigns values to all symbols following the given
if (auto *L = dyn_cast<LayoutInputSection<ELFT>>(I)) { // input section 'D' in output section 'Sec'. When symbols
uintX_t Value = L->Cmd->Expression(Sec->getVA() + Off) - Sec->getVA(); // are in the beginning of output section the value of 'D'
if (L->Cmd->Name == ".") { // 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; Off = Value;
} else if (auto *Sym = Sec->setSize(Off);
cast_or_null<DefinedSynthetic<ELFT>>(L->Cmd->Sym)) { continue;
// shouldDefine could have returned false, so we need to check Sym, }
// for non-null value.
if (DefinedSynthetic<ELFT> *Sym =
cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
Sym->Section = OutSec; Sym->Section = OutSec;
Sym->Value = Value; 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 // Update section size inside for-loop, so that SIZEOF
// works correctly in the case below: // works correctly in the case below:
// .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
Sec->setSize(Off); Sec->setSize(Off);
// Add symbols following current input section.
AssignSuccessors(I);
} }
} }

View File

@ -26,7 +26,7 @@ class SymbolBody;
template <class ELFT> class InputSectionBase; template <class ELFT> class InputSectionBase;
template <class ELFT> class OutputSectionBase; template <class ELFT> class OutputSectionBase;
template <class ELFT> class OutputSectionFactory; template <class ELFT> class OutputSectionFactory;
template <class ELFT> class LayoutInputSection; class InputSectionData;
typedef std::function<uint64_t(uint64_t)> Expr; typedef std::function<uint64_t(uint64_t)> Expr;
@ -66,6 +66,7 @@ struct SymbolAssignment : BaseCommand {
// Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN. // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
bool Provide = false; bool Provide = false;
bool Hidden = false; bool Hidden = false;
InputSectionData *GoesAfter = nullptr;
}; };
// Linker scripts allow additional constraints to be put on ouput sections. // Linker scripts allow additional constraints to be put on ouput sections.
@ -178,8 +179,6 @@ private:
std::vector<size_t> getPhdrIndices(StringRef SectionName); std::vector<size_t> getPhdrIndices(StringRef SectionName);
size_t getPhdrIndex(StringRef PhdrName); size_t getPhdrIndex(StringRef PhdrName);
llvm::SpecificBumpPtrAllocator<LayoutInputSection<ELFT>> LAlloc;
uintX_t Dot; uintX_t Dot;
}; };

View File

@ -1825,8 +1825,6 @@ OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
case InputSectionBase<ELFT>::MipsAbiFlags: case InputSectionBase<ELFT>::MipsAbiFlags:
Sec = new MipsAbiFlagsOutputSection<ELFT>(); Sec = new MipsAbiFlagsOutputSection<ELFT>();
break; break;
case InputSectionBase<ELFT>::Layout:
llvm_unreachable("Invalid section type");
} }
Out<ELFT>::Pool.emplace_back(Sec); Out<ELFT>::Pool.emplace_back(Sec);
return {Sec, true}; return {Sec, true};