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