Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 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 | //===----------------------------------------------------------------------===// |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 9 | /// |
| 10 | /// \file |
| 11 | /// Representation of ELF sections. |
| 12 | /// |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #ifndef SUBZERO_SRC_ICEELFSECTION_H |
| 16 | #define SUBZERO_SRC_ICEELFSECTION_H |
| 17 | |
| 18 | #include "IceDefs.h" |
| 19 | #include "IceELFStreamer.h" |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 20 | #include "IceFixups.h" |
| 21 | #include "IceOperand.h" |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 22 | |
| 23 | using namespace llvm::ELF; |
| 24 | |
| 25 | namespace Ice { |
| 26 | |
| 27 | class ELFStreamer; |
| 28 | class ELFStringTableSection; |
| 29 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 30 | /// Base representation of an ELF section. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 31 | class ELFSection { |
Jim Stichnoth | c6ead20 | 2015-02-24 09:30:30 -0800 | [diff] [blame] | 32 | ELFSection() = delete; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 33 | ELFSection(const ELFSection &) = delete; |
| 34 | ELFSection &operator=(const ELFSection &) = delete; |
| 35 | |
| 36 | public: |
John Porto | 1bec8bc | 2015-06-22 10:51:13 -0700 | [diff] [blame] | 37 | virtual ~ELFSection() = default; |
| 38 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 39 | /// Sentinel value for a section number/index for before the final |
| 40 | /// section index is actually known. The dummy NULL section will be assigned |
| 41 | /// number 0, and it is referenced by the dummy 0-th symbol in the symbol |
| 42 | /// table, so use max() instead of 0. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 43 | enum { NoSectionNumber = std::numeric_limits<SizeT>::max() }; |
| 44 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 45 | /// Constructs an ELF section, filling in fields that will be known |
| 46 | /// once the *type* of section is decided. Other fields may be updated |
| 47 | /// incrementally or only after the program is completely defined. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 48 | ELFSection(const IceString &Name, Elf64_Word ShType, Elf64_Xword ShFlags, |
| 49 | Elf64_Xword ShAddralign, Elf64_Xword ShEntsize) |
Jim Stichnoth | eafb56c | 2015-06-22 10:35:22 -0700 | [diff] [blame] | 50 | : Name(Name), Header() { |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 51 | Header.sh_type = ShType; |
| 52 | Header.sh_flags = ShFlags; |
| 53 | Header.sh_addralign = ShAddralign; |
| 54 | Header.sh_entsize = ShEntsize; |
| 55 | } |
| 56 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 57 | /// Set the section number/index after it is finally known. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 58 | void setNumber(SizeT N) { |
| 59 | // Should only set the number once: from NoSectionNumber -> N. |
| 60 | assert(Number == NoSectionNumber); |
| 61 | Number = N; |
| 62 | } |
| 63 | SizeT getNumber() const { |
| 64 | assert(Number != NoSectionNumber); |
| 65 | return Number; |
| 66 | } |
| 67 | |
| 68 | void setSize(Elf64_Xword sh_size) { Header.sh_size = sh_size; } |
| 69 | SizeT getCurrentSize() const { return Header.sh_size; } |
| 70 | |
| 71 | void setNameStrIndex(Elf64_Word sh_name) { Header.sh_name = sh_name; } |
| 72 | |
Jan Voung | c9ec579 | 2015-02-05 17:31:28 -0800 | [diff] [blame] | 73 | const IceString &getName() const { return Name; } |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 74 | |
| 75 | void setLinkNum(Elf64_Word sh_link) { Header.sh_link = sh_link; } |
| 76 | |
| 77 | void setInfoNum(Elf64_Word sh_info) { Header.sh_info = sh_info; } |
| 78 | |
| 79 | void setFileOffset(Elf64_Off sh_offset) { Header.sh_offset = sh_offset; } |
| 80 | |
| 81 | Elf64_Xword getSectionAlign() const { return Header.sh_addralign; } |
| 82 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 83 | /// Write the section header out with the given streamer. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 84 | template <bool IsELF64> void writeHeader(ELFStreamer &Str); |
| 85 | |
| 86 | protected: |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 87 | /// Name of the section in convenient string form (instead of a index |
| 88 | /// into the Section Header String Table, which is not known till later). |
Jan Voung | c9ec579 | 2015-02-05 17:31:28 -0800 | [diff] [blame] | 89 | const IceString Name; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 90 | |
| 91 | // The fields of the header. May only be partially initialized, but should |
| 92 | // be fully initialized before writing. |
| 93 | Elf64_Shdr Header; |
| 94 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 95 | /// The number of the section after laying out sections. |
Jim Stichnoth | eafb56c | 2015-06-22 10:35:22 -0700 | [diff] [blame] | 96 | SizeT Number = NoSectionNumber; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 97 | }; |
| 98 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 99 | /// Models text/code sections. Code is written out incrementally and the |
| 100 | /// size of the section is then updated incrementally. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 101 | class ELFTextSection : public ELFSection { |
Jim Stichnoth | c6ead20 | 2015-02-24 09:30:30 -0800 | [diff] [blame] | 102 | ELFTextSection() = delete; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 103 | ELFTextSection(const ELFTextSection &) = delete; |
| 104 | ELFTextSection &operator=(const ELFTextSection &) = delete; |
| 105 | |
| 106 | public: |
| 107 | using ELFSection::ELFSection; |
| 108 | |
| 109 | void appendData(ELFStreamer &Str, const llvm::StringRef MoreData); |
| 110 | }; |
| 111 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 112 | /// Models data/rodata sections. Data is written out incrementally and the |
| 113 | /// size of the section is then updated incrementally. |
| 114 | /// Some rodata sections may have fixed entsize and duplicates may be mergeable. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 115 | class ELFDataSection : public ELFSection { |
Jim Stichnoth | c6ead20 | 2015-02-24 09:30:30 -0800 | [diff] [blame] | 116 | ELFDataSection() = delete; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 117 | ELFDataSection(const ELFDataSection &) = delete; |
| 118 | ELFDataSection &operator=(const ELFDataSection &) = delete; |
| 119 | |
| 120 | public: |
| 121 | using ELFSection::ELFSection; |
| 122 | |
| 123 | void appendData(ELFStreamer &Str, const llvm::StringRef MoreData); |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 124 | |
| 125 | void appendZeros(ELFStreamer &Str, SizeT NumBytes); |
| 126 | |
| 127 | void appendRelocationOffset(ELFStreamer &Str, bool IsRela, |
| 128 | RelocOffsetT RelocOffset); |
| 129 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 130 | /// Pad the next section offset for writing data elements to the requested |
| 131 | /// alignment. If the section is NOBITS then do not actually write out |
| 132 | /// the padding and only update the section size. |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 133 | void padToAlignment(ELFStreamer &Str, Elf64_Xword Align); |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 134 | }; |
| 135 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 136 | /// Model of ELF symbol table entries. Besides keeping track of the fields |
| 137 | /// required for an elf symbol table entry it also tracks the number that |
| 138 | /// represents the symbol's final index in the symbol table. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 139 | struct ELFSym { |
| 140 | Elf64_Sym Sym; |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 141 | ELFSection *Section; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 142 | SizeT Number; |
| 143 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 144 | /// Sentinel value for symbols that haven't been assigned a number yet. |
| 145 | /// The dummy 0-th symbol will be assigned number 0, so don't use that. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 146 | enum { UnknownNumber = std::numeric_limits<SizeT>::max() }; |
| 147 | |
| 148 | void setNumber(SizeT N) { |
| 149 | assert(Number == UnknownNumber); |
| 150 | Number = N; |
| 151 | } |
| 152 | |
| 153 | SizeT getNumber() const { |
| 154 | assert(Number != UnknownNumber); |
| 155 | return Number; |
| 156 | } |
| 157 | }; |
| 158 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 159 | /// 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. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 161 | class ELFSymbolTableSection : public ELFSection { |
Jim Stichnoth | c6ead20 | 2015-02-24 09:30:30 -0800 | [diff] [blame] | 162 | ELFSymbolTableSection() = delete; |
| 163 | ELFSymbolTableSection(const ELFSymbolTableSection &) = delete; |
| 164 | ELFSymbolTableSection &operator=(const ELFSymbolTableSection &) = delete; |
| 165 | |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 166 | public: |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 167 | ELFSymbolTableSection(const IceString &Name, Elf64_Word ShType, |
| 168 | Elf64_Xword ShFlags, Elf64_Xword ShAddralign, |
| 169 | Elf64_Xword ShEntsize) |
| 170 | : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize), |
| 171 | NullSymbol(nullptr) {} |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 172 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 173 | /// Create initial entry for a symbol when it is defined. |
| 174 | /// Each entry should only be defined once. |
| 175 | /// We might want to allow Name to be a dummy name initially, then |
| 176 | /// get updated to the real thing, since Data initializers are read |
| 177 | /// before the bitcode's symbol table is read. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 178 | void createDefinedSym(const IceString &Name, uint8_t Type, uint8_t Binding, |
| 179 | ELFSection *Section, RelocOffsetT Offset, SizeT Size); |
| 180 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 181 | /// Note that a symbol table entry needs to be created for the given |
| 182 | /// symbol because it is undefined. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 183 | void noteUndefinedSym(const IceString &Name, ELFSection *NullSection); |
| 184 | |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 185 | const ELFSym *findSymbol(const IceString &Name) const; |
| 186 | |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 187 | void createNullSymbol(ELFSection *NullSection); |
| 188 | const ELFSym *getNullSymbol() const { return NullSymbol; } |
| 189 | |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 190 | size_t getSectionDataSize() const { |
| 191 | return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize; |
| 192 | } |
| 193 | |
| 194 | size_t getNumLocals() const { return LocalSymbols.size(); } |
| 195 | |
| 196 | void updateIndices(const ELFStringTableSection *StrTab); |
| 197 | |
| 198 | void writeData(ELFStreamer &Str, bool IsELF64); |
| 199 | |
| 200 | private: |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 201 | // Map from symbol name to its symbol information. |
| 202 | // This assumes symbols are unique across all sections. |
| 203 | typedef IceString SymtabKey; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 204 | typedef std::map<SymtabKey, ELFSym> SymMap; |
| 205 | |
| 206 | template <bool IsELF64> |
| 207 | void writeSymbolMap(ELFStreamer &Str, const SymMap &Map); |
| 208 | |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 209 | const ELFSym *NullSymbol; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 210 | // Keep Local and Global symbols separate, since the sh_info needs to |
| 211 | // know the index of the last LOCAL. |
| 212 | SymMap LocalSymbols; |
| 213 | SymMap GlobalSymbols; |
| 214 | }; |
| 215 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 216 | /// Models a relocation section. |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 217 | class ELFRelocationSection : public ELFSection { |
Jim Stichnoth | c6ead20 | 2015-02-24 09:30:30 -0800 | [diff] [blame] | 218 | ELFRelocationSection() = delete; |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 219 | ELFRelocationSection(const ELFRelocationSection &) = delete; |
| 220 | ELFRelocationSection &operator=(const ELFRelocationSection &) = delete; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 221 | |
| 222 | public: |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 223 | ELFRelocationSection(const IceString &Name, Elf64_Word ShType, |
| 224 | Elf64_Xword ShFlags, Elf64_Xword ShAddralign, |
| 225 | Elf64_Xword ShEntsize) |
| 226 | : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize), |
| 227 | RelatedSection(nullptr) {} |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 228 | |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 229 | const ELFSection *getRelatedSection() const { return RelatedSection; } |
| 230 | void setRelatedSection(const ELFSection *Section) { |
| 231 | RelatedSection = Section; |
| 232 | } |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 233 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 234 | /// Track additional relocations which start out relative to offset 0, |
| 235 | /// but should be adjusted to be relative to BaseOff. |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 236 | void addRelocations(RelocOffsetT BaseOff, const FixupRefList &FixupRefs); |
| 237 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 238 | /// Track a single additional relocation. |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 239 | void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); } |
| 240 | |
Jan Voung | 261cae3 | 2015-02-01 10:31:03 -0800 | [diff] [blame] | 241 | size_t getSectionDataSize() const; |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 242 | |
| 243 | template <bool IsELF64> |
| 244 | void writeData(const GlobalContext &Ctx, ELFStreamer &Str, |
| 245 | const ELFSymbolTableSection *SymTab); |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 246 | |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 247 | bool isRela() const { return Header.sh_type == SHT_RELA; } |
| 248 | |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 249 | private: |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 250 | const ELFSection *RelatedSection; |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 251 | FixupList Fixups; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 252 | }; |
| 253 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 254 | /// Models a string table. The user will build the string table by |
| 255 | /// adding strings incrementally. At some point, all strings should be |
| 256 | /// known and doLayout() should be called. After that, no other |
| 257 | /// strings may be added. However, the final offsets of the strings |
| 258 | /// can be discovered and used to fill out section headers and symbol |
| 259 | /// table entries. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 260 | class ELFStringTableSection : public ELFSection { |
Jim Stichnoth | c6ead20 | 2015-02-24 09:30:30 -0800 | [diff] [blame] | 261 | ELFStringTableSection() = delete; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 262 | ELFStringTableSection(const ELFStringTableSection &) = delete; |
| 263 | ELFStringTableSection &operator=(const ELFStringTableSection &) = delete; |
| 264 | |
| 265 | public: |
| 266 | using ELFSection::ELFSection; |
| 267 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 268 | /// Add a string to the table, in preparation for final layout. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 269 | void add(const IceString &Str); |
| 270 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 271 | /// Finalizes the layout of the string table and fills in the section Data. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 272 | void doLayout(); |
| 273 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 274 | /// The first byte of the string table should be \0, so it is an |
| 275 | /// invalid index. Indices start out as unknown until layout is complete. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 276 | enum { UnknownIndex = 0 }; |
| 277 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 278 | /// Grabs the final index of a string after layout. Returns UnknownIndex |
| 279 | /// if the string's index is not found. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 280 | size_t getIndex(const IceString &Str) const; |
| 281 | |
| 282 | llvm::StringRef getSectionData() const { |
| 283 | assert(isLaidOut()); |
| 284 | return llvm::StringRef(reinterpret_cast<const char *>(StringData.data()), |
| 285 | StringData.size()); |
| 286 | } |
| 287 | |
| 288 | size_t getSectionDataSize() const { return getSectionData().size(); } |
| 289 | |
| 290 | private: |
| 291 | bool isLaidOut() const { return !StringData.empty(); } |
| 292 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 293 | /// Strings can share a string table entry if they share the same |
| 294 | /// suffix. E.g., "pop" and "lollipop" can both use the characters |
| 295 | /// in "lollipop", but "pops" cannot, and "unpop" cannot either. |
| 296 | /// Though, "pop", "lollipop", and "unpop" share "pop" as the suffix, |
| 297 | /// "pop" can only share the characters with one of them. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 298 | struct SuffixComparator { |
| 299 | bool operator()(const IceString &StrA, const IceString &StrB) const; |
| 300 | }; |
| 301 | |
| 302 | typedef std::map<IceString, size_t, SuffixComparator> StringToIndexType; |
| 303 | |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 304 | /// Track strings to their index. Index will be UnknownIndex if not |
| 305 | /// yet laid out. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 306 | StringToIndexType StringToIndexMap; |
| 307 | |
| 308 | typedef std::vector<uint8_t> RawDataType; |
| 309 | RawDataType StringData; |
| 310 | }; |
| 311 | |
| 312 | template <bool IsELF64> void ELFSection::writeHeader(ELFStreamer &Str) { |
| 313 | Str.writeELFWord<IsELF64>(Header.sh_name); |
| 314 | Str.writeELFWord<IsELF64>(Header.sh_type); |
| 315 | Str.writeELFXword<IsELF64>(Header.sh_flags); |
| 316 | Str.writeAddrOrOffset<IsELF64>(Header.sh_addr); |
| 317 | Str.writeAddrOrOffset<IsELF64>(Header.sh_offset); |
| 318 | Str.writeELFXword<IsELF64>(Header.sh_size); |
| 319 | Str.writeELFWord<IsELF64>(Header.sh_link); |
| 320 | Str.writeELFWord<IsELF64>(Header.sh_info); |
| 321 | Str.writeELFXword<IsELF64>(Header.sh_addralign); |
| 322 | Str.writeELFXword<IsELF64>(Header.sh_entsize); |
| 323 | } |
| 324 | |
| 325 | template <bool IsELF64> |
| 326 | void ELFSymbolTableSection::writeSymbolMap(ELFStreamer &Str, |
| 327 | const SymMap &Map) { |
| 328 | // The order of the fields is different, so branch on IsELF64. |
| 329 | if (IsELF64) { |
| 330 | for (auto &KeyValue : Map) { |
| 331 | const Elf64_Sym &SymInfo = KeyValue.second.Sym; |
| 332 | Str.writeELFWord<IsELF64>(SymInfo.st_name); |
| 333 | Str.write8(SymInfo.st_info); |
| 334 | Str.write8(SymInfo.st_other); |
| 335 | Str.writeLE16(SymInfo.st_shndx); |
| 336 | Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value); |
| 337 | Str.writeELFXword<IsELF64>(SymInfo.st_size); |
| 338 | } |
| 339 | } else { |
| 340 | for (auto &KeyValue : Map) { |
| 341 | const Elf64_Sym &SymInfo = KeyValue.second.Sym; |
| 342 | Str.writeELFWord<IsELF64>(SymInfo.st_name); |
| 343 | Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value); |
| 344 | Str.writeELFWord<IsELF64>(SymInfo.st_size); |
| 345 | Str.write8(SymInfo.st_info); |
| 346 | Str.write8(SymInfo.st_other); |
| 347 | Str.writeLE16(SymInfo.st_shndx); |
| 348 | } |
| 349 | } |
| 350 | } |
| 351 | |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 352 | template <bool IsELF64> |
| 353 | void ELFRelocationSection::writeData(const GlobalContext &Ctx, ELFStreamer &Str, |
| 354 | const ELFSymbolTableSection *SymTab) { |
| 355 | for (const AssemblerFixup &Fixup : Fixups) { |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 356 | const ELFSym *Symbol; |
| 357 | if (Fixup.isNullSymbol()) |
| 358 | Symbol = SymTab->getNullSymbol(); |
| 359 | else |
| 360 | Symbol = SymTab->findSymbol(Fixup.symbol(&Ctx)); |
Jan Voung | 261cae3 | 2015-02-01 10:31:03 -0800 | [diff] [blame] | 361 | if (!Symbol) |
| 362 | llvm::report_fatal_error("Missing symbol mentioned in reloc"); |
| 363 | |
| 364 | if (IsELF64) { |
Jan Voung | b7db1a5 | 2015-07-21 09:39:01 -0700 | [diff] [blame] | 365 | llvm_unreachable( |
| 366 | "Not tested -- check that Fixup.offset() is correct even for pc-rel"); |
Jan Voung | 261cae3 | 2015-02-01 10:31:03 -0800 | [diff] [blame] | 367 | Elf64_Rela Rela; |
| 368 | Rela.r_offset = Fixup.position(); |
| 369 | Rela.setSymbolAndType(Symbol->getNumber(), Fixup.kind()); |
| 370 | Rela.r_addend = Fixup.offset(); |
| 371 | Str.writeAddrOrOffset<IsELF64>(Rela.r_offset); |
| 372 | Str.writeELFXword<IsELF64>(Rela.r_info); |
| 373 | Str.writeELFXword<IsELF64>(Rela.r_addend); |
| 374 | } else { |
| 375 | Elf32_Rel Rel; |
| 376 | Rel.r_offset = Fixup.position(); |
| 377 | Rel.setSymbolAndType(Symbol->getNumber(), Fixup.kind()); |
| 378 | Str.writeAddrOrOffset<IsELF64>(Rel.r_offset); |
| 379 | Str.writeELFWord<IsELF64>(Rel.r_info); |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 380 | } |
| 381 | } |
| 382 | } |
| 383 | |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 384 | } // end of namespace Ice |
| 385 | |
| 386 | #endif // SUBZERO_SRC_ICEELFSECTION_H |