Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 //===- subzero/src/IceELFObjectWriter.h - ELF object writer -----*- C++ -*-===// | 1 //===- subzero/src/IceELFObjectWriter.h - ELF object writer -----*- C++ -*-===// | 
| 2 // | 2 // | 
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator | 
| 4 // | 4 // | 
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source | 
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. | 
| 7 // | 7 // | 
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// | 
| 9 // | 9 // | 
| 10 // Abstraction for a writer that is responsible for writing an ELF file. | 10 // Abstraction for a writer that is responsible for writing an ELF file. | 
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 using namespace llvm::ELF; | 22 using namespace llvm::ELF; | 
| 23 | 23 | 
| 24 namespace Ice { | 24 namespace Ice { | 
| 25 | 25 | 
| 26 // Higher level ELF object writer. Manages section information and writes | 26 // Higher level ELF object writer. Manages section information and writes | 
| 27 // the final ELF object. The object writer will write to file the code | 27 // the final ELF object. The object writer will write to file the code | 
| 28 // and data as it is being defined (rather than keep a copy). | 28 // and data as it is being defined (rather than keep a copy). | 
| 29 // After all definitions are written out, it will finalize the bookkeeping | 29 // After all definitions are written out, it will finalize the bookkeeping | 
| 30 // sections and write them out. Expected usage: | 30 // sections and write them out. Expected usage: | 
| 31 // | 31 // | 
| 32 // (1) writeInitialELFHeader | 32 // (1) writeInitialELFHeader (invoke once) | 
| 33 // (2) writeDataInitializer* | 33 // (2) writeDataSection (invoke once) | 
| 34 // (3) writeFunctionCode* | 34 // (3) writeFunctionCode (may invoke once per function) | 
| 
 
Jim Stichnoth
2015/01/28 20:35:08
Why "may"? Just based on the method signature, it
 
jvoung (off chromium)
2015/01/28 23:37:53
Done. Hmm yes =)
 
 | |
| 35 // (4) writeNonUserSections | 35 // (4) writeConstantPool (may invoke once per type) | 
| 
 
Jim Stichnoth
2015/01/28 20:35:08
"(invoke at most once per primitive type)"
Would
 
jvoung (off chromium)
2015/01/28 23:37:53
Yes, or how about "must invoke once per pooled pri
 
Jim Stichnoth
2015/01/29 00:38:14
I agree - my main purpose of data-sections was to
 
 | |
| 36 // (5) writeNonUserSections (invoke once) | |
| 37 // | |
| 38 // The requirement for writeDataSection to be invoked only once can | |
| 39 // be relaxed if using -fdata-sections. The requirement to invoke only once | |
| 40 // without -fdata-sections is so that variables that belong to each possible | |
| 41 // SectionType are contiguous in the file. With -fdata-sections, each global | |
| 42 // variable is in a separate section and therefore the sections will be | |
| 43 // trivially contiguous. | |
| 44 // | |
| 45 // The motivation for requiring that writeFunctionCode happen after | |
| 46 // writeDataSection: to keep the .text and .data sections contiguous in the | |
| 47 // file. Having both -fdata-sections and -ffunction-sections does allow | |
| 48 // relaxing this requirement. | |
| 36 class ELFObjectWriter { | 49 class ELFObjectWriter { | 
| 37 ELFObjectWriter(const ELFObjectWriter &) = delete; | 50 ELFObjectWriter(const ELFObjectWriter &) = delete; | 
| 38 ELFObjectWriter &operator=(const ELFObjectWriter &) = delete; | 51 ELFObjectWriter &operator=(const ELFObjectWriter &) = delete; | 
| 39 | 52 | 
| 40 public: | 53 public: | 
| 41 ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out); | 54 ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out); | 
| 42 | 55 | 
| 43 // Write the initial ELF header. This is just to reserve space in the ELF | 56 // Write the initial ELF header. This is just to reserve space in the ELF | 
| 44 // file. Reserving space allows the other functions to write text | 57 // file. Reserving space allows the other functions to write text | 
| 45 // and data directly to the file and get the right file offsets. | 58 // and data directly to the file and get the right file offsets. | 
| 46 void writeInitialELFHeader(); | 59 void writeInitialELFHeader(); | 
| 47 | 60 | 
| 61 // Copy initializer data for globals to file and note the offset and size | |
| 62 // of each global's definition in the symbol table. | |
| 63 // Use the given target's RelocationKind for any relocations. | |
| 64 void writeDataSection(const VariableDeclarationList &Vars, | |
| 65 FixupKind RelocationKind); | |
| 66 | |
| 48 // Copy data of a function's text section to file and note the offset of the | 67 // Copy data of a function's text section to file and note the offset of the | 
| 49 // symbol's definition in the symbol table. | 68 // symbol's definition in the symbol table. | 
| 50 // Copy the text fixups for use after all functions are written. | 69 // Copy the text fixups for use after all functions are written. | 
| 70 // The text buffer and fixups are extracted from the Assembler object. | |
| 51 void writeFunctionCode(const IceString &FuncName, bool IsInternal, | 71 void writeFunctionCode(const IceString &FuncName, bool IsInternal, | 
| 52 const Assembler *Asm); | 72 const Assembler *Asm); | 
| 53 | 73 | 
| 54 // Copy initializer data for a global to file and note the offset and | 74 // Queries the GlobalContext for constant pools of the given type | 
| 55 // size of the global's definition in the symbol table. | 75 // and writes out read-only data sections for those constants. This also | 
| 56 // TODO(jvoung): This needs to know which section. This also needs the | 76 // fills the symbol table with labels for each constant pool entry. | 
| 57 // relocations to hook them up to the symbol table references. Also | |
| 58 // TODO is handling BSS (which just needs to note the size). | |
| 59 void writeDataInitializer(const IceString &VarName, | |
| 60 const llvm::StringRef Data); | |
| 61 | |
| 62 template <typename ConstType> void writeConstantPool(Type Ty); | 77 template <typename ConstType> void writeConstantPool(Type Ty); | 
| 63 | 78 | 
| 64 // Do final layout and write out the rest of the object file, then | 79 // Do final layout and write out the rest of the object file. | 
| 65 // patch up the initial ELF header with the final info. | 80 // Finally, patch up the initial ELF header with the final info. | 
| 66 void writeNonUserSections(); | 81 void writeNonUserSections(); | 
| 67 | 82 | 
| 83 // Which type of ELF section a global variable initializer belongs to. | |
| 84 enum SectionType { | |
| 85 BaseSectionType = 0, | |
| 86 ROData = BaseSectionType, | |
| 87 Data, | |
| 88 BSS, | |
| 89 NumSectionTypes | |
| 90 }; | |
| 91 | |
| 68 private: | 92 private: | 
| 69 GlobalContext &Ctx; | 93 GlobalContext &Ctx; | 
| 70 ELFStreamer &Str; | 94 ELFStreamer &Str; | 
| 71 bool SectionNumbersAssigned; | 95 bool SectionNumbersAssigned; | 
| 72 | 96 | 
| 73 // All created sections, separated into different pools. | 97 // All created sections, separated into different pools. | 
| 74 typedef std::vector<ELFSection *> SectionList; | 98 typedef std::vector<ELFSection *> SectionList; | 
| 75 typedef std::vector<ELFTextSection *> TextSectionList; | 99 typedef std::vector<ELFTextSection *> TextSectionList; | 
| 76 typedef std::vector<ELFDataSection *> DataSectionList; | 100 typedef std::vector<ELFDataSection *> DataSectionList; | 
| 77 typedef std::vector<ELFRelocationSection *> RelSectionList; | 101 typedef std::vector<ELFRelocationSection *> RelSectionList; | 
| 78 TextSectionList TextSections; | 102 TextSectionList TextSections; | 
| 79 RelSectionList RelTextSections; | 103 RelSectionList RelTextSections; | 
| 80 DataSectionList DataSections; | 104 DataSectionList DataSections; | 
| 81 RelSectionList RelDataSections; | 105 RelSectionList RelDataSections; | 
| 82 DataSectionList RoDataSections; | 106 DataSectionList RODataSections; | 
| 83 RelSectionList RelRoDataSections; | 107 RelSectionList RelRODataSections; | 
| 108 DataSectionList BSSSections; | |
| 84 | 109 | 
| 85 // Handles to special sections that need incremental bookkeeping. | 110 // Handles to special sections that need incremental bookkeeping. | 
| 86 ELFSection *NullSection; | 111 ELFSection *NullSection; | 
| 87 ELFStringTableSection *ShStrTab; | 112 ELFStringTableSection *ShStrTab; | 
| 88 ELFSymbolTableSection *SymTab; | 113 ELFSymbolTableSection *SymTab; | 
| 89 ELFStringTableSection *StrTab; | 114 ELFStringTableSection *StrTab; | 
| 90 | 115 | 
| 91 template <typename T> | 116 template <typename T> | 
| 92 T *createSection(const IceString &Name, Elf64_Word ShType, | 117 T *createSection(const IceString &Name, Elf64_Word ShType, | 
| 93 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, | 118 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, | 
| 94 Elf64_Xword ShEntsize); | 119 Elf64_Xword ShEntsize); | 
| 95 | 120 | 
| 121 // Create a relocation section, given the related section | |
| 122 // (e.g., .text, .data., .rodata). | |
| 123 ELFRelocationSection * | |
| 124 createRelocationSection(bool IsELF64, const ELFSection *RelatedSection); | |
| 125 | |
| 96 // Align the file position before writing out a section's data, | 126 // Align the file position before writing out a section's data, | 
| 97 // and return the position of the file. | 127 // and return the position of the file. | 
| 98 Elf64_Off alignFileOffset(Elf64_Xword Align); | 128 Elf64_Off alignFileOffset(Elf64_Xword Align); | 
| 99 | 129 | 
| 100 // Assign an ordering / section numbers to each section. | 130 // Assign an ordering / section numbers to each section. | 
| 101 // Fill in other information that is only known near the end | 131 // Fill in other information that is only known near the end | 
| 102 // (such as the size, if it wasn't already incrementally updated). | 132 // (such as the size, if it wasn't already incrementally updated). | 
| 103 // This then collects all sections in the decided order, into one vector, | 133 // This then collects all sections in the decided order, into one vector, | 
| 104 // for conveniently writing out all of the section headers. | 134 // for conveniently writing out all of the section headers. | 
| 105 void assignSectionNumbersInfo(SectionList &AllSections); | 135 void assignSectionNumbersInfo(SectionList &AllSections); | 
| 106 | 136 | 
| 107 // This function assigns .foo and .rel.foo consecutive section numbers. | 137 // This function assigns .foo and .rel.foo consecutive section numbers. | 
| 108 // It also sets the relocation section's sh_info field to the related | 138 // It also sets the relocation section's sh_info field to the related | 
| 109 // section's number. | 139 // section's number. | 
| 110 template <typename UserSectionList> | 140 template <typename UserSectionList> | 
| 111 void assignRelSectionNumInPairs(SizeT &CurSectionNumber, | 141 void assignRelSectionNumInPairs(SizeT &CurSectionNumber, | 
| 112 UserSectionList &UserSections, | 142 UserSectionList &UserSections, | 
| 113 RelSectionList &RelSections, | 143 RelSectionList &RelSections, | 
| 114 SectionList &AllSections); | 144 SectionList &AllSections); | 
| 115 | 145 | 
| 116 // Link the relocation sections to the symbol table. | 146 // Link the relocation sections to the symbol table. | 
| 117 void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections); | 147 void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections); | 
| 118 | 148 | 
| 149 // Helper function for writeDataSection. Writes a data section of type | |
| 150 // SectionType, given the global variables Vars belonging to that SectionType. | |
| 151 void writeDataOfType(SectionType SectionType, | |
| 152 const VariableDeclarationList &Vars, | |
| 153 FixupKind RelocationKind, bool IsELF64); | |
| 154 | |
| 119 // Write the final relocation sections given the final symbol table. | 155 // Write the final relocation sections given the final symbol table. | 
| 120 // May also be able to seek around the file and resolve function calls | 156 // May also be able to seek around the file and resolve function calls | 
| 121 // that are for functions within the same section. | 157 // that are for functions within the same section. | 
| 122 void writeAllRelocationSections(bool IsELF64); | 158 void writeAllRelocationSections(bool IsELF64); | 
| 123 void writeRelocationSections(bool IsELF64, RelSectionList &RelSections); | 159 void writeRelocationSections(bool IsELF64, RelSectionList &RelSections); | 
| 124 | 160 | 
| 125 // Write the ELF file header with the given information about sections. | 161 // Write the ELF file header with the given information about sections. | 
| 126 template <bool IsELF64> | 162 template <bool IsELF64> | 
| 127 void writeELFHeaderInternal(Elf64_Off SectionHeaderOffset, | 163 void writeELFHeaderInternal(Elf64_Off SectionHeaderOffset, | 
| 128 SizeT SectHeaderStrIndex, SizeT NumSections); | 164 SizeT SectHeaderStrIndex, SizeT NumSections); | 
| 129 }; | 165 }; | 
| 130 | 166 | 
| 131 } // end of namespace Ice | 167 } // end of namespace Ice | 
| 132 | 168 | 
| 133 #endif // SUBZERO_SRC_ICEELFOBJECTWRITER_H | 169 #endif // SUBZERO_SRC_ICEELFOBJECTWRITER_H | 
| OLD | NEW |