| 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 |