OSDN Git Service

bd0d0893dafb50c4548ea893179591c9c41f2e49
[android-x86/external-swiftshader.git] / src / IceELFObjectWriter.cpp
1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===//
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 // This file defines the writer for ELF relocatable object files.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/MathExtras.h"
15
16 #include "assembler.h"
17 #include "IceDefs.h"
18 #include "IceELFObjectWriter.h"
19 #include "IceELFSection.h"
20 #include "IceELFStreamer.h"
21 #include "IceGlobalContext.h"
22 #include "IceGlobalInits.h"
23 #include "IceOperand.h"
24
25 using namespace llvm::ELF;
26
27 namespace Ice {
28
29 namespace {
30
31 struct {
32   bool IsELF64;
33   uint16_t ELFMachine;
34   uint32_t ELFFlags;
35 } ELFTargetInfo[] = {
36 #define X(tag, str, is_elf64, e_machine, e_flags)                              \
37   { is_elf64, e_machine, e_flags }                                             \
38   ,
39       TARGETARCH_TABLE
40 #undef X
41 };
42
43 bool isELF64(TargetArch Arch) {
44   if (Arch < TargetArch_NUM)
45     return ELFTargetInfo[Arch].IsELF64;
46   llvm_unreachable("Invalid target arch for isELF64");
47   return false;
48 }
49
50 uint16_t getELFMachine(TargetArch Arch) {
51   if (Arch < TargetArch_NUM)
52     return ELFTargetInfo[Arch].ELFMachine;
53   llvm_unreachable("Invalid target arch for getELFMachine");
54   return EM_NONE;
55 }
56
57 uint32_t getELFFlags(TargetArch Arch) {
58   if (Arch < TargetArch_NUM)
59     return ELFTargetInfo[Arch].ELFFlags;
60   llvm_unreachable("Invalid target arch for getELFFlags");
61   return 0;
62 }
63
64 } // end of anonymous namespace
65
66 ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out)
67     : Ctx(Ctx), Str(Out), SectionNumbersAssigned(false) {
68   // Create the special bookkeeping sections now.
69   const IceString NullSectionName("");
70   NullSection = new (Ctx.allocate<ELFSection>())
71       ELFSection(NullSectionName, SHT_NULL, 0, 0, 0);
72
73   const IceString ShStrTabName(".shstrtab");
74   ShStrTab = new (Ctx.allocate<ELFStringTableSection>())
75       ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0);
76   ShStrTab->add(ShStrTabName);
77
78   const IceString SymTabName(".symtab");
79   bool IsELF64 = isELF64(Ctx.getTargetArch());
80   const Elf64_Xword SymTabAlign = IsELF64 ? 8 : 4;
81   const Elf64_Xword SymTabEntSize =
82       IsELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
83   static_assert(sizeof(Elf64_Sym) == 24 && sizeof(Elf32_Sym) == 16,
84                 "Elf_Sym sizes cannot be derived from sizeof");
85   SymTab = createSection<ELFSymbolTableSection>(SymTabName, SHT_SYMTAB, 0,
86                                                 SymTabAlign, SymTabEntSize);
87   // The first entry in the symbol table should be a NULL entry.
88   const IceString NullSymName("");
89   SymTab->createDefinedSym(NullSymName, STT_NOTYPE, STB_LOCAL, NullSection, 0,
90                            0);
91
92   const IceString StrTabName(".strtab");
93   StrTab =
94       createSection<ELFStringTableSection>(StrTabName, SHT_STRTAB, 0, 1, 0);
95 }
96
97 template <typename T>
98 T *ELFObjectWriter::createSection(const IceString &Name, Elf64_Word ShType,
99                                   Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
100                                   Elf64_Xword ShEntsize) {
101   assert(!SectionNumbersAssigned);
102   T *NewSection =
103       new (Ctx.allocate<T>()) T(Name, ShType, ShFlags, ShAddralign, ShEntsize);
104   ShStrTab->add(Name);
105   return NewSection;
106 }
107
108 ELFRelocationSection *
109 ELFObjectWriter::createRelocationSection(bool IsELF64,
110                                          const ELFSection *RelatedSection) {
111   // Choice of RELA vs REL is actually separate from elf64 vs elf32,
112   // but in practice we've only had .rela for elf64 (x86-64).
113   // In the future, the two properties may need to be decoupled
114   // and the ShEntSize can vary more.
115   const Elf64_Word ShType = IsELF64 ? SHT_RELA : SHT_REL;
116   IceString RelPrefix = IsELF64 ? ".rela" : ".rel";
117   IceString RelSectionName = RelPrefix + RelatedSection->getName();
118   const Elf64_Xword ShAlign = IsELF64 ? 8 : 4;
119   const Elf64_Xword ShEntSize =
120       IsELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel);
121   static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8,
122                 "Elf_Rel/Rela sizes cannot be derived from sizeof");
123   const Elf64_Xword ShFlags = 0;
124   ELFRelocationSection *RelSection = createSection<ELFRelocationSection>(
125       RelSectionName, ShType, ShFlags, ShAlign, ShEntSize);
126   RelSection->setRelatedSection(RelatedSection);
127   return RelSection;
128 }
129
130 template <typename UserSectionList>
131 void ELFObjectWriter::assignRelSectionNumInPairs(SizeT &CurSectionNumber,
132                                                  UserSectionList &UserSections,
133                                                  RelSectionList &RelSections,
134                                                  SectionList &AllSections) {
135   RelSectionList::iterator RelIt = RelSections.begin();
136   RelSectionList::iterator RelE = RelSections.end();
137   for (ELFSection *UserSection : UserSections) {
138     UserSection->setNumber(CurSectionNumber++);
139     UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName()));
140     AllSections.push_back(UserSection);
141     if (RelIt != RelE) {
142       ELFRelocationSection *RelSection = *RelIt;
143       if (RelSection->getRelatedSection() == UserSection) {
144         RelSection->setInfoNum(UserSection->getNumber());
145         RelSection->setNumber(CurSectionNumber++);
146         RelSection->setNameStrIndex(ShStrTab->getIndex(RelSection->getName()));
147         AllSections.push_back(RelSection);
148         ++RelIt;
149       }
150     }
151   }
152   // Should finish with UserIt at the same time as RelIt.
153   assert(RelIt == RelE);
154   return;
155 }
156
157 void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber,
158                                        RelSectionList &RelSections) {
159   for (ELFRelocationSection *S : RelSections) {
160     S->setLinkNum(SymTabNumber);
161   }
162 }
163
164 void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) {
165   // Go through each section, assigning them section numbers and
166   // and fill in the size for sections that aren't incrementally updated.
167   assert(!SectionNumbersAssigned);
168   SizeT CurSectionNumber = 0;
169   NullSection->setNumber(CurSectionNumber++);
170   // The rest of the fields are initialized to 0, and stay that way.
171   AllSections.push_back(NullSection);
172
173   assignRelSectionNumInPairs<TextSectionList>(CurSectionNumber, TextSections,
174                                               RelTextSections, AllSections);
175   assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, DataSections,
176                                               RelDataSections, AllSections);
177   for (ELFSection *BSSSection : BSSSections) {
178     BSSSection->setNumber(CurSectionNumber++);
179     BSSSection->setNameStrIndex(ShStrTab->getIndex(BSSSection->getName()));
180     AllSections.push_back(BSSSection);
181   }
182   assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, RODataSections,
183                                               RelRODataSections, AllSections);
184
185   ShStrTab->setNumber(CurSectionNumber++);
186   ShStrTab->setNameStrIndex(ShStrTab->getIndex(ShStrTab->getName()));
187   AllSections.push_back(ShStrTab);
188
189   SymTab->setNumber(CurSectionNumber++);
190   SymTab->setNameStrIndex(ShStrTab->getIndex(SymTab->getName()));
191   AllSections.push_back(SymTab);
192
193   StrTab->setNumber(CurSectionNumber++);
194   StrTab->setNameStrIndex(ShStrTab->getIndex(StrTab->getName()));
195   AllSections.push_back(StrTab);
196
197   SymTab->setLinkNum(StrTab->getNumber());
198   SymTab->setInfoNum(SymTab->getNumLocals());
199
200   assignRelLinkNum(SymTab->getNumber(), RelTextSections);
201   assignRelLinkNum(SymTab->getNumber(), RelDataSections);
202   assignRelLinkNum(SymTab->getNumber(), RelRODataSections);
203   SectionNumbersAssigned = true;
204 }
205
206 Elf64_Off ELFObjectWriter::alignFileOffset(Elf64_Xword Align) {
207   Elf64_Off OffsetInFile = Str.tell();
208   Elf64_Xword AlignDiff = Utils::OffsetToAlignment(OffsetInFile, Align);
209   if (AlignDiff == 0)
210     return OffsetInFile;
211   Str.writeZeroPadding(AlignDiff);
212   OffsetInFile += AlignDiff;
213   return OffsetInFile;
214 }
215
216 void ELFObjectWriter::writeFunctionCode(const IceString &FuncName,
217                                         bool IsInternal, const Assembler *Asm) {
218   assert(!SectionNumbersAssigned);
219   ELFTextSection *Section = nullptr;
220   ELFRelocationSection *RelSection = nullptr;
221   if (TextSections.empty()) {
222     // TODO(jvoung): handle ffunction-sections.
223     IceString SectionName = ".text";
224     bool IsELF64 = isELF64(Ctx.getTargetArch());
225     const Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR;
226     // TODO(jvoung): Should be bundle size. Grab it from that target?
227     const Elf64_Xword ShAlign = 32;
228     Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags,
229                                             ShAlign, 0);
230     Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign());
231     Section->setFileOffset(OffsetInFile);
232     TextSections.push_back(Section);
233     RelSection = createRelocationSection(IsELF64, Section);
234     RelTextSections.push_back(RelSection);
235   } else {
236     Section = TextSections[0];
237     RelSection = RelTextSections[0];
238   }
239   RelocOffsetT OffsetInSection = Section->getCurrentSize();
240   // Function symbols are set to 0 size in the symbol table,
241   // in contrast to data symbols which have a proper size.
242   SizeT SymbolSize = 0;
243   Section->appendData(Str, Asm->getBufferView());
244   uint8_t SymbolType;
245   uint8_t SymbolBinding;
246   if (IsInternal) {
247     SymbolType = STT_NOTYPE;
248     SymbolBinding = STB_LOCAL;
249   } else {
250     SymbolType = STT_FUNC;
251     SymbolBinding = STB_GLOBAL;
252   }
253   SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section,
254                            OffsetInSection, SymbolSize);
255   StrTab->add(FuncName);
256
257   // Create a relocation section for the text section if needed, and copy the
258   // fixup information from per-function Assembler memory to the object
259   // writer's memory, for writing later.
260   if (!Asm->fixups().empty()) {
261     RelSection->addRelocations(OffsetInSection, Asm->fixups());
262   }
263 }
264
265 namespace {
266
267 ELFObjectWriter::SectionType
268 classifyGlobalSection(const VariableDeclaration *Var) {
269   if (Var->getIsConstant())
270     return ELFObjectWriter::ROData;
271   if (Var->hasNonzeroInitializer())
272     return ELFObjectWriter::Data;
273   return ELFObjectWriter::BSS;
274 }
275
276 // Partition the Vars list by SectionType into VarsBySection.
277 // If TranslateOnly is non-empty, then only the TranslateOnly variable
278 // is kept for emission.
279 void partitionGlobalsBySection(const VariableDeclarationList &Vars,
280                                VariableDeclarationList VarsBySection[],
281                                const IceString &TranslateOnly) {
282   for (VariableDeclaration *Var : Vars) {
283     if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
284       size_t Section = classifyGlobalSection(Var);
285       assert(Section < ELFObjectWriter::NumSectionTypes);
286       VarsBySection[Section].push_back(Var);
287     }
288   }
289 }
290
291 } // end of anonymous namespace
292
293 void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
294                                        FixupKind RelocationKind) {
295   assert(!SectionNumbersAssigned);
296   VariableDeclarationList VarsBySection[ELFObjectWriter::NumSectionTypes];
297   for (auto &SectionList : VarsBySection)
298     SectionList.reserve(Vars.size());
299   partitionGlobalsBySection(Vars, VarsBySection, Ctx.getFlags().TranslateOnly);
300   bool IsELF64 = isELF64(Ctx.getTargetArch());
301   size_t I = 0;
302   for (auto &SectionList : VarsBySection) {
303     writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind,
304                     IsELF64);
305   }
306 }
307
308 void ELFObjectWriter::writeDataOfType(SectionType ST,
309                                       const VariableDeclarationList &Vars,
310                                       FixupKind RelocationKind, bool IsELF64) {
311   if (Vars.empty())
312     return;
313   ELFDataSection *Section;
314   ELFRelocationSection *RelSection;
315   // TODO(jvoung): Handle fdata-sections.
316   IceString SectionName;
317   Elf64_Xword ShAddralign = 1;
318   for (VariableDeclaration *Var : Vars) {
319     Elf64_Xword Align = Var->getAlignment();
320     ShAddralign = std::max(ShAddralign, Align);
321   }
322   const Elf64_Xword ShEntsize = 0; // non-uniform data element size.
323   // Lift this out, so it can be re-used if we do fdata-sections?
324   switch (ST) {
325   case ROData: {
326     SectionName = ".rodata";
327     // Only expecting to write the data sections all in one shot for now.
328     assert(RODataSections.empty());
329     const Elf64_Xword ShFlags = SHF_ALLOC;
330     Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
331                                             ShAddralign, ShEntsize);
332     Section->setFileOffset(alignFileOffset(ShAddralign));
333     RODataSections.push_back(Section);
334     RelSection = createRelocationSection(IsELF64, Section);
335     RelRODataSections.push_back(RelSection);
336     break;
337   }
338   case Data: {
339     SectionName = ".data";
340     assert(DataSections.empty());
341     const Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
342     Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
343                                             ShAddralign, ShEntsize);
344     Section->setFileOffset(alignFileOffset(ShAddralign));
345     DataSections.push_back(Section);
346     RelSection = createRelocationSection(IsELF64, Section);
347     RelDataSections.push_back(RelSection);
348     break;
349   }
350   case BSS: {
351     SectionName = ".bss";
352     assert(BSSSections.empty());
353     const Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
354     Section = createSection<ELFDataSection>(SectionName, SHT_NOBITS, ShFlags,
355                                             ShAddralign, ShEntsize);
356     Section->setFileOffset(alignFileOffset(ShAddralign));
357     BSSSections.push_back(Section);
358     break;
359   }
360   case NumSectionTypes:
361     llvm::report_fatal_error("Unknown SectionType");
362     break;
363   }
364
365   const uint8_t SymbolType = STT_OBJECT;
366   for (VariableDeclaration *Var : Vars) {
367     // If the variable declaration does not have an initializer, its symtab
368     // entry will be created separately.
369     if (!Var->hasInitializer())
370       continue;
371     Elf64_Xword Align = Var->getAlignment();
372     Section->padToAlignment(Str, Align);
373     SizeT SymbolSize = Var->getNumBytes();
374     bool IsExternal = Var->isExternal() || Ctx.getFlags().DisableInternal;
375     const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
376     IceString MangledName = Var->mangleName(&Ctx);
377     SymTab->createDefinedSym(MangledName, SymbolType, SymbolBinding, Section,
378                              Section->getCurrentSize(), SymbolSize);
379     StrTab->add(MangledName);
380     if (!Var->hasNonzeroInitializer()) {
381       assert(ST == BSS || ST == ROData);
382       if (ST == ROData)
383         Section->appendZeros(Str, SymbolSize);
384       else
385         Section->setSize(Section->getCurrentSize() + SymbolSize);
386     } else {
387       assert(ST != BSS);
388       for (VariableDeclaration::Initializer *Init : Var->getInitializers()) {
389         switch (Init->getKind()) {
390         case VariableDeclaration::Initializer::DataInitializerKind: {
391           const auto Data = llvm::cast<VariableDeclaration::DataInitializer>(
392                                 Init)->getContents();
393           Section->appendData(Str, llvm::StringRef(Data.data(), Data.size()));
394           break;
395         }
396         case VariableDeclaration::Initializer::ZeroInitializerKind:
397           Section->appendZeros(Str, Init->getNumBytes());
398           break;
399         case VariableDeclaration::Initializer::RelocInitializerKind: {
400           const auto Reloc =
401               llvm::cast<VariableDeclaration::RelocInitializer>(Init);
402           AssemblerFixup NewFixup;
403           NewFixup.set_position(Section->getCurrentSize());
404           NewFixup.set_kind(RelocationKind);
405           const bool SuppressMangling = true;
406           NewFixup.set_value(Ctx.getConstantSym(
407               Reloc->getOffset(), Reloc->getDeclaration()->mangleName(&Ctx),
408               SuppressMangling));
409           RelSection->addRelocation(NewFixup);
410           Section->appendRelocationOffset(Str, RelSection->isRela(),
411                                           Reloc->getOffset());
412           break;
413         }
414         }
415       }
416     }
417   }
418 }
419
420 void ELFObjectWriter::writeInitialELFHeader() {
421   assert(!SectionNumbersAssigned);
422   const Elf64_Off DummySHOffset = 0;
423   const SizeT DummySHStrIndex = 0;
424   const SizeT DummyNumSections = 0;
425   if (isELF64(Ctx.getTargetArch())) {
426     writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex,
427                                  DummyNumSections);
428   } else {
429     writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex,
430                                   DummyNumSections);
431   }
432 }
433
434 template <bool IsELF64>
435 void ELFObjectWriter::writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,
436                                              SizeT SectHeaderStrIndex,
437                                              SizeT NumSections) {
438   // Write the e_ident: magic number, class, etc.
439   // The e_ident is byte order and ELF class independent.
440   Str.writeBytes(llvm::StringRef(ElfMagic, strlen(ElfMagic)));
441   Str.write8(IsELF64 ? ELFCLASS64 : ELFCLASS32);
442   Str.write8(ELFDATA2LSB);
443   Str.write8(EV_CURRENT);
444   Str.write8(ELFOSABI_NONE);
445   const uint8_t ELF_ABIVersion = 0;
446   Str.write8(ELF_ABIVersion);
447   Str.writeZeroPadding(EI_NIDENT - EI_PAD);
448
449   // TODO(jvoung): Handle and test > 64K sections.  See the generic ABI doc:
450   // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html
451   // e_shnum should be 0 and then actual number of sections is
452   // stored in the sh_size member of the 0th section.
453   assert(NumSections < SHN_LORESERVE);
454   assert(SectHeaderStrIndex < SHN_LORESERVE);
455
456   // Write the rest of the file header, which does depend on byte order
457   // and ELF class.
458   Str.writeLE16(ET_REL);                             // e_type
459   Str.writeLE16(getELFMachine(Ctx.getTargetArch())); // e_machine
460   Str.writeELFWord<IsELF64>(1);                      // e_version
461   // Since this is for a relocatable object, there is no entry point,
462   // and no program headers.
463   Str.writeAddrOrOffset<IsELF64>(0);                                // e_entry
464   Str.writeAddrOrOffset<IsELF64>(0);                                // e_phoff
465   Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset);              // e_shoff
466   Str.writeELFWord<IsELF64>(getELFFlags(Ctx.getTargetArch()));      // e_flags
467   Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize
468   static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52,
469                 "Elf_Ehdr sizes cannot be derived from sizeof");
470   Str.writeLE16(0); // e_phentsize
471   Str.writeLE16(0); // e_phnum
472   Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr)
473                         : sizeof(Elf32_Shdr)); // e_shentsize
474   static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40,
475                 "Elf_Shdr sizes cannot be derived from sizeof");
476   Str.writeLE16(static_cast<Elf64_Half>(NumSections));        // e_shnum
477   Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx
478 }
479
480 template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
481   ConstantList Pool = Ctx.getConstantPool(Ty);
482   if (Pool.empty()) {
483     return;
484   }
485   SizeT Align = typeAlignInBytes(Ty);
486   size_t EntSize = typeWidthInBytes(Ty);
487   char Buf[20];
488   SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf));
489   assert(WriteAmt == EntSize);
490   // Assume that writing WriteAmt bytes at a time allows us to avoid aligning
491   // between entries.
492   assert(WriteAmt % Align == 0);
493   // Check that we write the full PrimType.
494   assert(WriteAmt == sizeof(typename ConstType::PrimType));
495   const Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE;
496   std::string SecBuffer;
497   llvm::raw_string_ostream SecStrBuf(SecBuffer);
498   SecStrBuf << ".rodata.cst" << WriteAmt;
499   ELFDataSection *Section = createSection<ELFDataSection>(
500       SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt);
501   RODataSections.push_back(Section);
502   SizeT OffsetInSection = 0;
503   // The symbol table entry doesn't need to know the defined symbol's
504   // size since this is in a section with a fixed Entry Size.
505   const SizeT SymbolSize = 0;
506   Section->setFileOffset(alignFileOffset(Align));
507
508   // Write the data.
509   for (Constant *C : Pool) {
510     auto Const = llvm::cast<ConstType>(C);
511     std::string SymBuffer;
512     llvm::raw_string_ostream SymStrBuf(SymBuffer);
513     Const->emitPoolLabel(SymStrBuf);
514     std::string &SymName = SymStrBuf.str();
515     SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section,
516                              OffsetInSection, SymbolSize);
517     StrTab->add(SymName);
518     typename ConstType::PrimType Value = Const->getValue();
519     memcpy(Buf, &Value, WriteAmt);
520     Str.writeBytes(llvm::StringRef(Buf, WriteAmt));
521     OffsetInSection += WriteAmt;
522   }
523   Section->setSize(OffsetInSection);
524 }
525
526 // Instantiate known needed versions of the template, since we are
527 // defining the function in the .cpp file instead of the .h file.
528 // We may need to instantiate constant pools for integers as well
529 // if we do constant-pooling of large integers to remove them
530 // from the instruction stream (fewer bytes controlled by an attacker).
531 template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty);
532
533 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty);
534
535 void ELFObjectWriter::writeAllRelocationSections(bool IsELF64) {
536   writeRelocationSections(IsELF64, RelTextSections);
537   writeRelocationSections(IsELF64, RelDataSections);
538   writeRelocationSections(IsELF64, RelRODataSections);
539 }
540
541 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) {
542   for (const Constant *S : UndefSyms) {
543     const auto Sym = llvm::cast<ConstantRelocatable>(S);
544     const IceString &Name = Sym->getName();
545     assert(Sym->getOffset() == 0);
546     assert(Sym->getSuppressMangling());
547     SymTab->noteUndefinedSym(Name, NullSection);
548     StrTab->add(Name);
549   }
550 }
551
552 void ELFObjectWriter::writeRelocationSections(bool IsELF64,
553                                               RelSectionList &RelSections) {
554   for (ELFRelocationSection *RelSec : RelSections) {
555     Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign());
556     RelSec->setFileOffset(Offset);
557     RelSec->setSize(RelSec->getSectionDataSize());
558     if (IsELF64) {
559       RelSec->writeData<true>(Ctx, Str, SymTab);
560     } else {
561       RelSec->writeData<false>(Ctx, Str, SymTab);
562     }
563   }
564 }
565
566 void ELFObjectWriter::writeNonUserSections() {
567   bool IsELF64 = isELF64(Ctx.getTargetArch());
568
569   // Write out the shstrtab now that all sections are known.
570   ShStrTab->doLayout();
571   ShStrTab->setSize(ShStrTab->getSectionDataSize());
572   Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign());
573   ShStrTab->setFileOffset(ShStrTabOffset);
574   Str.writeBytes(ShStrTab->getSectionData());
575
576   SectionList AllSections;
577   assignSectionNumbersInfo(AllSections);
578
579   // Finalize the regular StrTab and fix up references in the SymTab.
580   StrTab->doLayout();
581   StrTab->setSize(StrTab->getSectionDataSize());
582
583   SymTab->updateIndices(StrTab);
584
585   Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign());
586   SymTab->setFileOffset(SymTabOffset);
587   SymTab->setSize(SymTab->getSectionDataSize());
588   SymTab->writeData(Str, IsELF64);
589
590   Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign());
591   StrTab->setFileOffset(StrTabOffset);
592   Str.writeBytes(StrTab->getSectionData());
593
594   writeAllRelocationSections(IsELF64);
595
596   // Write out the section headers.
597   const size_t ShdrAlign = IsELF64 ? 8 : 4;
598   Elf64_Off ShOffset = alignFileOffset(ShdrAlign);
599   for (const auto S : AllSections) {
600     if (IsELF64)
601       S->writeHeader<true>(Str);
602     else
603       S->writeHeader<false>(Str);
604   }
605
606   // Finally write the updated ELF header w/ the correct number of sections.
607   Str.seek(0);
608   if (IsELF64) {
609     writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(),
610                                  AllSections.size());
611   } else {
612     writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(),
613                                   AllSections.size());
614   }
615 }
616
617 } // end of namespace Ice