108c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung//===- subzero/src/IceELFObjectWriter.h - ELF object writer -----*- C++ -*-===//
208c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung//
308c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung//                        The Subzero Code Generator
408c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung//
508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung// This file is distributed under the University of Illinois Open Source
608c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung// License. See LICENSE.TXT for details.
708c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung//
808c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung//===----------------------------------------------------------------------===//
99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Abstraction for a writer that is responsible for writing an ELF file.
129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
1308c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung//===----------------------------------------------------------------------===//
1408c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
1508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung#ifndef SUBZERO_SRC_ICEELFOBJECTWRITER_H
1608c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung#define SUBZERO_SRC_ICEELFOBJECTWRITER_H
1708c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
1808c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung#include "IceDefs.h"
1908c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung#include "IceELFSection.h"
2008c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung#include "IceELFStreamer.h"
2191a3e2c9973fb8bd264c9bcbe45081cf8fb24922Jan Voung#include "IceTypes.h"
2208c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
2308c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voungusing namespace llvm::ELF;
2408c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
2508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voungnamespace Ice {
2608c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
27a78e4baab1557beccdb7604175dcea97ef1afe06John Portousing VariableDeclarationPartition = std::vector<VariableDeclaration *>;
28a78e4baab1557beccdb7604175dcea97ef1afe06John Porto
2957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Higher level ELF object writer. Manages section information and writes the
3057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// final ELF object. The object writer will write to file the code and data as
3157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// it is being defined (rather than keep a copy). After all definitions are
3257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// written out, it will finalize the bookkeeping sections and write them out.
3357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Expected usage:
349612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
359612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// (1) writeInitialELFHeader (invoke once)
369612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// (2) writeDataSection      (may be invoked multiple times, as long as
379612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///                            SectionSuffix is unique)
389612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// (3) writeFunctionCode     (must invoke once per function)
399612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// (4) writeConstantPool     (must invoke once per pooled primitive type)
409612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// (5) setUndefinedSyms      (invoke once)
419612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// (6) writeNonUserSections  (invoke once)
429612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
4357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// The requirement for writeDataSection to be invoked only once can be relaxed
4457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// if using -fdata-sections. The requirement to invoke only once without
4557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// -fdata-sections is so that variables that belong to each possible
469612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// SectionType are contiguous in the file. With -fdata-sections, each global
479612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// variable is in a separate section and therefore the sections will be
489612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// trivially contiguous.
4908c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voungclass ELFObjectWriter {
50c6ead20cc2e9ecb0ca45b650ce911ef565d88f6eJim Stichnoth  ELFObjectWriter() = delete;
5108c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  ELFObjectWriter(const ELFObjectWriter &) = delete;
5208c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  ELFObjectWriter &operator=(const ELFObjectWriter &) = delete;
5308c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
5408c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voungpublic:
5508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out);
5608c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
579612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Write the initial ELF header. This is just to reserve space in the ELF
5857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// file. Reserving space allows the other functions to write text and data
5957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// directly to the file and get the right file offsets.
6008c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  void writeInitialELFHeader();
6108c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
6257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Copy initializer data for globals to file and note the offset and size of
6357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// each global's definition in the symbol table. Use the given target's
6457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// RelocationKind for any relocations.
6572984d881d7afb8d890380348061a3177b609e89Jan Voung  void writeDataSection(const VariableDeclarationList &Vars,
668b1a705165292328a3db53da273420989b46e443John Porto                        FixupKind RelocationKind,
67467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth                        const std::string &SectionSuffix, bool IsPIC);
6872984d881d7afb8d890380348061a3177b609e89Jan Voung
699612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Copy data of a function's text section to file and note the offset of the
7057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// symbol's definition in the symbol table. Copy the text fixups for use
7157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// after all functions are written. The text buffer and fixups are extracted
7257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// from the Assembler object.
73467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  void writeFunctionCode(GlobalString FuncName, bool IsInternal,
746e8d3fae541c3e3aa1cb213a9db3a8155edcdbe8John Porto                         Assembler *Asm);
7508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
7657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Queries the GlobalContext for constant pools of the given type and writes
7757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// out read-only data sections for those constants. This also fills the
7857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// symbol table with labels for each constant pool entry.
7991a3e2c9973fb8bd264c9bcbe45081cf8fb24922Jan Voung  template <typename ConstType> void writeConstantPool(Type Ty);
8091a3e2c9973fb8bd264c9bcbe45081cf8fb24922Jan Voung
8186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  /// Write a jump table and register fixups for the target addresses.
828ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  void writeJumpTable(const JumpTableData &JT, FixupKind RelocationKind,
838ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth                      bool IsPIC);
8486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
859612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Populate the symbol table with a list of external/undefined symbols.
86261cae38fd492fbe90b8431d11d2a36014101d71Jan Voung  void setUndefinedSyms(const ConstantList &UndefSyms);
87261cae38fd492fbe90b8431d11d2a36014101d71Jan Voung
8857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Do final layout and write out the rest of the object file. Finally, patch
8957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// up the initial ELF header with the final info.
9008c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  void writeNonUserSections();
9108c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
9257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Which type of ELF section a global variable initializer belongs to. This
9357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// is used as an array index so should start at 0 and be contiguous.
9472984d881d7afb8d890380348061a3177b609e89Jan Voung  enum SectionType { ROData = 0, Data, BSS, NumSectionTypes };
9572984d881d7afb8d890380348061a3177b609e89Jan Voung
963da9f6571608b337af7c9d2ad9e0ca938bb49ae7Jaydeep Patil  /// Create target specific section with the given information about section.
973da9f6571608b337af7c9d2ad9e0ca938bb49ae7Jaydeep Patil  void writeTargetRODataSection(const std::string &Name, Elf64_Word ShType,
983da9f6571608b337af7c9d2ad9e0ca938bb49ae7Jaydeep Patil                                Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
993da9f6571608b337af7c9d2ad9e0ca938bb49ae7Jaydeep Patil                                Elf64_Xword ShEntsize,
1003da9f6571608b337af7c9d2ad9e0ca938bb49ae7Jaydeep Patil                                const llvm::StringRef &SecData);
1013da9f6571608b337af7c9d2ad9e0ca938bb49ae7Jaydeep Patil
10208c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voungprivate:
10308c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  GlobalContext &Ctx;
10408c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  ELFStreamer &Str;
105eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth  bool SectionNumbersAssigned = false;
1061f47ad02c2db6427f53438f764c1299fe55dfcbdJan Voung  bool ELF64;
10708c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
10808c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  // All created sections, separated into different pools.
1098072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using SectionList = std::vector<ELFSection *>;
1108072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using TextSectionList = std::vector<ELFTextSection *>;
1118072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using DataSectionList = std::vector<ELFDataSection *>;
1128072bae156fa62e51e02925997992c4908a2682fAndrew Scull  using RelSectionList = std::vector<ELFRelocationSection *>;
11308c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  TextSectionList TextSections;
11408c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  RelSectionList RelTextSections;
11508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  DataSectionList DataSections;
11608c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  RelSectionList RelDataSections;
11772984d881d7afb8d890380348061a3177b609e89Jan Voung  DataSectionList RODataSections;
11872984d881d7afb8d890380348061a3177b609e89Jan Voung  RelSectionList RelRODataSections;
11972984d881d7afb8d890380348061a3177b609e89Jan Voung  DataSectionList BSSSections;
12008c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
12108c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  // Handles to special sections that need incremental bookkeeping.
12208c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  ELFSection *NullSection;
12308c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  ELFStringTableSection *ShStrTab;
12408c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  ELFSymbolTableSection *SymTab;
12508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  ELFStringTableSection *StrTab;
12608c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
12708c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  template <typename T>
128467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  T *createSection(const std::string &Name, Elf64_Word ShType,
12908c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung                   Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
13008c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung                   Elf64_Xword ShEntsize);
13108c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
13257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Create a relocation section, given the related section (e.g., .text,
13357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// .data., .rodata).
13472984d881d7afb8d890380348061a3177b609e89Jan Voung  ELFRelocationSection *
1351f47ad02c2db6427f53438f764c1299fe55dfcbdJan Voung  createRelocationSection(const ELFSection *RelatedSection);
13672984d881d7afb8d890380348061a3177b609e89Jan Voung
13757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Align the file position before writing out a section's data, and return
13857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// the position of the file.
13908c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  Elf64_Off alignFileOffset(Elf64_Xword Align);
14008c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
14157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Assign an ordering / section numbers to each section. Fill in other
14257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// information that is only known near the end (such as the size, if it
14357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// wasn't already incrementally updated). This then collects all sections in
14457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// the decided order, into one vector, for conveniently writing out all of
14557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// the section headers.
14608c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  void assignSectionNumbersInfo(SectionList &AllSections);
14708c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
14857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// This function assigns .foo and .rel.foo consecutive section numbers. It
14957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// also sets the relocation section's sh_info field to the related section's
15057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// number.
15108c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  template <typename UserSectionList>
15208c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  void assignRelSectionNumInPairs(SizeT &CurSectionNumber,
15308c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung                                  UserSectionList &UserSections,
15408c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung                                  RelSectionList &RelSections,
15508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung                                  SectionList &AllSections);
15608c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
1579612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Link the relocation sections to the symbol table.
15808c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections);
15908c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
1609612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Helper function for writeDataSection. Writes a data section of type
16187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  /// SectionType, given the global variables Vars belonging to that
16287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  /// SectionType.
16372984d881d7afb8d890380348061a3177b609e89Jan Voung  void writeDataOfType(SectionType SectionType,
164a78e4baab1557beccdb7604175dcea97ef1afe06John Porto                       const VariableDeclarationPartition &Vars,
165467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth                       FixupKind RelocationKind,
166467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth                       const std::string &SectionSuffix, bool IsPIC);
16772984d881d7afb8d890380348061a3177b609e89Jan Voung
16857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// Write the final relocation sections given the final symbol table. May also
16957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// be able to seek around the file and resolve function calls that are for
17057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  /// functions within the same section.
1711f47ad02c2db6427f53438f764c1299fe55dfcbdJan Voung  void writeAllRelocationSections();
1721f47ad02c2db6427f53438f764c1299fe55dfcbdJan Voung  void writeRelocationSections(RelSectionList &RelSections);
173ec27073120be04bf6234a0742e40ae3454ef9d3fJan Voung
1749612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull  /// Write the ELF file header with the given information about sections.
17508c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung  template <bool IsELF64>
176a601cc5f89701e1f117ab61bfa3669d1aed48846Jan Voung  void writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,
17708c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung                              SizeT SectHeaderStrIndex, SizeT NumSections);
17808c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung};
17908c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
18008c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung} // end of namespace Ice
18108c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung
18208c3bcd66dc0101720da78c1d5f49230f4521c75Jan Voung#endif // SUBZERO_SRC_ICEELFOBJECTWRITER_H
183