Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -34,21 +34,19 @@ template class ObjectFile; class OutputSection; -// This corresponds to a section of an input file. -class InputSectionBase { +class SectionBase { public: - enum Kind { Regular, EHFrame, Merge, Synthetic, }; + enum Kind { Regular, EHFrame, Merge, Synthetic, Output }; Kind kind() const { return (Kind)SectionKind; } - // The file this section is from. - InputFile *File; - - ArrayRef Data; StringRef Name; unsigned SectionKind : 3; + // The next two bit fields are only used by InputSectionBase, but we + // put them here so the struct packs better. + // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. unsigned Live : 1; // for garbage collection @@ -63,12 +61,45 @@ uint32_t Link; uint32_t Info; + OutputSection *getOutputSection(); + const OutputSection *getOutputSection() const { + return const_cast(this)->getOutputSection(); + } + + // Translate an offset in the input section to an offset in the output + // section. + uint64_t getOffset(uint64_t Offset) const; + + uint64_t getOffset(const DefinedRegular &Sym) const; + +protected: + SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags, + uint64_t Entsize, uint64_t Alignment, uint32_t Type, + uint32_t Info, uint32_t Link) + : Name(Name), SectionKind(SectionKind), Alignment(Alignment), + Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info) {} +}; + +// 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; + + ArrayRef Data; uint64_t getOffsetInFile() const; static InputSectionBase Discarded; InputSectionBase() - : SectionKind(Regular), Live(false), Assigned(false), Repl(this) { + : SectionBase(Regular, "", /*Flags*/ 0, /*Entsize*/ 0, /*Alignment*/ 0, + /*Type*/ 0, + /*Info*/ 0, /*Link*/ 0), + Repl(this) { + Live = false; + Assigned = false; NumRelocations = 0; AreRelocsRela = false; } @@ -113,20 +144,13 @@ // Returns the size of this section (even if this is a common or BSS.) size_t getSize() const; - OutputSection *getOutputSection() const; - template ObjectFile *getFile() const; template llvm::object::ELFFile getObj() const { return getFile()->getObj(); } - 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. - uint64_t getOffset(uint64_t Offset) const; template void uncompress(); @@ -165,7 +189,7 @@ template MergeInputSection(ObjectFile *F, const typename ELFT::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. @@ -237,7 +261,7 @@ template EhInputSection(ObjectFile *F, const typename ELFT::Shdr *Header, StringRef Name); - static bool classof(const InputSectionBase *S); + static bool classof(const SectionBase *S); template void split(); template void split(ArrayRef Rels); @@ -267,7 +291,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,11 @@ uint32_t Link, uint32_t Info, uint64_t Alignment, ArrayRef Data, StringRef Name, Kind SectionKind) - : File(File), Data(Data), Name(Name), SectionKind(SectionKind), - Live(!Config->GcSections || !(Flags & SHF_ALLOC)), Assigned(false), - Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info), - Repl(this) { + : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info, + Link), + File(File), Data(Data), Repl(this) { + Live = !Config->GcSections || !(Flags & SHF_ALLOC); + Assigned = false; NumRelocations = 0; AreRelocsRela = false; @@ -99,15 +100,19 @@ return SecStart - FileStart; } -uint64_t InputSectionBase::getOffset(uint64_t Offset) const { +uint64_t SectionBase::getOffset(uint64_t Offset) const { switch (kind()) { + case Output: { + auto *OS = cast(this); + return Offset == uint64_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 == uint64_t(-1) ? getSize() : Offset); + return IS->OutSecOff + (Offset == uint64_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 @@ -122,12 +127,14 @@ llvm_unreachable("invalid section kind"); } -OutputSection *InputSectionBase::getOutputSection() const { +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 @@ -151,7 +158,7 @@ Data = ArrayRef((uint8_t *)OutputBuf, Size); } -uint64_t InputSectionBase::getOffset(const DefinedRegular &Sym) const { +uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const { return getOffset(Sym.Value); } @@ -200,9 +207,13 @@ 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) { + return S->kind() != Output; } template InputSectionBase *InputSection::getRelocatedSection() { @@ -249,14 +260,14 @@ // 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->isRela()) { - 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,7 +599,7 @@ this->Live = true; } -bool EhInputSection::classof(const InputSectionBase *S) { +bool EhInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::EHFrame; } @@ -711,7 +722,7 @@ this->getSectionPiece(Off)->Live = true; } -bool MergeInputSection::classof(const InputSectionBase *S) { +bool MergeInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::Merge; } 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 @@ -78,7 +78,7 @@ typename ELFT::uint Offset = D->Value; if (D->isSection()) Offset += getAddend(Sec, Rel); - Fn({D->Section->Repl, Offset}); + Fn({cast(D->Section)->Repl, Offset}); } else if (auto *U = dyn_cast(&B)) { for (InputSectionBase *Sec : CNamedSections.lookup(U->getName())) Fn({Sec, 0}); @@ -223,7 +223,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); @@ -65,20 +70,12 @@ // formula: Off = Off_first + VA - VA_first. OutputSection *FirstInPtLoad = nullptr; - StringRef Name; - // The following fields correspond to Elf_Shdr members. uint64_t Size = 0; - uint64_t Entsize = 0; uint64_t Offset = 0; - uint64_t Flags = 0; uint64_t LMAOffset = 0; uint64_t Addr = 0; - uint32_t Alignment = 0; uint32_t ShName = 0; - uint32_t Type = 0; - uint32_t Info = 0; - uint32_t Link = 0; void addSection(InputSectionBase *C); void sort(std::function Order); Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -65,7 +65,9 @@ } OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags) - : Name(Name), Flags(Flags), Alignment(1), Type(Type) {} + : SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type, + /*Info*/ 0, + /*Link*/ 0) {} template static bool compareByFilePosition(InputSection *A, InputSection *B) { Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -58,10 +58,7 @@ Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, uint8_t Binding, - InputSectionBase *Section, InputFile *File); - - Symbol *addSynthetic(StringRef N, const OutputSection *Section, - uint64_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, - uint64_t Value, uint64_t Size, uint8_t Binding, - InputSectionBase *Section, InputFile *File) { +Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, + uint8_t Type, uint64_t Value, + uint64_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, - uint64_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; @@ -173,11 +172,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; } @@ -190,37 +188,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 { @@ -327,16 +295,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; @@ -388,8 +356,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; @@ -43,18 +41,11 @@ template static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) { switch (Body.kind()) { - case SymbolBody::DefinedSyntheticKind: { - auto &D = cast(Body); - const OutputSection *Sec = D.Section; - if (!Sec) - return D.Value; - if (D.Value == uint64_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 @@ -202,8 +193,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->getOutputSection(); @@ -219,8 +209,6 @@ return nullptr; } - if (auto *S = dyn_cast(this)) - return S->Section; return nullptr; } @@ -271,7 +259,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); } @@ -411,14 +403,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 @@ -467,7 +467,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; } @@ -1364,8 +1365,8 @@ // 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->getOutputSection() == + cast(E.Symbol)->Section->getOutputSection(); return false; }); if (I == Symbols.end()) Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -454,7 +454,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; @@ -486,12 +486,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; } @@ -516,7 +521,7 @@ if (!includeInSymtab(*B)) continue; - InputSectionBase *Sec = DR->Section; + SectionBase *Sec = DR->Section; if (!shouldKeepInSymtab(Sec, B->getName(), *B)) continue; In::SymTab->addSymbol(B); @@ -734,35 +739,27 @@ } template -static DefinedSynthetic *addOptionalSynthetic(StringRef Name, - OutputSection *Sec, uint64_t 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, - uint64_t Value) { +static Symbol *addRegular(StringRef Name, SectionBase *Sec, uint64_t 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, - uint64_t Value) { +static DefinedRegular * +addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t 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 @@ -775,10 +772,10 @@ if (In::DynSymTab) return; StringRef S = Config->isRela() ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular(S, In::RelaIplt, 0); + addOptionalRegular(S, In::RelaIplt, 0, STV_HIDDEN, STB_WEAK); S = Config->isRela() ? "__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 @@ -838,14 +835,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); @@ -881,7 +877,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); @@ -1200,8 +1196,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); @@ -1222,8 +1220,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) { @@ -1630,7 +1628,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;