Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 //===- subzero/src/IceELFSection.h - Model of ELF sections ------*- C++ -*-===// | |
| 2 // | |
| 3 // The Subzero Code Generator | |
| 4 // | |
| 5 // This file is distributed under the University of Illinois Open Source | |
| 6 // License. See LICENSE.TXT for details. | |
| 7 // | |
| 8 //===----------------------------------------------------------------------===// | |
| 9 // | |
| 10 // Representation of ELF sections. | |
| 11 // | |
| 12 //===----------------------------------------------------------------------===// | |
| 13 | |
| 14 #ifndef SUBZERO_SRC_ICEELFSECTION_H | |
| 15 #define SUBZERO_SRC_ICEELFSECTION_H | |
| 16 | |
| 17 #include "IceDefs.h" | |
| 18 #include "IceELFStreamer.h" | |
| 19 | |
| 20 using namespace llvm::ELF; | |
| 21 | |
| 22 namespace Ice { | |
| 23 | |
| 24 class ELFStreamer; | |
| 25 class ELFStringTableSection; | |
| 26 | |
| 27 // Base representation of an ELF section. | |
| 28 class ELFSection { | |
| 29 ELFSection(const ELFSection &) = delete; | |
| 30 ELFSection &operator=(const ELFSection &) = delete; | |
| 31 | |
| 32 public: | |
| 33 // Constructs an ELF section, filling in fields that will be known | |
| 34 // once the *type* of section is decided. Other fields may be updated | |
| 35 // incrementally or only after the program is completely defined. | |
| 36 ELFSection(const IceString &Name, Elf64_Word sh_type, Elf64_Xword sh_flags, | |
| 37 Elf64_Xword sh_addralign, Elf64_Xword sh_entsize) | |
| 38 : Name(Name), Header(), Number(NoSectionNumber) { | |
| 39 Header.sh_type = sh_type; | |
| 40 Header.sh_flags = sh_flags; | |
| 41 Header.sh_addralign = sh_addralign; | |
| 42 Header.sh_entsize = sh_entsize; | |
| 43 } | |
| 44 | |
| 45 // Sentinel value for a section number/index for before the final | |
| 46 // section index is actually known. | |
| 47 static const SizeT NoSectionNumber; | |
|
Jim Stichnoth
2014/11/21 21:32:22
I think you could do this instead, for slightly be
jvoung (off chromium)
2014/11/24 21:35:46
Done.
| |
| 48 | |
| 49 // Set the section number/index after it is finally known. | |
| 50 void setNumber(SizeT N) { | |
| 51 // Should only set the number once: from NoSectionNumber -> N. | |
| 52 assert(Number == NoSectionNumber); | |
| 53 Number = N; | |
| 54 } | |
| 55 SizeT getNumber() const { | |
| 56 assert(Number != NoSectionNumber); | |
| 57 return Number; | |
| 58 } | |
| 59 | |
| 60 void setSize(Elf64_Xword sh_size) { Header.sh_size = sh_size; } | |
| 61 SizeT getCurrentSize() const { return Header.sh_size; } | |
| 62 | |
| 63 void setNameStrIndex(Elf64_Word sh_name) { Header.sh_name = sh_name; } | |
| 64 | |
| 65 IceString getName() const { return Name; } | |
| 66 | |
| 67 void setLinkNum(Elf64_Word sh_link) { Header.sh_link = sh_link; } | |
| 68 | |
| 69 void setInfoNum(Elf64_Word sh_info) { Header.sh_info = sh_info; } | |
| 70 | |
| 71 void setFileOffset(Elf64_Off sh_offset) { Header.sh_offset = sh_offset; } | |
| 72 | |
| 73 Elf64_Xword getSectionAlign() const { return Header.sh_addralign; } | |
| 74 | |
| 75 // Write the section header out with the given streamer. | |
| 76 template <bool IsELF64> void writeHeader(ELFStreamer &Str); | |
| 77 | |
| 78 protected: | |
| 79 ~ELFSection() {} | |
| 80 | |
| 81 // Name of the section in convenient string form (instead of a index | |
| 82 // into the Section Header String Table, which is not known till later). | |
| 83 IceString Name; | |
| 84 | |
| 85 // The fields of the header. May only be partially initialized, but should | |
| 86 // be fully initialized before writing. | |
| 87 Elf64_Shdr Header; | |
| 88 | |
| 89 // The number of the section after laying out sections. | |
| 90 SizeT Number; | |
| 91 }; | |
| 92 | |
| 93 // Models text/code sections. Code is written out incrementally and the | |
| 94 // size of the section is then updated incrementally. | |
| 95 class ELFTextSection : public ELFSection { | |
| 96 ELFTextSection(const ELFTextSection &) = delete; | |
| 97 ELFTextSection &operator=(const ELFTextSection &) = delete; | |
| 98 | |
| 99 public: | |
| 100 using ELFSection::ELFSection; | |
| 101 | |
| 102 void appendData(ELFStreamer &Str, const llvm::StringRef MoreData); | |
| 103 }; | |
| 104 | |
| 105 // Models data/rodata sections. Data is written out incrementally and the | |
| 106 // size of the section is then updated incrementally. | |
| 107 // Some rodata sections may have fixed entsize and duplicates may be mergeable. | |
| 108 class ELFDataSection : public ELFSection { | |
| 109 ELFDataSection(const ELFDataSection &) = delete; | |
| 110 ELFDataSection &operator=(const ELFDataSection &) = delete; | |
| 111 | |
| 112 public: | |
| 113 using ELFSection::ELFSection; | |
| 114 | |
| 115 void appendData(ELFStreamer &Str, const llvm::StringRef MoreData); | |
| 116 }; | |
| 117 | |
| 118 // Model of ELF symbol table entries. Besides keeping track of the fields | |
| 119 // required for an elf symbol table entry it also tracks the number that | |
| 120 // represents the symbol's final index in the symbol table. | |
| 121 struct ELFSym { | |
| 122 Elf64_Sym Sym; | |
| 123 SizeT Number; | |
| 124 | |
| 125 static const SizeT UnknownNumber; | |
| 126 | |
| 127 void setNumber(SizeT N) { | |
| 128 assert(Number == UnknownNumber); | |
| 129 Number = N; | |
| 130 } | |
| 131 | |
| 132 SizeT getNumber() const { | |
| 133 assert(Number != UnknownNumber); | |
| 134 return Number; | |
| 135 } | |
| 136 }; | |
| 137 | |
| 138 // Models a symbol table. Symbols may be added up until updateIndices is | |
| 139 // called. At that point the indices of each symbol will be finalized. | |
| 140 class ELFSymbolTableSection : public ELFSection { | |
| 141 public: | |
| 142 using ELFSection::ELFSection; | |
| 143 | |
| 144 // Create initial entry for a symbol when it is defined. | |
| 145 // Each entry should only be defined once. | |
| 146 // We might want to allow Name to be a dummy name initially, then | |
| 147 // get updated to the real thing, since Data initializers are read | |
| 148 // before the bitcode's symbol table is read. | |
| 149 void createDefinedSym(const IceString &Name, uint8_t Type, uint8_t Binding, | |
| 150 ELFSection *Section, RelocOffsetT Offset, SizeT Size); | |
| 151 | |
| 152 // Note that a symbol table entry needs to be created for the given | |
| 153 // symbol because it is undefined. | |
| 154 void noteUndefinedSym(const IceString &Name, ELFSection *NullSection); | |
| 155 | |
| 156 size_t getSectionDataSize() const { | |
| 157 return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize; | |
| 158 } | |
| 159 | |
| 160 size_t getNumLocals() const { return LocalSymbols.size(); } | |
| 161 | |
| 162 void updateIndices(const ELFStringTableSection *StrTab); | |
| 163 | |
| 164 void writeData(ELFStreamer &Str, bool IsELF64); | |
| 165 | |
| 166 private: | |
| 167 // Map from symbol name + section to its symbol information. | |
| 168 typedef std::pair<IceString, ELFSection *> SymtabKey; | |
| 169 typedef std::map<SymtabKey, ELFSym> SymMap; | |
| 170 | |
| 171 template <bool IsELF64> | |
| 172 void writeSymbolMap(ELFStreamer &Str, const SymMap &Map); | |
| 173 | |
| 174 // Keep Local and Global symbols separate, since the sh_info needs to | |
| 175 // know the index of the last LOCAL. | |
| 176 SymMap LocalSymbols; | |
| 177 SymMap GlobalSymbols; | |
| 178 }; | |
| 179 | |
| 180 // Base model of a relocation section. | |
| 181 class ELFRelocationSectionBase : public ELFSection { | |
| 182 ELFRelocationSectionBase(const ELFRelocationSectionBase &) = delete; | |
| 183 ELFRelocationSectionBase & | |
| 184 operator=(const ELFRelocationSectionBase &) = delete; | |
| 185 | |
| 186 public: | |
| 187 ELFRelocationSectionBase(const IceString &Name, Elf64_Word sh_type, | |
| 188 Elf64_Xword sh_flags, Elf64_Xword sh_addralign, | |
| 189 Elf64_Xword sh_entsize, ELFSection *RelatedSection) | |
| 190 : ELFSection(Name, sh_type, sh_flags, sh_addralign, sh_entsize), | |
| 191 RelatedSection(RelatedSection) {} | |
| 192 | |
| 193 ELFSection *getRelatedSection() const { return RelatedSection; } | |
| 194 | |
| 195 private: | |
| 196 ELFSection *RelatedSection; | |
| 197 }; | |
| 198 | |
| 199 // ELFRelocationSection which depends on the actual relocation type. | |
| 200 // Specializations are needed depending on the ELFCLASS and whether | |
| 201 // or not addends are explicit or implicitly embedded in the related | |
| 202 // section (ELFCLASS64 pack their r_info field differently from ELFCLASS32). | |
| 203 template <typename RelType> | |
| 204 class ELFRelocationSection : ELFRelocationSectionBase { | |
| 205 ELFRelocationSection(const ELFRelocationSectionBase &) = delete; | |
| 206 ELFRelocationSection &operator=(const ELFRelocationSectionBase &) = delete; | |
| 207 | |
| 208 public: | |
| 209 using ELFRelocationSectionBase::ELFRelocationSectionBase; | |
| 210 | |
| 211 void addRelocations() { | |
| 212 // TODO: fill me in | |
| 213 } | |
| 214 | |
| 215 private: | |
| 216 typedef std::pair<RelType, ELFSym *> ELFRelSym; | |
| 217 typedef std::vector<ELFRelSym> RelocationList; | |
| 218 RelocationList Relocations; | |
| 219 }; | |
| 220 | |
| 221 // Models a string table. The user will build the string table by | |
| 222 // adding strings incrementally. At some point, all strings should be | |
| 223 // known and layOutStrings() should be called. After that, no other | |
| 224 // strings may be added. However, the final offsets of the strings | |
| 225 // can be discovered and used to fill out section headers and symbol | |
| 226 // table entries. | |
| 227 class ELFStringTableSection : public ELFSection { | |
| 228 ELFStringTableSection(const ELFStringTableSection &) = delete; | |
| 229 ELFStringTableSection &operator=(const ELFStringTableSection &) = delete; | |
| 230 | |
| 231 public: | |
| 232 using ELFSection::ELFSection; | |
| 233 | |
| 234 // Add a string to the table, in preparation for final layout. | |
| 235 void add(const IceString &Str); | |
| 236 | |
| 237 // Finalizes the layout of the string table and fills in the section Data. | |
| 238 void doLayout(); | |
| 239 | |
| 240 // Grabs the final index of a string after layout. | |
| 241 size_t getIndex(const IceString &Str) const; | |
| 242 | |
| 243 llvm::StringRef getSectionData() const { | |
| 244 assert(isLaidOut()); | |
| 245 return llvm::StringRef(reinterpret_cast<const char *>(StringData.data()), | |
| 246 StringData.size()); | |
| 247 } | |
| 248 | |
| 249 size_t getSectionDataSize() const { return getSectionData().size(); } | |
| 250 | |
| 251 private: | |
| 252 bool isLaidOut() const { return !StringData.empty(); } | |
| 253 | |
| 254 // Strings can share a string table entry if they share the same suffix. | |
| 255 // E.g., "pop\\0" and "lollipop\0" can both use the characters in | |
|
Jim Stichnoth
2014/11/21 21:32:22
Did you mean for the backslashes to be doubled? (
jvoung (off chromium)
2014/11/24 21:35:46
Hmm, I guess \0 should be fine -- making consisten
| |
| 256 // "lolipop\\0", but "pops\\0" cannot, and "unpop\\0" cannot either. | |
| 257 // Though, "pop\\0", "lollipop\\0", and "unpop\\0" share "pop\\0" as | |
| 258 // the suffix, "pop\\0" can only share the characters with one of them. | |
| 259 struct SuffixComparator { | |
| 260 bool operator()(const IceString &StrA, const IceString &StrB) const; | |
| 261 }; | |
| 262 | |
| 263 typedef std::map<IceString, size_t, SuffixComparator> StringToIndexType; | |
| 264 | |
| 265 static const size_t UnknownIndex; | |
| 266 | |
| 267 // Track strings to their index. Index will be UnknownIndex if not | |
| 268 // yet laid out. | |
| 269 StringToIndexType StringToIndexMap; | |
| 270 | |
| 271 typedef std::vector<uint8_t> RawDataType; | |
| 272 RawDataType StringData; | |
| 273 }; | |
| 274 | |
| 275 template <bool IsELF64> void ELFSection::writeHeader(ELFStreamer &Str) { | |
| 276 Str.writeELFWord<IsELF64>(Header.sh_name); | |
| 277 Str.writeELFWord<IsELF64>(Header.sh_type); | |
| 278 Str.writeELFXword<IsELF64>(Header.sh_flags); | |
| 279 Str.writeAddrOrOffset<IsELF64>(Header.sh_addr); | |
| 280 Str.writeAddrOrOffset<IsELF64>(Header.sh_offset); | |
| 281 Str.writeELFXword<IsELF64>(Header.sh_size); | |
| 282 Str.writeELFWord<IsELF64>(Header.sh_link); | |
| 283 Str.writeELFWord<IsELF64>(Header.sh_info); | |
| 284 Str.writeELFXword<IsELF64>(Header.sh_addralign); | |
| 285 Str.writeELFXword<IsELF64>(Header.sh_entsize); | |
| 286 } | |
| 287 | |
| 288 template <bool IsELF64> | |
| 289 void ELFSymbolTableSection::writeSymbolMap(ELFStreamer &Str, | |
| 290 const SymMap &Map) { | |
| 291 // The order of the fields is different, so branch on IsELF64. | |
| 292 if (IsELF64) { | |
| 293 for (auto &KeyValue : Map) { | |
| 294 const Elf64_Sym &SymInfo = KeyValue.second.Sym; | |
| 295 Str.writeELFWord<IsELF64>(SymInfo.st_name); | |
| 296 Str.write8(SymInfo.st_info); | |
| 297 Str.write8(SymInfo.st_other); | |
| 298 Str.writeLE16(SymInfo.st_shndx); | |
| 299 Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value); | |
| 300 Str.writeELFXword<IsELF64>(SymInfo.st_size); | |
| 301 } | |
| 302 } else { | |
| 303 for (auto &KeyValue : Map) { | |
| 304 const Elf64_Sym &SymInfo = KeyValue.second.Sym; | |
| 305 Str.writeELFWord<IsELF64>(SymInfo.st_name); | |
| 306 Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value); | |
| 307 Str.writeELFWord<IsELF64>(SymInfo.st_size); | |
| 308 Str.write8(SymInfo.st_info); | |
| 309 Str.write8(SymInfo.st_other); | |
| 310 Str.writeLE16(SymInfo.st_shndx); | |
| 311 } | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 } // end of namespace Ice | |
| 316 | |
| 317 #endif // SUBZERO_SRC_ICEELFSECTION_H | |
| OLD | NEW |