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