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);
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
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>
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;
// 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,
void relocate(uint8_t *Buf, uint8_t *BufEnd);
std::vector<Relocation<ELFT>> Relocations;
-
- bool Compressed;
};
template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded;
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();
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;
}
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;
}
}
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);
for (InputSectionBase<ELFT> *Sec : V) {
if (Subalign)
Sec->Alignment = Subalign;
- if (!Sec->OutSec)
- OutSec->addSection(Sec);
+ OutSec->addSection(Sec);
}
}
}
addStartEndSymbols(Cmd, Sec);
return;
}
-
typedef typename ELFT::uint uintX_t;
uintX_t Off = 0;
+ auto ItCmd = Cmd->Commands.begin();
+
+ // 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;
- 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 == ".") {
+ 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);
}
}