Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -33,12 +33,39 @@ template class ObjectFile; class OutputSection; -// This corresponds to a section of an input file. -class InputSectionBase { +class SectionBase { + unsigned SectionKind : 3; + +public: + enum Kind { Regular, EHFrame, Merge, Synthetic, Output }; + +protected: + SectionBase(Kind SectionKind, uint64_t Flags) + : SectionKind(SectionKind), Flags(Flags) {} + public: - enum Kind { Regular, EHFrame, Merge, Synthetic, }; Kind kind() const { return (Kind)SectionKind; } + + uint64_t Flags; + + template OutputSection *getOutputSection(); + template const OutputSection *getOutputSection() const { + return const_cast(this)->getOutputSection(); + } + + // Translate an offset in the input section to an offset in the output + // section. + template uint64_t getOffset(uint64_t Offset) const; + + template uint64_t getOffset(const DefinedRegular &Sym) const; +}; + +// This corresponds to a section of an input file. +class InputSectionBase : public SectionBase { +public: + static bool classof(const SectionBase *S); + // The file this section is from. InputFile *File; @@ -46,8 +73,6 @@ StringRef Name; - unsigned SectionKind : 3; - // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. unsigned Live : 1; // for garbage collection @@ -56,15 +81,15 @@ uint32_t Alignment; // These corresponds to the fields in Elf_Shdr. - uint64_t Flags; uint64_t Offset = 0; uint64_t Entsize; uint32_t Type; uint32_t Link; uint32_t Info; - InputSectionBase() - : SectionKind(Regular), Live(false), Assigned(false), Repl(this) { + InputSectionBase(Kind SectionKind) + : SectionBase(SectionKind, /*Flags*/ 0), Live(false), Assigned(false), + Repl(this) { NumRelocations = 0; AreRelocsRela = false; } @@ -109,20 +134,13 @@ // Returns the size of this section (even if this is a common or BSS.) template size_t getSize() const; - template OutputSection *getOutputSection() const; - template ObjectFile *getFile() const; template llvm::object::ELFFile getObj() const { return getFile()->getObj(); } - template uint64_t getOffset(const DefinedRegular &Sym) const; - template InputSectionBase *getLinkOrderDep() const; - // Translate an offset in the input section to an offset in the output - // section. - template uint64_t getOffset(uint64_t Offset) const; template void uncompress(); @@ -164,7 +182,7 @@ public: MergeInputSection(ObjectFile *F, const Elf_Shdr *Header, StringRef Name); - static bool classof(const InputSectionBase *S); + static bool classof(const SectionBase *S); void splitIntoPieces(); // Mark the piece at a given offset live. Used by GC. @@ -236,7 +254,7 @@ typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::uint uintX_t; EhInputSection(ObjectFile *F, const Elf_Shdr *Header, StringRef Name); - static bool classof(const InputSectionBase *S); + static bool classof(const SectionBase *S); void split(); template void split(ArrayRef Rels); @@ -269,7 +287,7 @@ // to. The writer sets a value. uint64_t OutSecOff = 0; - static bool classof(const InputSectionBase *S); + static bool classof(const SectionBase *S); template InputSectionBase *getRelocatedSection(); Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -55,10 +55,9 @@ uint32_t Link, uint32_t Info, uint64_t Addralign, ArrayRef Data, StringRef Name, Kind SectionKind) - : File(File), Data(Data), Name(Name), SectionKind(SectionKind), + : SectionBase(SectionKind, Flags), File(File), Data(Data), Name(Name), Live(!Config->GcSections || !(Flags & SHF_ALLOC)), Assigned(false), - Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info), - Repl(this) { + Entsize(Entsize), Type(Type), Link(Link), Info(Info), Repl(this) { NumRelocations = 0; AreRelocsRela = false; @@ -94,17 +93,21 @@ return Data.size(); } -template -uint64_t InputSectionBase::getOffset(uint64_t Offset) const { +template uint64_t SectionBase::getOffset(uint64_t Offset) const { typedef typename ELFT::uint uintX_t; switch (kind()) { + case Output: { + auto *OS = cast(this); + return Offset == uintX_t(-1) ? OS->Size : Offset; + } case Regular: return cast(this)->OutSecOff + Offset; - case Synthetic: + case Synthetic: { + auto *IS = cast(this); // For synthetic sections we treat offset -1 as the end of the section. - // The same approach is used for synthetic symbols (DefinedSynthetic). - return cast(this)->OutSecOff + - (Offset == uintX_t(-1) ? getSize() : Offset); + return IS->OutSecOff + + (Offset == uintX_t(-1) ? IS->getSize() : Offset); + } case EHFrame: // The file crtbeginT.o has relocations pointing to the start of an empty // .eh_frame that is known to be the first in the link. It does that to @@ -119,13 +122,14 @@ llvm_unreachable("invalid section kind"); } -template -OutputSection *InputSectionBase::getOutputSection() const { +template OutputSection *SectionBase::getOutputSection() { if (auto *MS = dyn_cast>(this)) return MS->MergeSec ? MS->MergeSec->OutSec : nullptr; if (auto *EH = dyn_cast>(this)) return EH->EHSec->OutSec; - return OutSec; + if (auto *IS = dyn_cast(this)) + return IS->OutSec; + return cast(this); } // Uncompress section contents. Note that this function is called @@ -150,7 +154,7 @@ } template -uint64_t InputSectionBase::getOffset(const DefinedRegular &Sym) const { +uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const { return getOffset(Sym.Value); } @@ -188,7 +192,7 @@ InputSection InputSection::Discarded; -InputSection::InputSection() : InputSectionBase() {} +InputSection::InputSection() : InputSectionBase(Regular) {} InputSection::InputSection(uint64_t Flags, uint32_t Type, uint64_t Addralign, ArrayRef Data, StringRef Name, Kind K) @@ -201,9 +205,23 @@ const typename ELFT::Shdr *Header, StringRef Name) : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} -bool InputSection::classof(const InputSectionBase *S) { - return S->kind() == InputSectionBase::Regular || - S->kind() == InputSectionBase::Synthetic; +bool InputSection::classof(const SectionBase *S) { + return S->kind() == SectionBase::Regular || + S->kind() == SectionBase::Synthetic; +} + +bool InputSectionBase::classof(const SectionBase *S) { + Kind K = S->kind(); + switch (K) { + case Regular: + case EHFrame: + case Merge: + case Synthetic: + return true; + case Output: + return false; + } + llvm_unreachable("Invalid kind"); } template InputSectionBase *InputSection::getRelocatedSection() { @@ -250,14 +268,15 @@ // avoid having to parse and recreate .eh_frame, we just replace any // relocation in it pointing to discarded sections with R_*_NONE, which // hopefully creates a frame that is ignored at runtime. - InputSectionBase *Section = cast(Body).Section; + SectionBase *Section = cast(Body).Section; if (Section == &InputSection::Discarded) { P->setSymbolAndType(0, 0, false); continue; } if (Config->Rela) { - P->r_addend += Body.getVA() - Section->OutSec->Addr; + P->r_addend += + Body.getVA() - Section->getOutputSection()->Addr; } else if (Config->Relocatable) { const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset; RelocatedSection->Relocations.push_back( @@ -588,8 +607,7 @@ this->Live = true; } -template -bool EhInputSection::classof(const InputSectionBase *S) { +template bool EhInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::EHFrame; } @@ -717,7 +735,7 @@ } template -bool MergeInputSection::classof(const InputSectionBase *S) { +bool MergeInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::Merge; } @@ -829,10 +847,10 @@ template InputSectionBase *InputSectionBase::getLinkOrderDep() const; template InputSectionBase *InputSectionBase::getLinkOrderDep() const; -template OutputSection *InputSectionBase::getOutputSection() const; -template OutputSection *InputSectionBase::getOutputSection() const; -template OutputSection *InputSectionBase::getOutputSection() const; -template OutputSection *InputSectionBase::getOutputSection() const; +template OutputSection *SectionBase::getOutputSection(); +template OutputSection *SectionBase::getOutputSection(); +template OutputSection *SectionBase::getOutputSection(); +template OutputSection *SectionBase::getOutputSection(); template InputSectionBase *InputSection::getRelocatedSection(); template InputSectionBase *InputSection::getRelocatedSection(); @@ -840,18 +858,18 @@ template InputSectionBase *InputSection::getRelocatedSection(); template uint64_t -InputSectionBase::getOffset(const DefinedRegular &Sym) const; +SectionBase::getOffset(const DefinedRegular &Sym) const; template uint64_t -InputSectionBase::getOffset(const DefinedRegular &Sym) const; +SectionBase::getOffset(const DefinedRegular &Sym) const; template uint64_t -InputSectionBase::getOffset(const DefinedRegular &Sym) const; +SectionBase::getOffset(const DefinedRegular &Sym) const; template uint64_t -InputSectionBase::getOffset(const DefinedRegular &Sym) const; +SectionBase::getOffset(const DefinedRegular &Sym) const; -template uint64_t InputSectionBase::getOffset(uint64_t Offset) const; -template uint64_t InputSectionBase::getOffset(uint64_t Offset) const; -template uint64_t InputSectionBase::getOffset(uint64_t Offset) const; -template uint64_t InputSectionBase::getOffset(uint64_t Offset) const; +template uint64_t SectionBase::getOffset(uint64_t Offset) const; +template uint64_t SectionBase::getOffset(uint64_t Offset) const; +template uint64_t SectionBase::getOffset(uint64_t Offset) const; +template uint64_t SectionBase::getOffset(uint64_t Offset) const; template size_t InputSectionBase::getSize() const; template size_t InputSectionBase::getSize() const; Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -47,13 +47,13 @@ // If expression is section-relative the function below is used // to get the output section pointer. - std::function Section; + std::function Section; uint64_t operator()(uint64_t Dot) const { return Val(Dot); } operator bool() const { return (bool)Val; } Expr(std::function Val, std::function IsAbsolute, - std::function Section) + std::function Section) : Val(Val), IsAbsolute(IsAbsolute), Section(Section) {} template Expr(T V) : Expr(V, [] { return true; }, [] { return nullptr; }) {} @@ -207,15 +207,15 @@ class LinkerScriptBase { protected: ~LinkerScriptBase() = default; + OutputSection *Aether; public: virtual uint64_t getHeaderSize() = 0; virtual uint64_t getSymbolValue(const Twine &Loc, StringRef S) = 0; virtual bool isDefined(StringRef S) = 0; virtual bool isAbsolute(StringRef S) = 0; - virtual const OutputSection *getSymbolSection(StringRef S) = 0; - virtual const OutputSection *getOutputSection(const Twine &Loc, - StringRef S) = 0; + virtual OutputSection *getSymbolSection(StringRef S) = 0; + virtual OutputSection *getOutputSection(const Twine &Loc, StringRef S) = 0; virtual uint64_t getOutputSectionSize(StringRef S) = 0; }; @@ -268,8 +268,8 @@ uint64_t getSymbolValue(const Twine &Loc, StringRef S) override; bool isDefined(StringRef S) override; bool isAbsolute(StringRef S) override; - const OutputSection *getSymbolSection(StringRef S) override; - const OutputSection *getOutputSection(const Twine &Loc, StringRef S) override; + OutputSection *getSymbolSection(StringRef S) override; + OutputSection *getOutputSection(const Twine &Loc, StringRef S) override; uint64_t getOutputSectionSize(StringRef S) override; std::vector *OutputSections; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -63,21 +63,10 @@ Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); Sym->Binding = STB_GLOBAL; + OutputSection *Sec = + Cmd->Expression.IsAbsolute() ? nullptr : Cmd->Expression.Section(); replaceBody(Sym, Cmd->Name, /*IsLocal=*/false, Visibility, - STT_NOTYPE, 0, 0, nullptr, nullptr); - return Sym->body(); -} - -template static SymbolBody *addSynthetic(SymbolAssignment *Cmd) { - Symbol *Sym; - uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; - const OutputSection *Sec = - ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section(); - std::tie(Sym, std::ignore) = Symtab::X->insert( - Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, - /*File*/ nullptr); - Sym->Binding = STB_GLOBAL; - replaceBody(Sym, Cmd->Name, 0, Sec); + STT_NOTYPE, 0, 0, Sec, nullptr); return Sym->body(); } @@ -119,18 +108,14 @@ if (!Cmd->Sym) return; - if (auto *Body = dyn_cast(Cmd->Sym)) { - Body->Section = Cmd->Expression.Section(); - if (Body->Section) { - uint64_t VA = 0; - if (Body->Section->Flags & SHF_ALLOC) - VA = Body->Section->Addr; - Body->Value = Cmd->Expression(Dot) - VA; - } - return; + auto *Sym = cast(Cmd->Sym); + Sym->Value = Cmd->Expression(Dot); + if (!Cmd->Expression.IsAbsolute()) { + Sym->Section = Cmd->Expression.Section(); + if (auto *Sec = dyn_cast_or_null(Sym->Section)) + if (Sec->Flags & SHF_ALLOC) + Sym->Value -= Sec->Addr; } - - cast(Cmd->Sym)->Value = Cmd->Expression(Dot); } template @@ -144,12 +129,7 @@ if (Cmd->Provide && (!B || B->isDefined())) return; - // Otherwise, create a new symbol if one does not exist or an - // undefined one does exist. - if (Cmd->Expression.IsAbsolute()) - Cmd->Sym = addRegular(Cmd); - else - Cmd->Sym = addSynthetic(Cmd); + Cmd->Sym = addRegular(Cmd); // If there are sections, then let the value be assigned later in // `assignAddresses`. @@ -321,6 +301,19 @@ template void LinkerScript::processCommands(OutputSectionFactory &Factory) { + // A symbol can be assigned before any section is mentioned in the linker + // script. In an DSO, the symbol values are addresses, so the only important + // section values are: + // * SHN_UNDEF + // * SHN_ABS + // * Any value meaning a regular section. + // To handle that, create a dummy aether section that fills the void before + // the linker scripts switches to another section. It has an index of one + // which will map to whatever the first actual section is. + Aether = make("", 0, SHF_ALLOC); + Aether->SectionIndex = 1; + CurOutSec = Aether; + for (unsigned I = 0; I < Opt.Commands.size(); ++I) { auto Iter = Opt.Commands.begin() + I; const std::unique_ptr &Base1 = *Iter; @@ -385,6 +378,7 @@ Factory.addInputSec(S, Cmd->Name); } } + CurOutSec = nullptr; } // Add sections that didn't match any sections command. @@ -772,18 +766,6 @@ void LinkerScript::assignAddresses(std::vector &Phdrs) { // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; - - // A symbol can be assigned before any section is mentioned in the linker - // script. In an DSO, the symbol values are addresses, so the only important - // section values are: - // * SHN_UNDEF - // * SHN_ABS - // * Any value meaning a regular section. - // To handle that, create a dummy aether section that fills the void before - // the linker scripts switches to another section. It has an index of one - // which will map to whatever the first actual section is. - auto *Aether = make("", 0, SHF_ALLOC); - Aether->SectionIndex = 1; switchTo(Aether); for (const std::unique_ptr &Base : Opt.Commands) { @@ -924,8 +906,8 @@ } template -const OutputSection *LinkerScript::getOutputSection(const Twine &Loc, - StringRef Name) { +OutputSection *LinkerScript::getOutputSection(const Twine &Loc, + StringRef Name) { static OutputSection FakeSec("", 0, 0); for (OutputSection *Sec : *OutputSections) @@ -976,7 +958,7 @@ // specific section but isn't absolute at the same time, so we try // to find suitable section for it as well. template -const OutputSection *LinkerScript::getSymbolSection(StringRef S) { +OutputSection *LinkerScript::getSymbolSection(StringRef S) { if (SymbolBody *Sym = Symtab::X->find(S)) return Sym->getOutputSection(); return CurOutSec; @@ -1634,7 +1616,7 @@ static Expr combine(StringRef Op, Expr L, Expr R) { auto IsAbs = [=] { return L.IsAbsolute() && R.IsAbsolute(); }; auto GetOutSec = [=] { - const OutputSection *S = L.Section(); + OutputSection *S = L.Section(); return S ? S : R.Section(); }; Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -72,7 +72,7 @@ typename ELFT::uint Offset = D->Value; if (D->isSection()) Offset += getAddend(Sec, Rel); - return {D->Section->Repl, Offset}; + return {cast(D->Section)->Repl, Offset}; } // Calls Fn for each section that Sec refers to via relocations. @@ -216,7 +216,7 @@ auto MarkSymbol = [&](const SymbolBody *Sym) { if (auto *D = dyn_cast_or_null(Sym)) - Enqueue({D->Section, D->Value}); + Enqueue({cast(D->Section), D->Value}); }; // Add GC root symbols. Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -11,6 +11,7 @@ #define LLD_ELF_OUTPUT_SECTIONS_H #include "Config.h" +#include "InputSection.h" #include "Relocations.h" #include "lld/Core/LLVM.h" @@ -37,10 +38,14 @@ // It is composed of multiple InputSections. // The writer creates multiple OutputSections and assign them unique, // non-overlapping file offsets and VAs. -class OutputSection final { +class OutputSection final : public SectionBase { public: OutputSection(StringRef Name, uint32_t Type, uint64_t Flags); + static bool classof(const SectionBase *S) { + return S->kind() == SectionBase::Output; + } + uint64_t getLMA() const { return Addr + LMAOffset; } template void writeHeaderTo(typename ELFT::Shdr *SHdr); @@ -72,7 +77,6 @@ uint64_t Entsize = 0; uint64_t Addralign = 0; uint64_t Offset = 0; - uint64_t Flags = 0; uint64_t LMAOffset = 0; uint64_t Addr = 0; uint32_t ShName = 0; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -67,7 +67,7 @@ } OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags) - : Name(Name), Addralign(1), Flags(Flags), Type(Type) {} + : SectionBase(Output, Flags), Name(Name), Addralign(1), Type(Type) {} template static bool compareByFilePosition(InputSection *A, InputSection *B) { Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -59,10 +59,7 @@ Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, uintX_t Value, uintX_t Size, uint8_t Binding, - InputSectionBase *Section, InputFile *File); - - Symbol *addSynthetic(StringRef N, const OutputSection *Section, uintX_t Value, - uint8_t StOther); + SectionBase *Section, InputFile *File); void addShared(SharedFile *F, StringRef Name, const Elf_Sym &Sym, const typename ELFT::Verdef *Verdef); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -369,7 +369,8 @@ return; } - std::string OldLoc = D->Section->template getLocation(D->Value); + std::string OldLoc = + cast(D->Section)->template getLocation(D->Value); std::string NewLoc = ErrSec->getLocation(ErrOffset); print(NewLoc + ": duplicate symbol '" + toString(*Existing) + "'"); @@ -377,10 +378,10 @@ } template -Symbol * -SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, - uintX_t Value, uintX_t Size, uint8_t Binding, - InputSectionBase *Section, InputFile *File) { +Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, + uint8_t Type, uintX_t Value, uintX_t Size, + uint8_t Binding, SectionBase *Section, + InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), @@ -391,24 +392,8 @@ replaceBody(S, Name, /*IsLocal=*/false, StOther, Type, Value, Size, Section, File); else if (Cmp == 0) - reportDuplicate(S->body(), Section, Value); - return S; -} - -template -Symbol *SymbolTable::addSynthetic(StringRef N, - const OutputSection *Section, - uintX_t Value, uint8_t StOther) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(N, STT_NOTYPE, getVisibility(StOther), - /*CanOmitFromDynSym*/ false, nullptr); - int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL, - /*IsAbsolute*/ false, /*Value*/ 0); - if (Cmp > 0) - replaceBody(S, N, Value, Section); - else if (Cmp == 0) - reportDuplicate(S->body(), nullptr); + reportDuplicate(S->body(), + dyn_cast_or_null(Section), Value); return S; } Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -43,8 +43,7 @@ DefinedRegularKind = DefinedFirst, SharedKind, DefinedCommonKind, - DefinedSyntheticKind, - DefinedLast = DefinedSyntheticKind, + DefinedLast = DefinedCommonKind, UndefinedKind, LazyArchiveKind, LazyObjectKind, @@ -84,7 +83,7 @@ template typename ELFT::uint getGotPltVA() const; template typename ELFT::uint getPltVA() const; template typename ELFT::uint getSize() const; - template const OutputSection *getOutputSection() const; + template OutputSection *getOutputSection() const; // The file from which this symbol was created. InputFile *File = nullptr; @@ -177,11 +176,10 @@ class DefinedRegular : public Defined { public: DefinedRegular(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type, - uint64_t Value, uint64_t Size, InputSectionBase *Section, + uint64_t Value, uint64_t Size, SectionBase *Section, InputFile *File) : Defined(SymbolBody::DefinedRegularKind, Name, IsLocal, StOther, Type), - Value(Value), Size(Size), - Section(Section ? Section->Repl : NullInputSection) { + Value(Value), Size(Size), Section(Section) { this->File = File; } @@ -194,37 +192,7 @@ uint64_t Value; uint64_t Size; - - // The input section this symbol belongs to. Notice that this is - // a reference to a pointer. We are using two levels of indirections - // because of ICF. If ICF decides two sections need to be merged, it - // manipulates this Section pointers so that they point to the same - // section. This is a bit tricky, so be careful to not be confused. - // If this is null, the symbol is an absolute symbol. - InputSectionBase *&Section; - -private: - static InputSectionBase *NullInputSection; -}; - -// DefinedSynthetic is a class to represent linker-generated ELF symbols. -// The difference from the regular symbol is that DefinedSynthetic symbols -// don't belong to any input files or sections. Thus, its constructor -// takes an output section to calculate output VA, etc. -// If Section is null, this symbol is relative to the image base. -class DefinedSynthetic : public Defined { -public: - DefinedSynthetic(StringRef Name, uint64_t Value, const OutputSection *Section) - : Defined(SymbolBody::DefinedSyntheticKind, Name, /*IsLocal=*/false, - llvm::ELF::STV_HIDDEN, 0 /* Type */), - Value(Value), Section(Section) {} - - static bool classof(const SymbolBody *S) { - return S->kind() == SymbolBody::DefinedSyntheticKind; - } - - uint64_t Value; - const OutputSection *Section; + SectionBase *Section; }; class Undefined : public SymbolBody { @@ -334,16 +302,16 @@ // DefinedRegular symbols. struct ElfSym { // The content for _etext and etext symbols. - static DefinedSynthetic *Etext; - static DefinedSynthetic *Etext2; + static DefinedRegular *Etext; + static DefinedRegular *Etext2; // The content for _edata and edata symbols. - static DefinedSynthetic *Edata; - static DefinedSynthetic *Edata2; + static DefinedRegular *Edata; + static DefinedRegular *Edata2; // The content for _end and end symbols. - static DefinedSynthetic *End; - static DefinedSynthetic *End2; + static DefinedRegular *End; + static DefinedRegular *End2; // The content for _gp_disp/__gnu_local_gp symbols for MIPS target. static DefinedRegular *MipsGpDisp; @@ -395,8 +363,8 @@ // This field is used to store the Symbol's SymbolBody. This instantiation of // AlignedCharArrayUnion gives us a struct with a char array field that is // large and aligned enough to store any derived class of SymbolBody. - llvm::AlignedCharArrayUnion + llvm::AlignedCharArrayUnion Body; SymbolBody *body() { return reinterpret_cast(Body.buffer); } Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -28,14 +28,12 @@ using namespace lld; using namespace lld::elf; -InputSectionBase *DefinedRegular::NullInputSection; - -DefinedSynthetic *ElfSym::Etext; -DefinedSynthetic *ElfSym::Etext2; -DefinedSynthetic *ElfSym::Edata; -DefinedSynthetic *ElfSym::Edata2; -DefinedSynthetic *ElfSym::End; -DefinedSynthetic *ElfSym::End2; +DefinedRegular *ElfSym::Etext; +DefinedRegular *ElfSym::Etext2; +DefinedRegular *ElfSym::Edata; +DefinedRegular *ElfSym::Edata2; +DefinedRegular *ElfSym::End; +DefinedRegular *ElfSym::End2; DefinedRegular *ElfSym::MipsGpDisp; DefinedRegular *ElfSym::MipsLocalGp; DefinedRegular *ElfSym::MipsGp; @@ -45,18 +43,11 @@ typedef typename ELFT::uint uintX_t; switch (Body.kind()) { - case SymbolBody::DefinedSyntheticKind: { - auto &D = cast(Body); - const OutputSection *Sec = D.Section; - if (!Sec) - return D.Value; - if (D.Value == uintX_t(-1)) - return Sec->Addr + Sec->Size; - return Sec->Addr + D.Value; - } case SymbolBody::DefinedRegularKind: { auto &D = cast(Body); - InputSectionBase *IS = D.Section; + SectionBase *IS = D.Section; + if (auto *ISB = dyn_cast_or_null(IS)) + IS = ISB->Repl; // According to the ELF spec reference to a local symbol from outside // the group are not allowed. Unfortunately .eh_frame breaks that rule @@ -209,8 +200,7 @@ return 0; } -template -const OutputSection *SymbolBody::getOutputSection() const { +template OutputSection *SymbolBody::getOutputSection() const { if (auto *S = dyn_cast(this)) { if (S->Section) return S->Section->template getOutputSection(); @@ -229,8 +219,6 @@ return nullptr; } - if (auto *S = dyn_cast(this)) - return S->Section; return nullptr; } @@ -281,7 +269,11 @@ if (!Section || !isFunc()) return false; return (this->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC || - (Section->getFile()->getObj().getHeader()->e_flags & + (cast(Section) + ->template getFile() + ->getObj() + .getHeader() + ->e_flags & EF_MIPS_PIC); } @@ -421,14 +413,10 @@ template uint64_t SymbolBody::template getSize() const; template uint64_t SymbolBody::template getSize() const; -template const OutputSection * - SymbolBody::template getOutputSection() const; -template const OutputSection * - SymbolBody::template getOutputSection() const; -template const OutputSection * - SymbolBody::template getOutputSection() const; -template const OutputSection * - SymbolBody::template getOutputSection() const; +template OutputSection *SymbolBody::template getOutputSection() const; +template OutputSection *SymbolBody::template getOutputSection() const; +template OutputSection *SymbolBody::template getOutputSection() const; +template OutputSection *SymbolBody::template getOutputSection() const; template bool DefinedRegular::template isMipsPIC() const; template bool DefinedRegular::template isMipsPIC() const; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -457,7 +457,8 @@ auto *D = dyn_cast(&B); if (!D || !D->Section) return false; - InputSectionBase *Target = D->Section->Repl; + auto *Target = + cast(cast(D->Section)->Repl); return Target && Target->Live; } @@ -1347,8 +1348,10 @@ // This is used for -r, so we have to handle multiple section // symbols being combined. if (Body->Type == STT_SECTION && E.Symbol->Type == STT_SECTION) - return cast(Body)->Section->OutSec == - cast(E.Symbol)->Section->OutSec; + return cast(Body) + ->Section->template getOutputSection() == + cast(E.Symbol) + ->Section->template getOutputSection(); return false; }); if (I == Symbols.end()) Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -453,7 +453,7 @@ } template -static bool shouldKeepInSymtab(InputSectionBase *Sec, StringRef SymName, +static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, const SymbolBody &B) { if (B.isFile() || B.isSection()) return false; @@ -485,12 +485,17 @@ if (auto *D = dyn_cast(&B)) { // Always include absolute symbols. - if (!D->Section) + SectionBase *Sec = D->Section; + if (!Sec) return true; - // Exclude symbols pointing to garbage-collected sections. - if (!D->Section->Live) - return false; - if (auto *S = dyn_cast>(D->Section)) + if (auto *IS = dyn_cast(Sec)) { + Sec = IS->Repl; + IS = cast(Sec); + // Exclude symbols pointing to garbage-collected sections. + if (!IS->Live) + return false; + } + if (auto *S = dyn_cast>(Sec)) if (!S->getSectionPiece(D->Value)->Live) return false; } @@ -515,7 +520,7 @@ if (!includeInSymtab(*B)) continue; - InputSectionBase *Sec = DR->Section; + SectionBase *Sec = DR->Section; if (!shouldKeepInSymtab(Sec, B->getName(), *B)) continue; In::SymTab->addSymbol(B); @@ -733,35 +738,27 @@ } template -static DefinedSynthetic * -addOptionalSynthetic(StringRef Name, OutputSection *Sec, - typename ELFT::uint Val, uint8_t StOther = STV_HIDDEN) { - if (SymbolBody *S = Symtab::X->find(Name)) - if (!S->isInCurrentDSO()) - return cast( - Symtab::X->addSynthetic(Name, Sec, Val, StOther)->body()); - return nullptr; -} - -template -static Symbol *addRegular(StringRef Name, InputSectionBase *Sec, - typename ELFT::uint Value) { +static Symbol * +addRegular(StringRef Name, SectionBase *Sec, typename ELFT::uint Value, + uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_WEAK) { // The linker generated symbols are added as STB_WEAK to allow user defined // ones to override them. - return Symtab::X->addRegular(Name, STV_HIDDEN, STT_NOTYPE, Value, - /*Size=*/0, STB_WEAK, Sec, + return Symtab::X->addRegular(Name, StOther, STT_NOTYPE, Value, + /*Size=*/0, Binding, Sec, /*File=*/nullptr); } template -static Symbol *addOptionalRegular(StringRef Name, InputSectionBase *IS, - typename ELFT::uint Value) { +static DefinedRegular * +addOptionalRegular(StringRef Name, SectionBase *Sec, typename ELFT::uint Val, + uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) { SymbolBody *S = Symtab::X->find(Name); if (!S) return nullptr; if (S->isInCurrentDSO()) - return S->symbol(); - return addRegular(Name, IS, Value); + return nullptr; + return cast( + addRegular(Name, Sec, Val, StOther, Binding)->body()); } // The beginning and the ending of .rel[a].plt section are marked @@ -774,10 +771,10 @@ if (In::DynSymTab) return; StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular(S, In::RelaIplt, 0); + addOptionalRegular(S, In::RelaIplt, 0, STV_HIDDEN, STB_WEAK); S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end"; - addOptionalRegular(S, In::RelaIplt, -1); + addOptionalRegular(S, In::RelaIplt, -1, STV_HIDDEN, STB_WEAK); } // The linker is expected to define some symbols depending on @@ -837,14 +834,13 @@ return; // __ehdr_start is the location of ELF file headers. - addOptionalSynthetic("__ehdr_start", Out::ElfHeader, 0); + addOptionalRegular("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN); - auto Define = [](StringRef S, DefinedSynthetic *&Sym1, - DefinedSynthetic *&Sym2) { - Sym1 = addOptionalSynthetic(S, nullptr, 0, STV_DEFAULT); + auto Define = [](StringRef S, DefinedRegular *&Sym1, DefinedRegular *&Sym2) { + Sym1 = addOptionalRegular(S, Out::ElfHeader, 0, STV_DEFAULT); assert(S.startswith("_")); S = S.substr(1); - Sym2 = addOptionalSynthetic(S, nullptr, 0, STV_DEFAULT); + Sym2 = addOptionalRegular(S, Out::ElfHeader, 0, STV_DEFAULT); }; Define("_end", ElfSym::End, ElfSym::End2); @@ -880,7 +876,7 @@ SymbolOrder.insert({S, Priority++}); // Build a map from sections to their priorities. - DenseMap SectionOrder; + DenseMap SectionOrder; for (elf::ObjectFile *File : Symtab::X->getObjectFiles()) { for (SymbolBody *Body : File->getSymbols()) { auto *D = dyn_cast(Body); @@ -1193,8 +1189,10 @@ auto Define = [&](StringRef Start, StringRef End, OutputSection *OS) { // These symbols resolve to the image base if the section does not exist. // A special value -1 indicates end of the section. - addOptionalSynthetic(Start, OS, 0); - addOptionalSynthetic(End, OS, OS ? -1 : 0); + if (!OS && Config->pic()) + OS = Out::ElfHeader; + addOptionalRegular(Start, OS, 0); + addOptionalRegular(End, OS, OS ? -1 : 0); }; Define("__preinit_array_start", "__preinit_array_end", Out::PreinitArray); @@ -1215,8 +1213,8 @@ StringRef S = Sec->Name; if (!isValidCIdentifier(S)) return; - addOptionalSynthetic(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); - addOptionalSynthetic(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); + addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); + addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); } template OutputSection *Writer::findSection(StringRef Name) { @@ -1623,7 +1621,7 @@ // to each section. This function fixes some predefined // symbol values that depend on section address and size. template void Writer::fixPredefinedSymbols() { - auto Set = [](DefinedSynthetic *S1, DefinedSynthetic *S2, OutputSection *Sec, + auto Set = [](DefinedRegular *S1, DefinedRegular *S2, OutputSection *Sec, uint64_t Value) { if (S1) { S1->Section = Sec;