|  | //===- 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 { | 
|  |  | 
|  | /// 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 IceString &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(const IceString &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 }; | 
|  |  | 
|  | 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 IceString &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 VariableDeclarationList &Vars, | 
|  | FixupKind RelocationKind, const IceString &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 |