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 (must invoke once per function) |
35 // (4) writeNonUserSections | 35 // (4) writeConstantPool (must invoke once per pooled primitive type) |
| 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 // This is used as an array index so should start at 0 and be contiguous. |
| 85 enum SectionType { ROData = 0, Data, BSS, NumSectionTypes }; |
| 86 |
68 private: | 87 private: |
69 GlobalContext &Ctx; | 88 GlobalContext &Ctx; |
70 ELFStreamer &Str; | 89 ELFStreamer &Str; |
71 bool SectionNumbersAssigned; | 90 bool SectionNumbersAssigned; |
72 | 91 |
73 // All created sections, separated into different pools. | 92 // All created sections, separated into different pools. |
74 typedef std::vector<ELFSection *> SectionList; | 93 typedef std::vector<ELFSection *> SectionList; |
75 typedef std::vector<ELFTextSection *> TextSectionList; | 94 typedef std::vector<ELFTextSection *> TextSectionList; |
76 typedef std::vector<ELFDataSection *> DataSectionList; | 95 typedef std::vector<ELFDataSection *> DataSectionList; |
77 typedef std::vector<ELFRelocationSection *> RelSectionList; | 96 typedef std::vector<ELFRelocationSection *> RelSectionList; |
78 TextSectionList TextSections; | 97 TextSectionList TextSections; |
79 RelSectionList RelTextSections; | 98 RelSectionList RelTextSections; |
80 DataSectionList DataSections; | 99 DataSectionList DataSections; |
81 RelSectionList RelDataSections; | 100 RelSectionList RelDataSections; |
82 DataSectionList RoDataSections; | 101 DataSectionList RODataSections; |
83 RelSectionList RelRoDataSections; | 102 RelSectionList RelRODataSections; |
| 103 DataSectionList BSSSections; |
84 | 104 |
85 // Handles to special sections that need incremental bookkeeping. | 105 // Handles to special sections that need incremental bookkeeping. |
86 ELFSection *NullSection; | 106 ELFSection *NullSection; |
87 ELFStringTableSection *ShStrTab; | 107 ELFStringTableSection *ShStrTab; |
88 ELFSymbolTableSection *SymTab; | 108 ELFSymbolTableSection *SymTab; |
89 ELFStringTableSection *StrTab; | 109 ELFStringTableSection *StrTab; |
90 | 110 |
91 template <typename T> | 111 template <typename T> |
92 T *createSection(const IceString &Name, Elf64_Word ShType, | 112 T *createSection(const IceString &Name, Elf64_Word ShType, |
93 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, | 113 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, |
94 Elf64_Xword ShEntsize); | 114 Elf64_Xword ShEntsize); |
95 | 115 |
| 116 // Create a relocation section, given the related section |
| 117 // (e.g., .text, .data., .rodata). |
| 118 ELFRelocationSection * |
| 119 createRelocationSection(bool IsELF64, const ELFSection *RelatedSection); |
| 120 |
96 // Align the file position before writing out a section's data, | 121 // Align the file position before writing out a section's data, |
97 // and return the position of the file. | 122 // and return the position of the file. |
98 Elf64_Off alignFileOffset(Elf64_Xword Align); | 123 Elf64_Off alignFileOffset(Elf64_Xword Align); |
99 | 124 |
100 // Assign an ordering / section numbers to each section. | 125 // Assign an ordering / section numbers to each section. |
101 // Fill in other information that is only known near the end | 126 // Fill in other information that is only known near the end |
102 // (such as the size, if it wasn't already incrementally updated). | 127 // (such as the size, if it wasn't already incrementally updated). |
103 // This then collects all sections in the decided order, into one vector, | 128 // This then collects all sections in the decided order, into one vector, |
104 // for conveniently writing out all of the section headers. | 129 // for conveniently writing out all of the section headers. |
105 void assignSectionNumbersInfo(SectionList &AllSections); | 130 void assignSectionNumbersInfo(SectionList &AllSections); |
106 | 131 |
107 // This function assigns .foo and .rel.foo consecutive section numbers. | 132 // This function assigns .foo and .rel.foo consecutive section numbers. |
108 // It also sets the relocation section's sh_info field to the related | 133 // It also sets the relocation section's sh_info field to the related |
109 // section's number. | 134 // section's number. |
110 template <typename UserSectionList> | 135 template <typename UserSectionList> |
111 void assignRelSectionNumInPairs(SizeT &CurSectionNumber, | 136 void assignRelSectionNumInPairs(SizeT &CurSectionNumber, |
112 UserSectionList &UserSections, | 137 UserSectionList &UserSections, |
113 RelSectionList &RelSections, | 138 RelSectionList &RelSections, |
114 SectionList &AllSections); | 139 SectionList &AllSections); |
115 | 140 |
116 // Link the relocation sections to the symbol table. | 141 // Link the relocation sections to the symbol table. |
117 void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections); | 142 void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections); |
118 | 143 |
| 144 // Helper function for writeDataSection. Writes a data section of type |
| 145 // SectionType, given the global variables Vars belonging to that SectionType. |
| 146 void writeDataOfType(SectionType SectionType, |
| 147 const VariableDeclarationList &Vars, |
| 148 FixupKind RelocationKind, bool IsELF64); |
| 149 |
119 // Write the final relocation sections given the final symbol table. | 150 // Write the final relocation sections given the final symbol table. |
120 // May also be able to seek around the file and resolve function calls | 151 // May also be able to seek around the file and resolve function calls |
121 // that are for functions within the same section. | 152 // that are for functions within the same section. |
122 void writeAllRelocationSections(bool IsELF64); | 153 void writeAllRelocationSections(bool IsELF64); |
123 void writeRelocationSections(bool IsELF64, RelSectionList &RelSections); | 154 void writeRelocationSections(bool IsELF64, RelSectionList &RelSections); |
124 | 155 |
125 // Write the ELF file header with the given information about sections. | 156 // Write the ELF file header with the given information about sections. |
126 template <bool IsELF64> | 157 template <bool IsELF64> |
127 void writeELFHeaderInternal(Elf64_Off SectionHeaderOffset, | 158 void writeELFHeaderInternal(Elf64_Off SectionHeaderOffset, |
128 SizeT SectHeaderStrIndex, SizeT NumSections); | 159 SizeT SectHeaderStrIndex, SizeT NumSections); |
129 }; | 160 }; |
130 | 161 |
131 } // end of namespace Ice | 162 } // end of namespace Ice |
132 | 163 |
133 #endif // SUBZERO_SRC_ICEELFOBJECTWRITER_H | 164 #endif // SUBZERO_SRC_ICEELFOBJECTWRITER_H |
OLD | NEW |