| //===- InputSection.h -------------------------------------------*- C++ -*-===// | 
 | // | 
 | //                             The LLVM Linker | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #ifndef LLD_ELF_INPUT_SECTION_H | 
 | #define LLD_ELF_INPUT_SECTION_H | 
 |  | 
 | #include "Config.h" | 
 | #include "Relocations.h" | 
 | #include "Thunks.h" | 
 | #include "lld/Common/LLVM.h" | 
 | #include "llvm/ADT/CachedHashString.h" | 
 | #include "llvm/ADT/DenseSet.h" | 
 | #include "llvm/ADT/TinyPtrVector.h" | 
 | #include "llvm/Object/ELF.h" | 
 |  | 
 | namespace lld { | 
 | namespace elf { | 
 |  | 
 | class Symbol; | 
 | struct SectionPiece; | 
 |  | 
 | class Defined; | 
 | class SyntheticSection; | 
 | class MergeSyntheticSection; | 
 | template <class ELFT> class ObjFile; | 
 | class OutputSection; | 
 |  | 
 | // 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, Output }; | 
 |  | 
 |   Kind kind() const { return (Kind)SectionKind; } | 
 |  | 
 |   StringRef Name; | 
 |  | 
 |   // This pointer points to the "real" instance of this instance. | 
 |   // Usually Repl == this. However, if ICF merges two sections, | 
 |   // Repl pointer of one section points to another section. So, | 
 |   // if you need to get a pointer to this instance, do not use | 
 |   // this but instead this->Repl. | 
 |   SectionBase *Repl; | 
 |  | 
 |   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; | 
 |  | 
 |   unsigned Bss : 1; | 
 |  | 
 |   // Set for sections that should not be folded by ICF. | 
 |   unsigned KeepUnique : 1; | 
 |  | 
 |   // These corresponds to the fields in Elf_Shdr. | 
 |   uint32_t Alignment; | 
 |   uint64_t Flags; | 
 |   uint64_t Entsize; | 
 |   uint32_t Type; | 
 |   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 getVA(uint64_t Offset = 0) 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), Repl(this), SectionKind(SectionKind), Live(false), | 
 |         Bss(false), KeepUnique(false), 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: | 
 |   template <class ELFT> | 
 |   InputSectionBase(ObjFile<ELFT> &File, const typename ELFT::Shdr &Header, | 
 |                    StringRef Name, Kind SectionKind); | 
 |  | 
 |   InputSectionBase(InputFile *File, uint64_t Flags, uint32_t Type, | 
 |                    uint64_t Entsize, uint32_t Link, uint32_t Info, | 
 |                    uint32_t Alignment, ArrayRef<uint8_t> Data, StringRef Name, | 
 |                    Kind SectionKind); | 
 |  | 
 |   static bool classof(const SectionBase *S) { return S->kind() != Output; } | 
 |  | 
 |   // The file which contains this section. Its dynamic type is always | 
 |   // ObjFile<ELFT>, but in order to avoid ELFT, we use InputFile as | 
 |   // its static type. | 
 |   InputFile *File; | 
 |  | 
 |   template <class ELFT> ObjFile<ELFT> *getFile() const { | 
 |     return cast_or_null<ObjFile<ELFT>>(File); | 
 |   } | 
 |  | 
 |   ArrayRef<uint8_t> Data; | 
 |   uint64_t getOffsetInFile() const; | 
 |  | 
 |   // True if this section has already been placed to a linker script | 
 |   // output section. This is needed because, in a linker script, you | 
 |   // can refer to the same section more than once. For example, in | 
 |   // the following linker script, | 
 |   // | 
 |   //   .foo : { *(.text) } | 
 |   //   .bar : { *(.text) } | 
 |   // | 
 |   // .foo takes all .text sections, and .bar becomes empty. To achieve | 
 |   // this, we need to memorize whether a section has been placed or | 
 |   // not for each input section. | 
 |   bool Assigned = false; | 
 |  | 
 |   // Input sections are part of an output section. Special sections | 
 |   // like .eh_frame and merge sections are first combined into a | 
 |   // synthetic section that is then added to an output section. In all | 
 |   // cases this points one level up. | 
 |   SectionBase *Parent = nullptr; | 
 |  | 
 |   // Relocations that refer to this section. | 
 |   const void *FirstRelocation = nullptr; | 
 |   unsigned NumRelocations : 31; | 
 |   unsigned AreRelocsRela : 1; | 
 |  | 
 |   template <class ELFT> ArrayRef<typename ELFT::Rel> rels() const { | 
 |     assert(!AreRelocsRela); | 
 |     return llvm::makeArrayRef( | 
 |         static_cast<const typename ELFT::Rel *>(FirstRelocation), | 
 |         NumRelocations); | 
 |   } | 
 |  | 
 |   template <class ELFT> ArrayRef<typename ELFT::Rela> relas() const { | 
 |     assert(AreRelocsRela); | 
 |     return llvm::makeArrayRef( | 
 |         static_cast<const typename ELFT::Rela *>(FirstRelocation), | 
 |         NumRelocations); | 
 |   } | 
 |  | 
 |   // InputSections that are dependent on us (reverse dependency for GC) | 
 |   llvm::TinyPtrVector<InputSection *> DependentSections; | 
 |  | 
 |   // Returns the size of this section (even if this is a common or BSS.) | 
 |   size_t getSize() const; | 
 |  | 
 |   InputSection *getLinkOrderDep() const; | 
 |  | 
 |   // Get the function symbol that encloses this offset from within the | 
 |   // section. | 
 |   template <class ELFT> | 
 |   Defined *getEnclosingFunction(uint64_t Offset); | 
 |  | 
 |   // Compilers emit zlib-compressed debug sections if the -gz option | 
 |   // is given. This function checks if this section is compressed, and | 
 |   // if so, decompress in memory. | 
 |   void maybeDecompress(); | 
 |  | 
 |   // Returns a source location string. Used to construct an error message. | 
 |   template <class ELFT> std::string getLocation(uint64_t Offset); | 
 |   std::string getSrcMsg(const Symbol &Sym, uint64_t Offset); | 
 |   std::string getObjMsg(uint64_t Offset); | 
 |  | 
 |   // Each section knows how to relocate itself. These functions apply | 
 |   // relocations, assuming that Buf points to this section's copy in | 
 |   // the mmap'ed output buffer. | 
 |   template <class ELFT> void relocate(uint8_t *Buf, uint8_t *BufEnd); | 
 |   void relocateAlloc(uint8_t *Buf, uint8_t *BufEnd); | 
 |  | 
 |   // The native ELF reloc data type is not very convenient to handle. | 
 |   // So we convert ELF reloc records to our own records in Relocations.cpp. | 
 |   // This vector contains such "cooked" relocations. | 
 |   std::vector<Relocation> Relocations; | 
 |  | 
 |   // A function compiled with -fsplit-stack calling a function | 
 |   // compiled without -fsplit-stack needs its prologue adjusted. Find | 
 |   // such functions and adjust their prologues.  This is very similar | 
 |   // to relocation. See https://gcc.gnu.org/wiki/SplitStacks for more | 
 |   // information. | 
 |   template <typename ELFT> | 
 |   void adjustSplitStackFunctionPrologues(uint8_t *Buf, uint8_t *End); | 
 |  | 
 |  | 
 |   template <typename T> llvm::ArrayRef<T> getDataAs() const { | 
 |     size_t S = Data.size(); | 
 |     assert(S % sizeof(T) == 0); | 
 |     return llvm::makeArrayRef<T>((const T *)Data.data(), S / sizeof(T)); | 
 |   } | 
 |  | 
 | private: | 
 |   // A pointer that owns decompressed data if a section is compressed by zlib. | 
 |   // Since the feature is not used often, this is usually a nullptr. | 
 |   std::unique_ptr<char[]> DecompressBuf; | 
 | }; | 
 |  | 
 | // SectionPiece represents a piece of splittable section contents. | 
 | // We allocate a lot of these and binary search on them. This means that they | 
 | // have to be as compact as possible, which is why we don't store the size (can | 
 | // be found by looking at the next one). | 
 | struct SectionPiece { | 
 |   SectionPiece(size_t Off, uint32_t Hash, bool Live) | 
 |       : InputOff(Off), Hash(Hash), OutputOff(0), | 
 |         Live(Live || !Config->GcSections) {} | 
 |  | 
 |   uint32_t InputOff; | 
 |   uint32_t Hash; | 
 |   int64_t OutputOff : 63; | 
 |   uint64_t Live : 1; | 
 | }; | 
 |  | 
 | static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big"); | 
 |  | 
 | // This corresponds to a SHF_MERGE section of an input file. | 
 | class MergeInputSection : public InputSectionBase { | 
 | public: | 
 |   template <class ELFT> | 
 |   MergeInputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header, | 
 |                     StringRef Name); | 
 |   MergeInputSection(uint64_t Flags, uint32_t Type, uint64_t Entsize, | 
 |                     ArrayRef<uint8_t> Data, StringRef Name); | 
 |  | 
 |   static bool classof(const SectionBase *S) { return S->kind() == Merge; } | 
 |   void splitIntoPieces(); | 
 |  | 
 |   // Translate an offset in the input section to an offset in the parent | 
 |   // MergeSyntheticSection. | 
 |   uint64_t getParentOffset(uint64_t Offset) const; | 
 |  | 
 |   // Splittable sections are handled as a sequence of data | 
 |   // rather than a single large blob of data. | 
 |   std::vector<SectionPiece> Pieces; | 
 |   llvm::DenseMap<uint32_t, uint32_t> OffsetMap; | 
 |  | 
 |   // Returns I'th piece's data. This function is very hot when | 
 |   // string merging is enabled, so we want to inline. | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   llvm::CachedHashStringRef getData(size_t I) const { | 
 |     size_t Begin = Pieces[I].InputOff; | 
 |     size_t End = | 
 |         (Pieces.size() - 1 == I) ? Data.size() : Pieces[I + 1].InputOff; | 
 |     return {toStringRef(Data.slice(Begin, End - Begin)), Pieces[I].Hash}; | 
 |   } | 
 |  | 
 |   // Returns the SectionPiece at a given input section offset. | 
 |   SectionPiece *getSectionPiece(uint64_t Offset); | 
 |   const SectionPiece *getSectionPiece(uint64_t Offset) const { | 
 |     return const_cast<MergeInputSection *>(this)->getSectionPiece(Offset); | 
 |   } | 
 |  | 
 |   SyntheticSection *getParent() const; | 
 |  | 
 | private: | 
 |   void splitStrings(ArrayRef<uint8_t> A, size_t Size); | 
 |   void splitNonStrings(ArrayRef<uint8_t> A, size_t Size); | 
 | }; | 
 |  | 
 | struct EhSectionPiece { | 
 |   EhSectionPiece(size_t Off, InputSectionBase *Sec, uint32_t Size, | 
 |                  unsigned FirstRelocation) | 
 |       : InputOff(Off), Sec(Sec), Size(Size), FirstRelocation(FirstRelocation) {} | 
 |  | 
 |   ArrayRef<uint8_t> data() { return {Sec->Data.data() + this->InputOff, Size}; } | 
 |  | 
 |   size_t InputOff; | 
 |   ssize_t OutputOff = -1; | 
 |   InputSectionBase *Sec; | 
 |   uint32_t Size; | 
 |   unsigned FirstRelocation; | 
 | }; | 
 |  | 
 | // This corresponds to a .eh_frame section of an input file. | 
 | class EhInputSection : public InputSectionBase { | 
 | public: | 
 |   template <class ELFT> | 
 |   EhInputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header, | 
 |                  StringRef Name); | 
 |   static bool classof(const SectionBase *S) { return S->kind() == EHFrame; } | 
 |   template <class ELFT> void split(); | 
 |   template <class ELFT, class RelTy> void split(ArrayRef<RelTy> Rels); | 
 |  | 
 |   // Splittable sections are handled as a sequence of data | 
 |   // rather than a single large blob of data. | 
 |   std::vector<EhSectionPiece> Pieces; | 
 |  | 
 |   SyntheticSection *getParent() const; | 
 | }; | 
 |  | 
 | // This is a section that is added directly to an output section | 
 | // instead of needing special combination via a synthetic section. This | 
 | // includes all input sections with the exceptions of SHF_MERGE and | 
 | // .eh_frame. It also includes the synthetic sections themselves. | 
 | class InputSection : public InputSectionBase { | 
 | public: | 
 |   InputSection(InputFile *F, uint64_t Flags, uint32_t Type, uint32_t Alignment, | 
 |                ArrayRef<uint8_t> Data, StringRef Name, Kind K = Regular); | 
 |   template <class ELFT> | 
 |   InputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header, | 
 |                StringRef Name); | 
 |  | 
 |   // Write this section to a mmap'ed file, assuming Buf is pointing to | 
 |   // beginning of the output section. | 
 |   template <class ELFT> void writeTo(uint8_t *Buf); | 
 |  | 
 |   uint64_t getOffset(uint64_t Offset) const { return OutSecOff + Offset; } | 
 |  | 
 |   OutputSection *getParent() const; | 
 |  | 
 |   // This variable has two usages. Initially, it represents an index in the | 
 |   // OutputSection's InputSection list, and is used when ordering SHF_LINK_ORDER | 
 |   // sections. After assignAddresses is called, it represents the offset from | 
 |   // the beginning of the output section this section was assigned to. | 
 |   uint64_t OutSecOff = 0; | 
 |  | 
 |   static bool classof(const SectionBase *S); | 
 |  | 
 |   InputSectionBase *getRelocatedSection() const; | 
 |  | 
 |   template <class ELFT, class RelTy> | 
 |   void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels); | 
 |  | 
 |   // Used by ICF. | 
 |   uint32_t Class[2] = {0, 0}; | 
 |  | 
 |   // Called by ICF to merge two input sections. | 
 |   void replace(InputSection *Other); | 
 |  | 
 |   static InputSection Discarded; | 
 |  | 
 | private: | 
 |   template <class ELFT, class RelTy> | 
 |   void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels); | 
 |  | 
 |   template <class ELFT> void copyShtGroup(uint8_t *Buf); | 
 | }; | 
 |  | 
 | // The list of all input sections. | 
 | extern std::vector<InputSectionBase *> InputSections; | 
 | } // namespace elf | 
 |  | 
 | std::string toString(const elf::InputSectionBase *); | 
 | } // namespace lld | 
 |  | 
 | #endif |