diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2017-03-08 22:36:28 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2017-03-08 22:36:28 +0000 |
commit | 5616adf65552eea6988b23ba266baf432209cac4 (patch) | |
tree | f7b9379dc4ba1c76fe43a832019f159f64c34ce9 | |
parent | e37b32c4334612ea4597202c0b6d6713618fe26a (diff) | |
download | bcm5719-llvm-5616adf65552eea6988b23ba266baf432209cac4.tar.gz bcm5719-llvm-5616adf65552eea6988b23ba266baf432209cac4.zip |
Remove DefinedSynthetic.
With this we have a single section hierarchy. It is a bit less code,
but the main advantage will be in a future patch being able to handle
foo = symbol_in_obj;
in a linker script. Currently that fails since we try to find the
output section of symbol_in_obj. With this we should be able to just
return an InputSection from the expression.
llvm-svn: 297313
-rw-r--r-- | lld/ELF/InputSection.cpp | 50 | ||||
-rw-r--r-- | lld/ELF/InputSection.h | 67 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 76 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 14 | ||||
-rw-r--r-- | lld/ELF/MarkLive.cpp | 4 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 4 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 15 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 31 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.h | 5 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 50 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 58 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.cpp | 7 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 76 |
13 files changed, 209 insertions, 248 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index a620d023e4c..eba84fd9bc4 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -55,10 +55,11 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, uint32_t Link, uint32_t Info, uint32_t Alignment, ArrayRef<uint8_t> 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; @@ -98,15 +99,20 @@ uint64_t InputSectionBase::getOffsetInFile() const { 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<OutputSection>(this); + // For output sections we treat offset -1 as the end of the section. + return Offset == uint64_t(-1) ? OS->Size : Offset; + } case Regular: return cast<InputSection>(this)->OutSecOff + Offset; - case Synthetic: + case Synthetic: { + auto *IS = cast<InputSection>(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<InputSection>(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 @@ -121,12 +127,14 @@ uint64_t InputSectionBase::getOffset(uint64_t Offset) const { llvm_unreachable("invalid section kind"); } -OutputSection *InputSectionBase::getOutputSection() const { +OutputSection *SectionBase::getOutputSection() { + if (auto *IS = dyn_cast<InputSection>(this)) + return IS->OutSec; if (auto *MS = dyn_cast<MergeInputSection>(this)) return MS->MergeSec ? MS->MergeSec->OutSec : nullptr; if (auto *EH = dyn_cast<EhInputSection>(this)) return EH->EHSec->OutSec; - return OutSec; + return cast<OutputSection>(this); } // Uncompress section contents. Note that this function is called @@ -150,7 +158,7 @@ template <class ELFT> void InputSectionBase::uncompress() { Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size); } -uint64_t InputSectionBase::getOffset(const DefinedRegular &Sym) const { +uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const { return getOffset(Sym.Value); } @@ -199,9 +207,13 @@ InputSection::InputSection(elf::ObjectFile<ELFT> *F, 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 <class ELFT> InputSectionBase *InputSection::getRelocatedSection() { @@ -248,14 +260,14 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { // 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<DefinedRegular>(Body).Section; + SectionBase *Section = cast<DefinedRegular>(Body).Section; if (Section == &InputSection::Discarded) { P->setSymbolAndType(0, 0, false); continue; } if (Config->isRela()) { - P->r_addend += Body.getVA<ELFT>() - Section->OutSec->Addr; + P->r_addend += Body.getVA<ELFT>() - Section->getOutputSection()->Addr; } else if (Config->Relocatable) { const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset; RelocatedSection->Relocations.push_back( @@ -587,7 +599,7 @@ EhInputSection::EhInputSection(elf::ObjectFile<ELFT> *F, this->Live = true; } -bool EhInputSection::classof(const InputSectionBase *S) { +bool EhInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::EHFrame; } @@ -710,7 +722,7 @@ void MergeInputSection::splitIntoPieces() { this->getSectionPiece(Off)->Live = true; } -bool MergeInputSection::classof(const InputSectionBase *S) { +bool MergeInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::Merge; } diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index b243d912082..4a5b1af56c3 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -34,21 +34,23 @@ class MergeSyntheticSection; template <class ELFT> class ObjectFile; class OutputSection; -// This corresponds to a section of an input file. -class InputSectionBase { +// This is the base class of all sections that lld handles. Some are sections in +// input files, some are sections in the produced output file and some exist +// just as a convenience for implementing special ways of combining some +// sections. +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<uint8_t> 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 +65,48 @@ public: uint32_t Link; uint32_t Info; + OutputSection *getOutputSection(); + const OutputSection *getOutputSection() const { + return const_cast<SectionBase *>(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) { + Live = false; + Assigned = false; + } +}; + +// 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<uint8_t> 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 +151,13 @@ public: // Returns the size of this section (even if this is a common or BSS.) size_t getSize() const; - OutputSection *getOutputSection() const; - template <class ELFT> ObjectFile<ELFT> *getFile() const; template <class ELFT> llvm::object::ELFFile<ELFT> getObj() const { return getFile<ELFT>()->getObj(); } - uint64_t getOffset(const DefinedRegular &Sym) const; - template <class ELFT> 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 <class ELFT> void uncompress(); @@ -165,7 +196,7 @@ public: template <class ELFT> MergeInputSection(ObjectFile<ELFT> *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 +268,7 @@ public: template <class ELFT> EhInputSection(ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header, StringRef Name); - static bool classof(const InputSectionBase *S); + static bool classof(const SectionBase *S); template <class ELFT> void split(); template <class ELFT, class RelTy> void split(ArrayRef<RelTy> Rels); @@ -267,7 +298,7 @@ public: // to. The writer sets a value. uint64_t OutSecOff = 0; - static bool classof(const InputSectionBase *S); + static bool classof(const SectionBase *S); template <class ELFT> InputSectionBase *getRelocatedSection(); diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 45727ee96cb..0e60c2769ed 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -63,21 +63,10 @@ template <class ELFT> static SymbolBody *addRegular(SymbolAssignment *Cmd) { Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); Sym->Binding = STB_GLOBAL; + OutputSection *Sec = + Cmd->Expression.IsAbsolute() ? nullptr : Cmd->Expression.Section(); replaceBody<DefinedRegular>(Sym, Cmd->Name, /*IsLocal=*/false, Visibility, - STT_NOTYPE, 0, 0, nullptr, nullptr); - return Sym->body(); -} - -template <class ELFT> 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<ELFT>::X->insert( - Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, - /*File*/ nullptr); - Sym->Binding = STB_GLOBAL; - replaceBody<DefinedSynthetic>(Sym, Cmd->Name, 0, Sec); + STT_NOTYPE, 0, 0, Sec, nullptr); return Sym->body(); } @@ -119,18 +108,14 @@ void LinkerScript<ELFT>::assignSymbol(SymbolAssignment *Cmd, bool InSec) { if (!Cmd->Sym) return; - if (auto *Body = dyn_cast<DefinedSynthetic>(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<DefinedRegular>(Cmd->Sym); + Sym->Value = Cmd->Expression(Dot); + if (!Cmd->Expression.IsAbsolute()) { + Sym->Section = Cmd->Expression.Section(); + if (auto *Sec = dyn_cast_or_null<OutputSection>(Sym->Section)) + if (Sec->Flags & SHF_ALLOC) + Sym->Value -= Sec->Addr; } - - cast<DefinedRegular>(Cmd->Sym)->Value = Cmd->Expression(Dot); } template <class ELFT> @@ -144,12 +129,7 @@ void LinkerScript<ELFT>::addSymbol(SymbolAssignment *Cmd) { 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<ELFT>(Cmd); - else - Cmd->Sym = addSynthetic<ELFT>(Cmd); + Cmd->Sym = addRegular<ELFT>(Cmd); // If there are sections, then let the value be assigned later in // `assignAddresses`. @@ -321,6 +301,19 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) { template <class ELFT> void LinkerScript<ELFT>::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<OutputSection>("", 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<BaseCommand> &Base1 = *Iter; @@ -385,6 +378,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory &Factory) { Factory.addInputSec<ELFT>(S, Cmd->Name); } } + CurOutSec = nullptr; } // Add sections that didn't match any sections command. @@ -772,18 +766,6 @@ template <class ELFT> void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry> &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<OutputSection>("", 0, SHF_ALLOC); - Aether->SectionIndex = 1; switchTo(Aether); for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) { @@ -924,8 +906,8 @@ template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() { } template <class ELFT> -const OutputSection *LinkerScript<ELFT>::getOutputSection(const Twine &Loc, - StringRef Name) { +OutputSection *LinkerScript<ELFT>::getOutputSection(const Twine &Loc, + StringRef Name) { static OutputSection FakeSec("", 0, 0); for (OutputSection *Sec : *OutputSections) @@ -976,7 +958,7 @@ template <class ELFT> bool LinkerScript<ELFT>::isAbsolute(StringRef S) { // specific section but isn't absolute at the same time, so we try // to find suitable section for it as well. template <class ELFT> -const OutputSection *LinkerScript<ELFT>::getSymbolSection(StringRef S) { +OutputSection *LinkerScript<ELFT>::getSymbolSection(StringRef S) { if (SymbolBody *Sym = Symtab<ELFT>::X->find(S)) return Sym->getOutputSection<ELFT>(); return CurOutSec; @@ -1634,7 +1616,7 @@ Expr ScriptParser::readExpr() { 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(); }; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index bf3dd182cc8..829592e50a2 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -47,13 +47,13 @@ struct Expr { // If expression is section-relative the function below is used // to get the output section pointer. - std::function<const OutputSection *()> Section; + std::function<OutputSection *()> Section; uint64_t operator()(uint64_t Dot) const { return Val(Dot); } operator bool() const { return (bool)Val; } Expr(std::function<uint64_t(uint64_t)> Val, std::function<bool()> IsAbsolute, - std::function<const OutputSection *()> Section) + std::function<OutputSection *()> Section) : Val(Val), IsAbsolute(IsAbsolute), Section(Section) {} template <typename T> Expr(T V) : Expr(V, [] { return true; }, [] { return nullptr; }) {} @@ -207,15 +207,15 @@ struct MemoryRegion { 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 @@ public: 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<OutputSection *> *OutputSections; diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 7a6c982047b..e1bc64d925c 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -78,7 +78,7 @@ static void resolveReloc(InputSectionBase &Sec, RelT &Rel, typename ELFT::uint Offset = D->Value; if (D->isSection()) Offset += getAddend<ELFT>(Sec, Rel); - Fn({D->Section->Repl, Offset}); + Fn({cast<InputSectionBase>(D->Section)->Repl, Offset}); } else if (auto *U = dyn_cast<Undefined>(&B)) { for (InputSectionBase *Sec : CNamedSections.lookup(U->getName())) Fn({Sec, 0}); @@ -223,7 +223,7 @@ template <class ELFT> void elf::markLive() { auto MarkSymbol = [&](const SymbolBody *Sym) { if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym)) - Enqueue({D->Section, D->Value}); + Enqueue({cast<InputSectionBase>(D->Section), D->Value}); }; // Add GC root symbols. diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 544a6d08798..81a945407a9 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -67,7 +67,9 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) { } 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 <typename ELFT> static bool compareByFilePosition(InputSection *A, InputSection *B) { diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 63c8dce72ab..e23f740b65b 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/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 @@ class DefinedRegular; // 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 <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr); @@ -65,20 +70,12 @@ public: // 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<int(InputSectionBase *S)> Order); diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 9105253b897..c3179d9cba8 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -369,7 +369,8 @@ static void reportDuplicate(SymbolBody *Existing, InputSectionBase *ErrSec, return; } - std::string OldLoc = D->Section->template getLocation<ELFT>(D->Value); + std::string OldLoc = + cast<InputSectionBase>(D->Section)->template getLocation<ELFT>(D->Value); std::string NewLoc = ErrSec->getLocation<ELFT>(ErrOffset); print(NewLoc + ": duplicate symbol '" + toString(*Existing) + "'"); @@ -377,10 +378,10 @@ static void reportDuplicate(SymbolBody *Existing, InputSectionBase *ErrSec, } template <typename ELFT> -Symbol * -SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, - uint64_t Value, uint64_t Size, uint8_t Binding, - InputSectionBase *Section, InputFile *File) { +Symbol *SymbolTable<ELFT>::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 @@ SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, Value, Size, Section, File); else if (Cmp == 0) - reportDuplicate<ELFT>(S->body(), Section, Value); - return S; -} - -template <typename ELFT> -Symbol *SymbolTable<ELFT>::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<ELFT>(S, WasInserted, STB_GLOBAL, - /*IsAbsolute*/ false, /*Value*/ 0); - if (Cmp > 0) - replaceBody<DefinedSynthetic>(S, N, Value, Section); - else if (Cmp == 0) - reportDuplicate(S->body(), nullptr); + reportDuplicate<ELFT>(S->body(), + dyn_cast_or_null<InputSectionBase>(Section), Value); return S; } diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index f6a2b1151f6..a5395f5beaa 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -58,10 +58,7 @@ public: 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<ELFT> *F, StringRef Name, const Elf_Sym &Sym, const typename ELFT::Verdef *Verdef); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 178c5e85b62..56607e9b6c6 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -28,14 +28,12 @@ using namespace llvm::ELF; 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 @@ DefinedRegular *ElfSym::MipsGp; template <class ELFT> static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) { switch (Body.kind()) { - case SymbolBody::DefinedSyntheticKind: { - auto &D = cast<DefinedSynthetic>(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<DefinedRegular>(Body); - InputSectionBase *IS = D.Section; + SectionBase *IS = D.Section; + if (auto *ISB = dyn_cast_or_null<InputSectionBase>(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 @@ -207,8 +198,7 @@ template <class ELFT> typename ELFT::uint SymbolBody::getSize() const { return 0; } -template <class ELFT> -const OutputSection *SymbolBody::getOutputSection() const { +template <class ELFT> OutputSection *SymbolBody::getOutputSection() const { if (auto *S = dyn_cast<DefinedRegular>(this)) { if (S->Section) return S->Section->getOutputSection(); @@ -227,8 +217,6 @@ const OutputSection *SymbolBody::getOutputSection() const { return nullptr; } - if (auto *S = dyn_cast<DefinedSynthetic>(this)) - return S->Section; return nullptr; } @@ -279,7 +267,11 @@ template <class ELFT> bool DefinedRegular::isMipsPIC() const { if (!Section || !isFunc()) return false; return (this->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC || - (Section->getFile<ELFT>()->getObj().getHeader()->e_flags & + (cast<InputSectionBase>(Section) + ->template getFile<ELFT>() + ->getObj() + .getHeader() + ->e_flags & EF_MIPS_PIC); } @@ -419,14 +411,10 @@ template uint32_t SymbolBody::template getSize<ELF32BE>() const; template uint64_t SymbolBody::template getSize<ELF64LE>() const; template uint64_t SymbolBody::template getSize<ELF64BE>() const; -template const OutputSection * - SymbolBody::template getOutputSection<ELF32LE>() const; -template const OutputSection * - SymbolBody::template getOutputSection<ELF32BE>() const; -template const OutputSection * - SymbolBody::template getOutputSection<ELF64LE>() const; -template const OutputSection * - SymbolBody::template getOutputSection<ELF64BE>() const; +template OutputSection *SymbolBody::template getOutputSection<ELF32LE>() const; +template OutputSection *SymbolBody::template getOutputSection<ELF32BE>() const; +template OutputSection *SymbolBody::template getOutputSection<ELF64LE>() const; +template OutputSection *SymbolBody::template getOutputSection<ELF64BE>() const; template bool DefinedRegular::template isMipsPIC<ELF32LE>() const; template bool DefinedRegular::template isMipsPIC<ELF32BE>() const; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 79bce2dd456..b1159963392 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -43,8 +43,7 @@ public: DefinedRegularKind = DefinedFirst, SharedKind, DefinedCommonKind, - DefinedSyntheticKind, - DefinedLast = DefinedSyntheticKind, + DefinedLast = DefinedCommonKind, UndefinedKind, LazyArchiveKind, LazyObjectKind, @@ -84,7 +83,7 @@ public: template <class ELFT> typename ELFT::uint getGotPltVA() const; template <class ELFT> typename ELFT::uint getPltVA() const; template <class ELFT> typename ELFT::uint getSize() const; - template <class ELFT> const OutputSection *getOutputSection() const; + template <class ELFT> OutputSection *getOutputSection() const; // The file from which this symbol was created. InputFile *File = nullptr; @@ -177,11 +176,10 @@ public: 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 @@ public: 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 @@ public: // 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 @@ struct Symbol { // 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<DefinedCommon, DefinedRegular, DefinedSynthetic, - Undefined, SharedSymbol, LazyArchive, LazyObject> + llvm::AlignedCharArrayUnion<DefinedCommon, DefinedRegular, Undefined, + SharedSymbol, LazyArchive, LazyObject> Body; SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 75649954980..a642345b6f5 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -460,7 +460,8 @@ bool EhFrameSection<ELFT>::isFdeLive(EhSectionPiece &Piece, auto *D = dyn_cast<DefinedRegular>(&B); if (!D || !D->Section) return false; - InputSectionBase *Target = D->Section->Repl; + auto *Target = + cast<InputSectionBase>(cast<InputSectionBase>(D->Section)->Repl); return Target && Target->Live; } @@ -1357,8 +1358,8 @@ size_t SymbolTableSection<ELFT>::getSymbolIndex(SymbolBody *Body) { // 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<DefinedRegular>(Body)->Section->OutSec == - cast<DefinedRegular>(E.Symbol)->Section->OutSec; + return cast<DefinedRegular>(Body)->Section->getOutputSection() == + cast<DefinedRegular>(E.Symbol)->Section->getOutputSection(); return false; }); if (I == Symbols.end()) diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index bcd6a0d434f..ce8f19eef55 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -453,7 +453,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { } template <class ELFT> -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 @@ template <class ELFT> static bool includeInSymtab(const SymbolBody &B) { if (auto *D = dyn_cast<DefinedRegular>(&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<MergeInputSection>(D->Section)) + if (auto *IS = dyn_cast<InputSectionBase>(Sec)) { + Sec = IS->Repl; + IS = cast<InputSectionBase>(Sec); + // Exclude symbols pointing to garbage-collected sections. + if (!IS->Live) + return false; + } + if (auto *S = dyn_cast<MergeInputSection>(Sec)) if (!S->getSectionPiece(D->Value)->Live) return false; } @@ -515,7 +520,7 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { if (!includeInSymtab<ELFT>(*B)) continue; - InputSectionBase *Sec = DR->Section; + SectionBase *Sec = DR->Section; if (!shouldKeepInSymtab<ELFT>(Sec, B->getName(), *B)) continue; In<ELFT>::SymTab->addSymbol(B); @@ -733,35 +738,27 @@ void PhdrEntry::add(OutputSection *Sec) { } template <class ELFT> -static DefinedSynthetic *addOptionalSynthetic(StringRef Name, - OutputSection *Sec, uint64_t Val, - uint8_t StOther = STV_HIDDEN) { - if (SymbolBody *S = Symtab<ELFT>::X->find(Name)) - if (!S->isInCurrentDSO()) - return cast<DefinedSynthetic>( - Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther)->body()); - return nullptr; -} - -template <class ELFT> -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<ELFT>::X->addRegular(Name, STV_HIDDEN, STT_NOTYPE, Value, - /*Size=*/0, STB_WEAK, Sec, + return Symtab<ELFT>::X->addRegular(Name, StOther, STT_NOTYPE, Value, + /*Size=*/0, Binding, Sec, /*File=*/nullptr); } template <class ELFT> -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<ELFT>::X->find(Name); if (!S) return nullptr; if (S->isInCurrentDSO()) - return S->symbol(); - return addRegular<ELFT>(Name, IS, Value); + return nullptr; + return cast<DefinedRegular>( + addRegular<ELFT>(Name, Sec, Val, StOther, Binding)->body()); } // The beginning and the ending of .rel[a].plt section are marked @@ -774,10 +771,10 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { if (In<ELFT>::DynSymTab) return; StringRef S = Config->isRela() ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0); + addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0, STV_HIDDEN, STB_WEAK); S = Config->isRela() ? "__rela_iplt_end" : "__rel_iplt_end"; - addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1); + addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1, STV_HIDDEN, STB_WEAK); } // The linker is expected to define some symbols depending on @@ -837,14 +834,13 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() { return; // __ehdr_start is the location of ELF file headers. - addOptionalSynthetic<ELFT>("__ehdr_start", Out::ElfHeader, 0); + addOptionalRegular<ELFT>("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN); - auto Define = [](StringRef S, DefinedSynthetic *&Sym1, - DefinedSynthetic *&Sym2) { - Sym1 = addOptionalSynthetic<ELFT>(S, nullptr, 0, STV_DEFAULT); + auto Define = [](StringRef S, DefinedRegular *&Sym1, DefinedRegular *&Sym2) { + Sym1 = addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT); assert(S.startswith("_")); S = S.substr(1); - Sym2 = addOptionalSynthetic<ELFT>(S, nullptr, 0, STV_DEFAULT); + Sym2 = addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT); }; Define("_end", ElfSym::End, ElfSym::End2); @@ -880,7 +876,7 @@ static void sortBySymbolsOrder(ArrayRef<OutputSection *> OutputSections) { SymbolOrder.insert({S, Priority++}); // Build a map from sections to their priorities. - DenseMap<InputSectionBase *, int> SectionOrder; + DenseMap<SectionBase *, int> SectionOrder; for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) { for (SymbolBody *Body : File->getSymbols()) { auto *D = dyn_cast<DefinedRegular>(Body); @@ -1208,8 +1204,10 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { 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<ELFT>(Start, OS, 0); - addOptionalSynthetic<ELFT>(End, OS, OS ? -1 : 0); + if (!OS && Config->pic()) + OS = Out::ElfHeader; + addOptionalRegular<ELFT>(Start, OS, 0); + addOptionalRegular<ELFT>(End, OS, OS ? -1 : 0); }; Define("__preinit_array_start", "__preinit_array_end", Out::PreinitArray); @@ -1230,8 +1228,8 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) { StringRef S = Sec->Name; if (!isValidCIdentifier(S)) return; - addOptionalSynthetic<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); - addOptionalSynthetic<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); + addOptionalRegular<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); + addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); } template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) { @@ -1638,7 +1636,7 @@ static uint16_t getELFType() { // to each section. This function fixes some predefined // symbol values that depend on section address and size. template <class ELFT> void Writer<ELFT>::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; |