| //===- subzero/src/IceELFObjectWriter.h - ELF object writer -----*- C++ -*-===// | 
 | // | 
 | //                        The Subzero Code Generator | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | /// | 
 | /// \file | 
 | /// \brief Abstraction for a writer that is responsible for writing an ELF file. | 
 | /// | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #ifndef SUBZERO_SRC_ICEELFOBJECTWRITER_H | 
 | #define SUBZERO_SRC_ICEELFOBJECTWRITER_H | 
 |  | 
 | #include "IceDefs.h" | 
 | #include "IceELFSection.h" | 
 | #include "IceELFStreamer.h" | 
 | #include "IceTypes.h" | 
 |  | 
 | using namespace llvm::ELF; | 
 |  | 
 | namespace Ice { | 
 |  | 
 | using VariableDeclarationPartition = std::vector<VariableDeclaration *>; | 
 |  | 
 | /// Higher level ELF object writer. Manages section information and writes the | 
 | /// final ELF object. The object writer will write to file the code and data as | 
 | /// it is being defined (rather than keep a copy). After all definitions are | 
 | /// written out, it will finalize the bookkeeping sections and write them out. | 
 | /// Expected usage: | 
 | /// | 
 | /// (1) writeInitialELFHeader (invoke once) | 
 | /// (2) writeDataSection      (may be invoked multiple times, as long as | 
 | ///                            SectionSuffix is unique) | 
 | /// (3) writeFunctionCode     (must invoke once per function) | 
 | /// (4) writeConstantPool     (must invoke once per pooled primitive type) | 
 | /// (5) setUndefinedSyms      (invoke once) | 
 | /// (6) writeNonUserSections  (invoke once) | 
 | /// | 
 | /// The requirement for writeDataSection to be invoked only once can be relaxed | 
 | /// if using -fdata-sections. The requirement to invoke only once without | 
 | /// -fdata-sections is so that variables that belong to each possible | 
 | /// SectionType are contiguous in the file. With -fdata-sections, each global | 
 | /// variable is in a separate section and therefore the sections will be | 
 | /// trivially contiguous. | 
 | class ELFObjectWriter { | 
 |   ELFObjectWriter() = delete; | 
 |   ELFObjectWriter(const ELFObjectWriter &) = delete; | 
 |   ELFObjectWriter &operator=(const ELFObjectWriter &) = delete; | 
 |  | 
 | public: | 
 |   ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out); | 
 |  | 
 |   /// Write the initial ELF header. This is just to reserve space in the ELF | 
 |   /// file. Reserving space allows the other functions to write text and data | 
 |   /// directly to the file and get the right file offsets. | 
 |   void writeInitialELFHeader(); | 
 |  | 
 |   /// Copy initializer data for globals to file and note the offset and size of | 
 |   /// each global's definition in the symbol table. Use the given target's | 
 |   /// RelocationKind for any relocations. | 
 |   void writeDataSection(const VariableDeclarationList &Vars, | 
 |                         FixupKind RelocationKind, | 
 |                         const std::string &SectionSuffix, bool IsPIC); | 
 |  | 
 |   /// Copy data of a function's text section to file and note the offset of the | 
 |   /// symbol's definition in the symbol table. Copy the text fixups for use | 
 |   /// after all functions are written. The text buffer and fixups are extracted | 
 |   /// from the Assembler object. | 
 |   void writeFunctionCode(GlobalString FuncName, bool IsInternal, | 
 |                          Assembler *Asm); | 
 |  | 
 |   /// Queries the GlobalContext for constant pools of the given type and writes | 
 |   /// out read-only data sections for those constants. This also fills the | 
 |   /// symbol table with labels for each constant pool entry. | 
 |   template <typename ConstType> void writeConstantPool(Type Ty); | 
 |  | 
 |   /// Write a jump table and register fixups for the target addresses. | 
 |   void writeJumpTable(const JumpTableData &JT, FixupKind RelocationKind, | 
 |                       bool IsPIC); | 
 |  | 
 |   /// Populate the symbol table with a list of external/undefined symbols. | 
 |   void setUndefinedSyms(const ConstantList &UndefSyms); | 
 |  | 
 |   /// Do final layout and write out the rest of the object file. Finally, patch | 
 |   /// up the initial ELF header with the final info. | 
 |   void writeNonUserSections(); | 
 |  | 
 |   /// Which type of ELF section a global variable initializer belongs to. This | 
 |   /// is used as an array index so should start at 0 and be contiguous. | 
 |   enum SectionType { ROData = 0, Data, BSS, NumSectionTypes }; | 
 |  | 
 |   /// Create target specific section with the given information about section. | 
 |   void writeTargetRODataSection(const std::string &Name, Elf64_Word ShType, | 
 |                                 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, | 
 |                                 Elf64_Xword ShEntsize, | 
 |                                 const llvm::StringRef &SecData); | 
 |  | 
 | private: | 
 |   GlobalContext &Ctx; | 
 |   ELFStreamer &Str; | 
 |   bool SectionNumbersAssigned = false; | 
 |   bool ELF64; | 
 |  | 
 |   // All created sections, separated into different pools. | 
 |   using SectionList = std::vector<ELFSection *>; | 
 |   using TextSectionList = std::vector<ELFTextSection *>; | 
 |   using DataSectionList = std::vector<ELFDataSection *>; | 
 |   using RelSectionList = std::vector<ELFRelocationSection *>; | 
 |   TextSectionList TextSections; | 
 |   RelSectionList RelTextSections; | 
 |   DataSectionList DataSections; | 
 |   RelSectionList RelDataSections; | 
 |   DataSectionList RODataSections; | 
 |   RelSectionList RelRODataSections; | 
 |   DataSectionList BSSSections; | 
 |  | 
 |   // Handles to special sections that need incremental bookkeeping. | 
 |   ELFSection *NullSection; | 
 |   ELFStringTableSection *ShStrTab; | 
 |   ELFSymbolTableSection *SymTab; | 
 |   ELFStringTableSection *StrTab; | 
 |  | 
 |   template <typename T> | 
 |   T *createSection(const std::string &Name, Elf64_Word ShType, | 
 |                    Elf64_Xword ShFlags, Elf64_Xword ShAddralign, | 
 |                    Elf64_Xword ShEntsize); | 
 |  | 
 |   /// Create a relocation section, given the related section (e.g., .text, | 
 |   /// .data., .rodata). | 
 |   ELFRelocationSection * | 
 |   createRelocationSection(const ELFSection *RelatedSection); | 
 |  | 
 |   /// Align the file position before writing out a section's data, and return | 
 |   /// the position of the file. | 
 |   Elf64_Off alignFileOffset(Elf64_Xword Align); | 
 |  | 
 |   /// Assign an ordering / section numbers to each section. Fill in other | 
 |   /// information that is only known near the end (such as the size, if it | 
 |   /// wasn't already incrementally updated). This then collects all sections in | 
 |   /// the decided order, into one vector, for conveniently writing out all of | 
 |   /// the section headers. | 
 |   void assignSectionNumbersInfo(SectionList &AllSections); | 
 |  | 
 |   /// This function assigns .foo and .rel.foo consecutive section numbers. It | 
 |   /// also sets the relocation section's sh_info field to the related section's | 
 |   /// number. | 
 |   template <typename UserSectionList> | 
 |   void assignRelSectionNumInPairs(SizeT &CurSectionNumber, | 
 |                                   UserSectionList &UserSections, | 
 |                                   RelSectionList &RelSections, | 
 |                                   SectionList &AllSections); | 
 |  | 
 |   /// Link the relocation sections to the symbol table. | 
 |   void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections); | 
 |  | 
 |   /// Helper function for writeDataSection. Writes a data section of type | 
 |   /// SectionType, given the global variables Vars belonging to that | 
 |   /// SectionType. | 
 |   void writeDataOfType(SectionType SectionType, | 
 |                        const VariableDeclarationPartition &Vars, | 
 |                        FixupKind RelocationKind, | 
 |                        const std::string &SectionSuffix, bool IsPIC); | 
 |  | 
 |   /// Write the final relocation sections given the final symbol table. May also | 
 |   /// be able to seek around the file and resolve function calls that are for | 
 |   /// functions within the same section. | 
 |   void writeAllRelocationSections(); | 
 |   void writeRelocationSections(RelSectionList &RelSections); | 
 |  | 
 |   /// Write the ELF file header with the given information about sections. | 
 |   template <bool IsELF64> | 
 |   void writeELFHeaderInternal(Elf64_Off SectionHeaderOffset, | 
 |                               SizeT SectHeaderStrIndex, SizeT NumSections); | 
 | }; | 
 |  | 
 | } // end of namespace Ice | 
 |  | 
 | #endif // SUBZERO_SRC_ICEELFOBJECTWRITER_H |