blob: 5cf89a5287795572b0123557039def15aee9fa5a [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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// Representation of ELF sections.
12///
Jan Voung08c3bcd2014-12-01 17:55:16 -080013//===----------------------------------------------------------------------===//
14
15#ifndef SUBZERO_SRC_ICEELFSECTION_H
16#define SUBZERO_SRC_ICEELFSECTION_H
17
18#include "IceDefs.h"
19#include "IceELFStreamer.h"
Jan Voungec270732015-01-12 17:00:22 -080020#include "IceFixups.h"
21#include "IceOperand.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080022
23using namespace llvm::ELF;
24
25namespace Ice {
26
27class ELFStreamer;
28class ELFStringTableSection;
29
Andrew Scull9612d322015-07-06 14:53:25 -070030/// Base representation of an ELF section.
Jan Voung08c3bcd2014-12-01 17:55:16 -080031class ELFSection {
Jim Stichnothc6ead202015-02-24 09:30:30 -080032 ELFSection() = delete;
Jan Voung08c3bcd2014-12-01 17:55:16 -080033 ELFSection(const ELFSection &) = delete;
34 ELFSection &operator=(const ELFSection &) = delete;
35
36public:
John Porto1bec8bc2015-06-22 10:51:13 -070037 virtual ~ELFSection() = default;
38
Andrew Scull9612d322015-07-06 14:53:25 -070039 /// 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 Voung08c3bcd2014-12-01 17:55:16 -080043 enum { NoSectionNumber = std::numeric_limits<SizeT>::max() };
44
Andrew Scull9612d322015-07-06 14:53:25 -070045 /// 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 Voung08c3bcd2014-12-01 17:55:16 -080048 ELFSection(const IceString &Name, Elf64_Word ShType, Elf64_Xword ShFlags,
49 Elf64_Xword ShAddralign, Elf64_Xword ShEntsize)
Jim Stichnotheafb56c2015-06-22 10:35:22 -070050 : Name(Name), Header() {
Jan Voung08c3bcd2014-12-01 17:55:16 -080051 Header.sh_type = ShType;
52 Header.sh_flags = ShFlags;
53 Header.sh_addralign = ShAddralign;
54 Header.sh_entsize = ShEntsize;
55 }
56
Andrew Scull9612d322015-07-06 14:53:25 -070057 /// Set the section number/index after it is finally known.
Jan Voung08c3bcd2014-12-01 17:55:16 -080058 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 Voungc9ec5792015-02-05 17:31:28 -080073 const IceString &getName() const { return Name; }
Jan Voung08c3bcd2014-12-01 17:55:16 -080074
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 Scull9612d322015-07-06 14:53:25 -070083 /// Write the section header out with the given streamer.
Jan Voung08c3bcd2014-12-01 17:55:16 -080084 template <bool IsELF64> void writeHeader(ELFStreamer &Str);
85
86protected:
Andrew Scull9612d322015-07-06 14:53:25 -070087 /// 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 Voungc9ec5792015-02-05 17:31:28 -080089 const IceString Name;
Jan Voung08c3bcd2014-12-01 17:55:16 -080090
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 Scull9612d322015-07-06 14:53:25 -070095 /// The number of the section after laying out sections.
Jim Stichnotheafb56c2015-06-22 10:35:22 -070096 SizeT Number = NoSectionNumber;
Jan Voung08c3bcd2014-12-01 17:55:16 -080097};
98
Andrew Scull9612d322015-07-06 14:53:25 -070099/// Models text/code sections. Code is written out incrementally and the
100/// size of the section is then updated incrementally.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800101class ELFTextSection : public ELFSection {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800102 ELFTextSection() = delete;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800103 ELFTextSection(const ELFTextSection &) = delete;
104 ELFTextSection &operator=(const ELFTextSection &) = delete;
105
106public:
107 using ELFSection::ELFSection;
108
109 void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
110};
111
Andrew Scull9612d322015-07-06 14:53:25 -0700112/// 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 Voung08c3bcd2014-12-01 17:55:16 -0800115class ELFDataSection : public ELFSection {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800116 ELFDataSection() = delete;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800117 ELFDataSection(const ELFDataSection &) = delete;
118 ELFDataSection &operator=(const ELFDataSection &) = delete;
119
120public:
121 using ELFSection::ELFSection;
122
123 void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
Jan Voung72984d82015-01-29 14:42:38 -0800124
125 void appendZeros(ELFStreamer &Str, SizeT NumBytes);
126
127 void appendRelocationOffset(ELFStreamer &Str, bool IsRela,
128 RelocOffsetT RelocOffset);
129
Andrew Scull9612d322015-07-06 14:53:25 -0700130 /// 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 Voung72984d82015-01-29 14:42:38 -0800133 void padToAlignment(ELFStreamer &Str, Elf64_Xword Align);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800134};
135
Andrew Scull9612d322015-07-06 14:53:25 -0700136/// 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 Voung08c3bcd2014-12-01 17:55:16 -0800139struct ELFSym {
140 Elf64_Sym Sym;
Jan Voungec270732015-01-12 17:00:22 -0800141 ELFSection *Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800142 SizeT Number;
143
Andrew Scull9612d322015-07-06 14:53:25 -0700144 /// 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 Voung08c3bcd2014-12-01 17:55:16 -0800146 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 Scull9612d322015-07-06 14:53:25 -0700159/// 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 Voung08c3bcd2014-12-01 17:55:16 -0800161class ELFSymbolTableSection : public ELFSection {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800162 ELFSymbolTableSection() = delete;
163 ELFSymbolTableSection(const ELFSymbolTableSection &) = delete;
164 ELFSymbolTableSection &operator=(const ELFSymbolTableSection &) = delete;
165
Jan Voung08c3bcd2014-12-01 17:55:16 -0800166public:
Jan Voungf644a4b2015-03-19 11:57:52 -0700167 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 Voung08c3bcd2014-12-01 17:55:16 -0800172
Andrew Scull9612d322015-07-06 14:53:25 -0700173 /// 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 Voung08c3bcd2014-12-01 17:55:16 -0800178 void createDefinedSym(const IceString &Name, uint8_t Type, uint8_t Binding,
179 ELFSection *Section, RelocOffsetT Offset, SizeT Size);
180
Andrew Scull9612d322015-07-06 14:53:25 -0700181 /// Note that a symbol table entry needs to be created for the given
182 /// symbol because it is undefined.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800183 void noteUndefinedSym(const IceString &Name, ELFSection *NullSection);
184
Jan Voungec270732015-01-12 17:00:22 -0800185 const ELFSym *findSymbol(const IceString &Name) const;
186
Jan Voungf644a4b2015-03-19 11:57:52 -0700187 void createNullSymbol(ELFSection *NullSection);
188 const ELFSym *getNullSymbol() const { return NullSymbol; }
189
Jan Voung08c3bcd2014-12-01 17:55:16 -0800190 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
200private:
Jan Voungec270732015-01-12 17:00:22 -0800201 // Map from symbol name to its symbol information.
202 // This assumes symbols are unique across all sections.
203 typedef IceString SymtabKey;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800204 typedef std::map<SymtabKey, ELFSym> SymMap;
205
206 template <bool IsELF64>
207 void writeSymbolMap(ELFStreamer &Str, const SymMap &Map);
208
Jan Voungf644a4b2015-03-19 11:57:52 -0700209 const ELFSym *NullSymbol;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800210 // 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 Scull9612d322015-07-06 14:53:25 -0700216/// Models a relocation section.
Jan Voungec270732015-01-12 17:00:22 -0800217class ELFRelocationSection : public ELFSection {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800218 ELFRelocationSection() = delete;
Jan Voungec270732015-01-12 17:00:22 -0800219 ELFRelocationSection(const ELFRelocationSection &) = delete;
220 ELFRelocationSection &operator=(const ELFRelocationSection &) = delete;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800221
222public:
Jan Voungf644a4b2015-03-19 11:57:52 -0700223 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 Voung08c3bcd2014-12-01 17:55:16 -0800228
Jan Voung72984d82015-01-29 14:42:38 -0800229 const ELFSection *getRelatedSection() const { return RelatedSection; }
230 void setRelatedSection(const ELFSection *Section) {
231 RelatedSection = Section;
232 }
Jan Voungec270732015-01-12 17:00:22 -0800233
Andrew Scull9612d322015-07-06 14:53:25 -0700234 /// Track additional relocations which start out relative to offset 0,
235 /// but should be adjusted to be relative to BaseOff.
Jan Voungec270732015-01-12 17:00:22 -0800236 void addRelocations(RelocOffsetT BaseOff, const FixupRefList &FixupRefs);
237
Andrew Scull9612d322015-07-06 14:53:25 -0700238 /// Track a single additional relocation.
Jan Voung72984d82015-01-29 14:42:38 -0800239 void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); }
240
Jan Voung261cae32015-02-01 10:31:03 -0800241 size_t getSectionDataSize() const;
Jan Voungec270732015-01-12 17:00:22 -0800242
243 template <bool IsELF64>
244 void writeData(const GlobalContext &Ctx, ELFStreamer &Str,
245 const ELFSymbolTableSection *SymTab);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800246
Jan Voung72984d82015-01-29 14:42:38 -0800247 bool isRela() const { return Header.sh_type == SHT_RELA; }
248
Jan Voung08c3bcd2014-12-01 17:55:16 -0800249private:
Jan Voung72984d82015-01-29 14:42:38 -0800250 const ELFSection *RelatedSection;
Jan Voungec270732015-01-12 17:00:22 -0800251 FixupList Fixups;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800252};
253
Andrew Scull9612d322015-07-06 14:53:25 -0700254/// 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 Voung08c3bcd2014-12-01 17:55:16 -0800260class ELFStringTableSection : public ELFSection {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800261 ELFStringTableSection() = delete;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800262 ELFStringTableSection(const ELFStringTableSection &) = delete;
263 ELFStringTableSection &operator=(const ELFStringTableSection &) = delete;
264
265public:
266 using ELFSection::ELFSection;
267
Andrew Scull9612d322015-07-06 14:53:25 -0700268 /// Add a string to the table, in preparation for final layout.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800269 void add(const IceString &Str);
270
Andrew Scull9612d322015-07-06 14:53:25 -0700271 /// Finalizes the layout of the string table and fills in the section Data.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800272 void doLayout();
273
Andrew Scull9612d322015-07-06 14:53:25 -0700274 /// 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 Voung08c3bcd2014-12-01 17:55:16 -0800276 enum { UnknownIndex = 0 };
277
Andrew Scull9612d322015-07-06 14:53:25 -0700278 /// Grabs the final index of a string after layout. Returns UnknownIndex
279 /// if the string's index is not found.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800280 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
290private:
291 bool isLaidOut() const { return !StringData.empty(); }
292
Andrew Scull9612d322015-07-06 14:53:25 -0700293 /// 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 Voung08c3bcd2014-12-01 17:55:16 -0800298 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 Scull9612d322015-07-06 14:53:25 -0700304 /// Track strings to their index. Index will be UnknownIndex if not
305 /// yet laid out.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800306 StringToIndexType StringToIndexMap;
307
308 typedef std::vector<uint8_t> RawDataType;
309 RawDataType StringData;
310};
311
312template <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
325template <bool IsELF64>
326void 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 Voungec270732015-01-12 17:00:22 -0800352template <bool IsELF64>
353void ELFRelocationSection::writeData(const GlobalContext &Ctx, ELFStreamer &Str,
354 const ELFSymbolTableSection *SymTab) {
355 for (const AssemblerFixup &Fixup : Fixups) {
Jan Voungf644a4b2015-03-19 11:57:52 -0700356 const ELFSym *Symbol;
357 if (Fixup.isNullSymbol())
358 Symbol = SymTab->getNullSymbol();
359 else
360 Symbol = SymTab->findSymbol(Fixup.symbol(&Ctx));
Jan Voung261cae32015-02-01 10:31:03 -0800361 if (!Symbol)
362 llvm::report_fatal_error("Missing symbol mentioned in reloc");
363
364 if (IsELF64) {
Jan Voungb7db1a52015-07-21 09:39:01 -0700365 llvm_unreachable(
366 "Not tested -- check that Fixup.offset() is correct even for pc-rel");
Jan Voung261cae32015-02-01 10:31:03 -0800367 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 Voungec270732015-01-12 17:00:22 -0800380 }
381 }
382}
383
Jan Voung08c3bcd2014-12-01 17:55:16 -0800384} // end of namespace Ice
385
386#endif // SUBZERO_SRC_ICEELFSECTION_H