OLD | NEW |
1 //===- subzero/src/IceELFSection.h - Model of ELF sections ------*- C++ -*-===// | 1 //===- subzero/src/IceELFSection.h - Model of ELF sections ------*- 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 /// \file | 10 /// \file |
11 /// \brief Representation of ELF sections. | 11 /// \brief Representation of ELF sections. |
12 /// | 12 /// |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 | 14 |
15 #ifndef SUBZERO_SRC_ICEELFSECTION_H | 15 #ifndef SUBZERO_SRC_ICEELFSECTION_H |
16 #define SUBZERO_SRC_ICEELFSECTION_H | 16 #define SUBZERO_SRC_ICEELFSECTION_H |
17 | 17 |
18 #include "IceDefs.h" | 18 #include "IceDefs.h" |
19 #include "IceELFStreamer.h" | 19 #include "IceELFStreamer.h" |
20 #include "IceFixups.h" | 20 #include "IceFixups.h" |
21 #include "IceOperand.h" | 21 #include "IceOperand.h" |
| 22 #include "IceStringPool.h" |
22 | 23 |
23 using namespace llvm::ELF; | 24 using namespace llvm::ELF; |
24 | 25 |
25 namespace Ice { | 26 namespace Ice { |
26 | 27 |
27 class ELFStreamer; | 28 class ELFStreamer; |
28 class ELFStringTableSection; | 29 class ELFStringTableSection; |
29 | 30 |
30 /// Base representation of an ELF section. | 31 /// Base representation of an ELF section. |
31 class ELFSection { | 32 class ELFSection { |
32 ELFSection() = delete; | 33 ELFSection() = delete; |
33 ELFSection(const ELFSection &) = delete; | 34 ELFSection(const ELFSection &) = delete; |
34 ELFSection &operator=(const ELFSection &) = delete; | 35 ELFSection &operator=(const ELFSection &) = delete; |
35 | 36 |
36 public: | 37 public: |
37 virtual ~ELFSection() = default; | 38 virtual ~ELFSection() = default; |
38 | 39 |
39 /// Sentinel value for a section number/index for before the final section | 40 /// Sentinel value for a section number/index for before the final section |
40 /// index is actually known. The dummy NULL section will be assigned number 0, | 41 /// index is actually known. The dummy NULL section will be assigned number 0, |
41 /// and it is referenced by the dummy 0-th symbol in the symbol table, so use | 42 /// and it is referenced by the dummy 0-th symbol in the symbol table, so use |
42 /// max() instead of 0. | 43 /// max() instead of 0. |
43 enum { NoSectionNumber = std::numeric_limits<SizeT>::max() }; | 44 enum { NoSectionNumber = std::numeric_limits<SizeT>::max() }; |
44 | 45 |
45 /// Constructs an ELF section, filling in fields that will be known once the | 46 /// Constructs an ELF section, filling in fields that will be known once the |
46 /// *type* of section is decided. Other fields may be updated incrementally or | 47 /// *type* of section is decided. Other fields may be updated incrementally or |
47 /// only after the program is completely defined. | 48 /// only after the program is completely defined. |
48 ELFSection(const IceString &Name, Elf64_Word ShType, Elf64_Xword ShFlags, | 49 ELFSection(const std::string &Name, Elf64_Word ShType, Elf64_Xword ShFlags, |
49 Elf64_Xword ShAddralign, Elf64_Xword ShEntsize) | 50 Elf64_Xword ShAddralign, Elf64_Xword ShEntsize) |
50 : Name(Name), Header() { | 51 : Name(Name), Header() { |
51 Header.sh_type = ShType; | 52 Header.sh_type = ShType; |
52 Header.sh_flags = ShFlags; | 53 Header.sh_flags = ShFlags; |
53 Header.sh_addralign = ShAddralign; | 54 Header.sh_addralign = ShAddralign; |
54 Header.sh_entsize = ShEntsize; | 55 Header.sh_entsize = ShEntsize; |
55 } | 56 } |
56 | 57 |
57 /// Set the section number/index after it is finally known. | 58 /// Set the section number/index after it is finally known. |
58 void setNumber(SizeT N) { | 59 void setNumber(SizeT N) { |
59 // Should only set the number once: from NoSectionNumber -> N. | 60 // Should only set the number once: from NoSectionNumber -> N. |
60 assert(Number == NoSectionNumber); | 61 assert(Number == NoSectionNumber); |
61 Number = N; | 62 Number = N; |
62 } | 63 } |
63 SizeT getNumber() const { | 64 SizeT getNumber() const { |
64 assert(Number != NoSectionNumber); | 65 assert(Number != NoSectionNumber); |
65 return Number; | 66 return Number; |
66 } | 67 } |
67 | 68 |
68 void setSize(Elf64_Xword sh_size) { Header.sh_size = sh_size; } | 69 void setSize(Elf64_Xword sh_size) { Header.sh_size = sh_size; } |
69 SizeT getCurrentSize() const { return Header.sh_size; } | 70 SizeT getCurrentSize() const { return Header.sh_size; } |
70 | 71 |
71 void setNameStrIndex(Elf64_Word sh_name) { Header.sh_name = sh_name; } | 72 void setNameStrIndex(Elf64_Word sh_name) { Header.sh_name = sh_name; } |
72 | 73 |
73 const IceString &getName() const { return Name; } | 74 const std::string &getName() const { return Name; } |
74 | 75 |
75 void setLinkNum(Elf64_Word sh_link) { Header.sh_link = sh_link; } | 76 void setLinkNum(Elf64_Word sh_link) { Header.sh_link = sh_link; } |
76 | 77 |
77 void setInfoNum(Elf64_Word sh_info) { Header.sh_info = sh_info; } | 78 void setInfoNum(Elf64_Word sh_info) { Header.sh_info = sh_info; } |
78 | 79 |
79 void setFileOffset(Elf64_Off sh_offset) { Header.sh_offset = sh_offset; } | 80 void setFileOffset(Elf64_Off sh_offset) { Header.sh_offset = sh_offset; } |
80 | 81 |
81 Elf64_Xword getSectionAlign() const { return Header.sh_addralign; } | 82 Elf64_Xword getSectionAlign() const { return Header.sh_addralign; } |
82 | 83 |
83 /// Write the section header out with the given streamer. | 84 /// Write the section header out with the given streamer. |
84 template <bool IsELF64> void writeHeader(ELFStreamer &Str); | 85 template <bool IsELF64> void writeHeader(ELFStreamer &Str); |
85 | 86 |
86 protected: | 87 protected: |
87 /// Name of the section in convenient string form (instead of a index into the | 88 /// Name of the section in convenient string form (instead of a index into the |
88 /// Section Header String Table, which is not known till later). | 89 /// Section Header String Table, which is not known till later). |
89 const IceString Name; | 90 const std::string Name; |
90 | 91 |
91 // The fields of the header. May only be partially initialized, but should | 92 // The fields of the header. May only be partially initialized, but should |
92 // be fully initialized before writing. | 93 // be fully initialized before writing. |
93 Elf64_Shdr Header; | 94 Elf64_Shdr Header; |
94 | 95 |
95 /// The number of the section after laying out sections. | 96 /// The number of the section after laying out sections. |
96 SizeT Number = NoSectionNumber; | 97 SizeT Number = NoSectionNumber; |
97 }; | 98 }; |
98 | 99 |
99 /// Models text/code sections. Code is written out incrementally and the size of | 100 /// Models text/code sections. Code is written out incrementally and the size of |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 }; | 158 }; |
158 | 159 |
159 /// Models a symbol table. Symbols may be added up until updateIndices is | 160 /// Models a symbol table. Symbols may be added up until updateIndices is |
160 /// called. At that point the indices of each symbol will be finalized. | 161 /// called. At that point the indices of each symbol will be finalized. |
161 class ELFSymbolTableSection : public ELFSection { | 162 class ELFSymbolTableSection : public ELFSection { |
162 ELFSymbolTableSection() = delete; | 163 ELFSymbolTableSection() = delete; |
163 ELFSymbolTableSection(const ELFSymbolTableSection &) = delete; | 164 ELFSymbolTableSection(const ELFSymbolTableSection &) = delete; |
164 ELFSymbolTableSection &operator=(const ELFSymbolTableSection &) = delete; | 165 ELFSymbolTableSection &operator=(const ELFSymbolTableSection &) = delete; |
165 | 166 |
166 public: | 167 public: |
167 ELFSymbolTableSection(const IceString &Name, Elf64_Word ShType, | 168 ELFSymbolTableSection(const std::string &Name, Elf64_Word ShType, |
168 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, | 169 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, |
169 Elf64_Xword ShEntsize) | 170 Elf64_Xword ShEntsize) |
170 : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize), | 171 : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize), |
171 NullSymbol(nullptr) {} | 172 NullSymbolName(), NullSymbol(nullptr) {} |
172 | 173 |
173 /// Create initial entry for a symbol when it is defined. Each entry should | 174 /// Create initial entry for a symbol when it is defined. Each entry should |
174 /// only be defined once. We might want to allow Name to be a dummy name | 175 /// only be defined once. We might want to allow Name to be a dummy name |
175 /// initially, then get updated to the real thing, since Data initializers are | 176 /// initially, then get updated to the real thing, since Data initializers are |
176 /// read before the bitcode's symbol table is read. | 177 /// read before the bitcode's symbol table is read. |
177 void createDefinedSym(const IceString &Name, uint8_t Type, uint8_t Binding, | 178 void createDefinedSym(GlobalString Name, uint8_t Type, uint8_t Binding, |
178 ELFSection *Section, RelocOffsetT Offset, SizeT Size); | 179 ELFSection *Section, RelocOffsetT Offset, SizeT Size); |
179 | 180 |
180 /// Note that a symbol table entry needs to be created for the given symbol | 181 /// Note that a symbol table entry needs to be created for the given symbol |
181 /// because it is undefined. | 182 /// because it is undefined. |
182 void noteUndefinedSym(const IceString &Name, ELFSection *NullSection); | 183 void noteUndefinedSym(GlobalString Name, ELFSection *NullSection); |
183 | 184 |
184 const ELFSym *findSymbol(const IceString &Name) const; | 185 const ELFSym *findSymbol(GlobalString Name) const; |
185 | 186 |
186 void createNullSymbol(ELFSection *NullSection); | 187 void createNullSymbol(ELFSection *NullSection, GlobalContext *Ctx); |
187 const ELFSym *getNullSymbol() const { return NullSymbol; } | 188 const ELFSym *getNullSymbol() const { return NullSymbol; } |
188 | 189 |
189 size_t getSectionDataSize() const { | 190 size_t getSectionDataSize() const { |
190 return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize; | 191 return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize; |
191 } | 192 } |
192 | 193 |
193 size_t getNumLocals() const { return LocalSymbols.size(); } | 194 size_t getNumLocals() const { return LocalSymbols.size(); } |
194 | 195 |
195 void updateIndices(const ELFStringTableSection *StrTab); | 196 void updateIndices(const ELFStringTableSection *StrTab); |
196 | 197 |
197 void writeData(ELFStreamer &Str, bool IsELF64); | 198 void writeData(ELFStreamer &Str, bool IsELF64); |
198 | 199 |
199 private: | 200 private: |
200 // Map from symbol name to its symbol information. This assumes symbols are | 201 // Map from symbol name to its symbol information. This assumes symbols are |
201 // unique across all sections. | 202 // unique across all sections. |
202 using SymtabKey = IceString; | 203 using SymtabKey = GlobalString; |
203 using SymMap = std::map<SymtabKey, ELFSym>; | 204 using SymMap = std::map<SymtabKey, ELFSym>; |
204 | 205 |
205 template <bool IsELF64> | 206 template <bool IsELF64> |
206 void writeSymbolMap(ELFStreamer &Str, const SymMap &Map); | 207 void writeSymbolMap(ELFStreamer &Str, const SymMap &Map); |
207 | 208 |
| 209 GlobalString NullSymbolName; |
208 const ELFSym *NullSymbol; | 210 const ELFSym *NullSymbol; |
209 // Keep Local and Global symbols separate, since the sh_info needs to know | 211 // Keep Local and Global symbols separate, since the sh_info needs to know |
210 // the index of the last LOCAL. | 212 // the index of the last LOCAL. |
211 SymMap LocalSymbols; | 213 SymMap LocalSymbols; |
212 SymMap GlobalSymbols; | 214 SymMap GlobalSymbols; |
213 }; | 215 }; |
214 | 216 |
215 /// Models a relocation section. | 217 /// Models a relocation section. |
216 class ELFRelocationSection : public ELFSection { | 218 class ELFRelocationSection : public ELFSection { |
217 ELFRelocationSection() = delete; | 219 ELFRelocationSection() = delete; |
218 ELFRelocationSection(const ELFRelocationSection &) = delete; | 220 ELFRelocationSection(const ELFRelocationSection &) = delete; |
219 ELFRelocationSection &operator=(const ELFRelocationSection &) = delete; | 221 ELFRelocationSection &operator=(const ELFRelocationSection &) = delete; |
220 | 222 |
221 public: | 223 public: |
222 ELFRelocationSection(const IceString &Name, Elf64_Word ShType, | 224 ELFRelocationSection(const std::string &Name, Elf64_Word ShType, |
223 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, | 225 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, |
224 Elf64_Xword ShEntsize) | 226 Elf64_Xword ShEntsize) |
225 : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize), | 227 : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize), |
226 RelatedSection(nullptr) {} | 228 RelatedSection(nullptr) {} |
227 | 229 |
228 const ELFSection *getRelatedSection() const { return RelatedSection; } | 230 const ELFSection *getRelatedSection() const { return RelatedSection; } |
229 void setRelatedSection(const ELFSection *Section) { | 231 void setRelatedSection(const ELFSection *Section) { |
230 RelatedSection = Section; | 232 RelatedSection = Section; |
231 } | 233 } |
232 | 234 |
(...skipping 24 matching lines...) Expand all Loading... |
257 /// out section headers and symbol table entries. | 259 /// out section headers and symbol table entries. |
258 class ELFStringTableSection : public ELFSection { | 260 class ELFStringTableSection : public ELFSection { |
259 ELFStringTableSection() = delete; | 261 ELFStringTableSection() = delete; |
260 ELFStringTableSection(const ELFStringTableSection &) = delete; | 262 ELFStringTableSection(const ELFStringTableSection &) = delete; |
261 ELFStringTableSection &operator=(const ELFStringTableSection &) = delete; | 263 ELFStringTableSection &operator=(const ELFStringTableSection &) = delete; |
262 | 264 |
263 public: | 265 public: |
264 using ELFSection::ELFSection; | 266 using ELFSection::ELFSection; |
265 | 267 |
266 /// Add a string to the table, in preparation for final layout. | 268 /// Add a string to the table, in preparation for final layout. |
267 void add(const IceString &Str); | 269 void add(const std::string &Str); |
| 270 void add(GlobalString Str) { |
| 271 if (Str.hasStdString()) |
| 272 add(Str.toString()); |
| 273 } |
268 | 274 |
269 /// Finalizes the layout of the string table and fills in the section Data. | 275 /// Finalizes the layout of the string table and fills in the section Data. |
270 void doLayout(); | 276 void doLayout(); |
271 | 277 |
272 /// The first byte of the string table should be \0, so it is an invalid | 278 /// The first byte of the string table should be \0, so it is an invalid |
273 /// index. Indices start out as unknown until layout is complete. | 279 /// index. Indices start out as unknown until layout is complete. |
274 enum { UnknownIndex = 0 }; | 280 enum { UnknownIndex = 0 }; |
275 | 281 |
276 /// Grabs the final index of a string after layout. Returns UnknownIndex if | 282 /// Grabs the final index of a string after layout. Returns UnknownIndex if |
277 /// the string's index is not found. | 283 /// the string's index is not found. |
278 size_t getIndex(const IceString &Str) const; | 284 size_t getIndex(const std::string &Str) const; |
279 | 285 |
280 llvm::StringRef getSectionData() const { | 286 llvm::StringRef getSectionData() const { |
281 assert(isLaidOut()); | 287 assert(isLaidOut()); |
282 return llvm::StringRef(reinterpret_cast<const char *>(StringData.data()), | 288 return llvm::StringRef(reinterpret_cast<const char *>(StringData.data()), |
283 StringData.size()); | 289 StringData.size()); |
284 } | 290 } |
285 | 291 |
286 size_t getSectionDataSize() const { return getSectionData().size(); } | 292 size_t getSectionDataSize() const { return getSectionData().size(); } |
287 | 293 |
288 private: | 294 private: |
289 bool isLaidOut() const { return !StringData.empty(); } | 295 bool isLaidOut() const { return !StringData.empty(); } |
290 | 296 |
291 /// Strings can share a string table entry if they share the same suffix. | 297 /// Strings can share a string table entry if they share the same suffix. |
292 /// E.g., "pop" and "lollipop" can both use the characters in "lollipop", but | 298 /// E.g., "pop" and "lollipop" can both use the characters in "lollipop", but |
293 /// "pops" cannot, and "unpop" cannot either. Though, "pop", "lollipop", and | 299 /// "pops" cannot, and "unpop" cannot either. Though, "pop", "lollipop", and |
294 /// "unpop" share "pop" as the suffix, "pop" can only share the characters | 300 /// "unpop" share "pop" as the suffix, "pop" can only share the characters |
295 /// with one of them. | 301 /// with one of them. |
296 struct SuffixComparator { | 302 struct SuffixComparator { |
297 bool operator()(const IceString &StrA, const IceString &StrB) const; | 303 bool operator()(const std::string &StrA, const std::string &StrB) const; |
298 }; | 304 }; |
299 | 305 |
300 using StringToIndexType = std::map<IceString, size_t, SuffixComparator>; | 306 using StringToIndexType = std::map<std::string, size_t, SuffixComparator>; |
301 | 307 |
302 /// Track strings to their index. Index will be UnknownIndex if not yet laid | 308 /// Track strings to their index. Index will be UnknownIndex if not yet laid |
303 /// out. | 309 /// out. |
304 StringToIndexType StringToIndexMap; | 310 StringToIndexType StringToIndexMap; |
305 | 311 |
306 using RawDataType = std::vector<uint8_t>; | 312 using RawDataType = std::vector<uint8_t>; |
307 RawDataType StringData; | 313 RawDataType StringData; |
308 }; | 314 }; |
309 | 315 |
310 template <bool IsELF64> void ELFSection::writeHeader(ELFStreamer &Str) { | 316 template <bool IsELF64> void ELFSection::writeHeader(ELFStreamer &Str) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 template <bool IsELF64> | 356 template <bool IsELF64> |
351 void ELFRelocationSection::writeData(ELFStreamer &Str, | 357 void ELFRelocationSection::writeData(ELFStreamer &Str, |
352 const ELFSymbolTableSection *SymTab) { | 358 const ELFSymbolTableSection *SymTab) { |
353 for (const AssemblerFixup &Fixup : Fixups) { | 359 for (const AssemblerFixup &Fixup : Fixups) { |
354 const ELFSym *Symbol; | 360 const ELFSym *Symbol; |
355 if (Fixup.isNullSymbol()) { | 361 if (Fixup.isNullSymbol()) { |
356 Symbol = SymTab->getNullSymbol(); | 362 Symbol = SymTab->getNullSymbol(); |
357 } else if (Fixup.valueIsSymbol()) { | 363 } else if (Fixup.valueIsSymbol()) { |
358 Symbol = Fixup.getSymbolValue(); | 364 Symbol = Fixup.getSymbolValue(); |
359 } else { | 365 } else { |
360 const IceString Name = Fixup.symbol(); | 366 GlobalString Name = Fixup.symbol(); |
361 Symbol = SymTab->findSymbol(Name); | 367 Symbol = SymTab->findSymbol(Name); |
362 if (!Symbol) | 368 if (!Symbol) |
363 llvm::report_fatal_error(Name + ": Missing symbol mentioned in reloc"); | 369 llvm::report_fatal_error(Name + ": Missing symbol mentioned in reloc"); |
364 } | 370 } |
365 | 371 |
366 if (IsELF64) { | 372 if (IsELF64) { |
367 Elf64_Rela Rela; | 373 Elf64_Rela Rela; |
368 Rela.r_offset = Fixup.position(); | 374 Rela.r_offset = Fixup.position(); |
369 Rela.setSymbolAndType(Symbol->getNumber(), Fixup.kind()); | 375 Rela.setSymbolAndType(Symbol->getNumber(), Fixup.kind()); |
370 Rela.r_addend = Fixup.offset(); | 376 Rela.r_addend = Fixup.offset(); |
371 Str.writeAddrOrOffset<IsELF64>(Rela.r_offset); | 377 Str.writeAddrOrOffset<IsELF64>(Rela.r_offset); |
372 Str.writeELFXword<IsELF64>(Rela.r_info); | 378 Str.writeELFXword<IsELF64>(Rela.r_info); |
373 Str.writeELFXword<IsELF64>(Rela.r_addend); | 379 Str.writeELFXword<IsELF64>(Rela.r_addend); |
374 } else { | 380 } else { |
375 Elf32_Rel Rel; | 381 Elf32_Rel Rel; |
376 Rel.r_offset = Fixup.position(); | 382 Rel.r_offset = Fixup.position(); |
377 Rel.setSymbolAndType(Symbol->getNumber(), Fixup.kind()); | 383 Rel.setSymbolAndType(Symbol->getNumber(), Fixup.kind()); |
378 Str.writeAddrOrOffset<IsELF64>(Rel.r_offset); | 384 Str.writeAddrOrOffset<IsELF64>(Rel.r_offset); |
379 Str.writeELFWord<IsELF64>(Rel.r_info); | 385 Str.writeELFWord<IsELF64>(Rel.r_info); |
380 } | 386 } |
381 } | 387 } |
382 } | 388 } |
383 | 389 |
384 } // end of namespace Ice | 390 } // end of namespace Ice |
385 | 391 |
386 #endif // SUBZERO_SRC_ICEELFSECTION_H | 392 #endif // SUBZERO_SRC_ICEELFSECTION_H |
OLD | NEW |