//===- 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 "lld/Core/LLVM.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Object/ELF.h" namespace lld { namespace elf { template class ICF; template class ObjectFile; template class OutputSection; template class OutputSectionBase; // This corresponds to a section of an input file. template class InputSectionBase { protected: typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::uint uintX_t; const Elf_Shdr *Header; // The file this section is from. ObjectFile *File; public: enum Kind { Regular, EHFrame, Merge, MipsReginfo }; Kind SectionKind; InputSectionBase(ObjectFile *File, const Elf_Shdr *Header, Kind SectionKind); OutputSectionBase *OutSec = nullptr; uint32_t Align; // Used for garbage collection. bool Live; // This pointer points to the "real" instance of this instance. // Usually Repl == this. However, if ICF merges two sections, // 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. InputSectionBase *Repl; // Returns the size of this section (even if this is a common or BSS.) size_t getSize() const; static InputSectionBase *Discarded; StringRef getSectionName() const; const Elf_Shdr *getSectionHdr() const { return Header; } ObjectFile *getFile() const { return File; } uintX_t getOffset(const Elf_Sym &Sym); // Translate an offset in the input section to an offset in the output // section. uintX_t getOffset(uintX_t Offset); ArrayRef getSectionData() const; // Returns a section that Rel is pointing to. Used by the garbage collector. InputSectionBase *getRelocTarget(const Elf_Rel &Rel) const; InputSectionBase *getRelocTarget(const Elf_Rela &Rel) const; template void relocate(uint8_t *Buf, uint8_t *BufEnd, llvm::iterator_range Rels); private: template int32_t findMipsPairedAddend(uint8_t *Buf, uint8_t *BufLoc, SymbolBody &Sym, const RelTy *Rel, const RelTy *End); }; template InputSectionBase * InputSectionBase::Discarded = (InputSectionBase *)-1ULL; // Usually sections are copied to the output as atomic chunks of data, // but some special types of sections are split into small pieces of data // and each piece is copied to a different place in the output. // This class represents such special sections. template class SplitInputSection : public InputSectionBase { typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::uint uintX_t; public: SplitInputSection(ObjectFile *File, const Elf_Shdr *Header, typename InputSectionBase::Kind SectionKind); // For each piece of data, we maintain the offsets in the input section and // in the output section. The latter may be -1 if it is not assigned yet. std::vector> Offsets; std::pair *, uintX_t> getRangeAndSize(uintX_t Offset); }; // This corresponds to a SHF_MERGE section of an input file. template class MergeInputSection : public SplitInputSection { typedef typename ELFT::uint uintX_t; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::Shdr Elf_Shdr; public: MergeInputSection(ObjectFile *F, const Elf_Shdr *Header); static bool classof(const InputSectionBase *S); // Translate an offset in the input section to an offset in the output // section. uintX_t getOffset(uintX_t Offset); }; // This corresponds to a .eh_frame section of an input file. template class EHInputSection : public SplitInputSection { public: typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::uint uintX_t; EHInputSection(ObjectFile *F, const Elf_Shdr *Header); static bool classof(const InputSectionBase *S); // Translate an offset in the input section to an offset in the output // section. uintX_t getOffset(uintX_t Offset); // Relocation section that refer to this one. const Elf_Shdr *RelocSection = nullptr; }; // This corresponds to a non SHF_MERGE section of an input file. template class InputSection : public InputSectionBase { friend ICF; typedef InputSectionBase Base; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::uint uintX_t; public: InputSection(ObjectFile *F, const Elf_Shdr *Header); // Write this section to a mmap'ed file, assuming Buf is pointing to // beginning of the output section. void writeTo(uint8_t *Buf); // Relocation sections that refer to this one. llvm::TinyPtrVector RelocSections; // The offset from beginning of the output sections this section was assigned // to. The writer sets a value. uint64_t OutSecOff = 0; static bool classof(const InputSectionBase *S); InputSectionBase *getRelocatedSection(); // Register thunk related to the symbol. When the section is written // to a mmap'ed file, target is requested to write an actual thunk code. // Now thunks is supported for MIPS target only. void addThunk(SymbolBody &Body); // The offset of synthetic thunk code from beginning of this section. uint64_t getThunkOff() const; // Size of chunk with thunks code. uint64_t getThunksSize() const; private: template void copyRelocations(uint8_t *Buf, llvm::iterator_range Rels); // Called by ICF to merge two input sections. void replace(InputSection *Other); // Used by ICF. uint64_t GroupId = 0; llvm::TinyPtrVector Thunks; }; // MIPS .reginfo section provides information on the registers used by the code // in the object file. Linker should collect this information and write a single // .reginfo section in the output file. The output section contains a union of // used registers masks taken from input .reginfo sections and final value // of the `_gp` symbol. For details: Chapter 4 / "Register Information" at // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf template class MipsReginfoInputSection : public InputSectionBase { typedef typename ELFT::Shdr Elf_Shdr; public: MipsReginfoInputSection(ObjectFile *F, const Elf_Shdr *Hdr); static bool classof(const InputSectionBase *S); const llvm::object::Elf_Mips_RegInfo *Reginfo; }; } // namespace elf } // namespace lld #endif