blob: 4663b71773ad7bdb2596aa3f2c36603e3b50c6ce [file] [log] [blame]
Jan Voung08c3bcd2014-12-01 17:55:16 -08001//===- 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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Defines the writer for ELF relocatable object files.
Andrew Scull9612d322015-07-06 14:53:25 -070012///
Jan Voung08c3bcd2014-12-01 17:55:16 -080013//===----------------------------------------------------------------------===//
14
John Porto67f8de92015-06-25 10:14:17 -070015#include "IceELFObjectWriter.h"
Jan Voung72984d82015-01-29 14:42:38 -080016
John Portoaff4ccf2015-06-10 16:35:06 -070017#include "IceAssembler.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080018#include "IceDefs.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080019#include "IceELFSection.h"
20#include "IceELFStreamer.h"
21#include "IceGlobalContext.h"
22#include "IceGlobalInits.h"
Andrew Scull86df4e92015-07-30 13:54:44 -070023#include "IceInst.h"
Jan Voung91a3e2c2015-01-09 13:01:42 -080024#include "IceOperand.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080025
John Portodc619252016-02-10 15:57:16 -080026#include "llvm/Support/ELF.h"
27#include "llvm/Support/MathExtras.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080028
29namespace Ice {
30
31namespace {
32
John Porto56958cb2016-01-14 09:18:18 -080033constexpr struct {
Jan Voung08c3bcd2014-12-01 17:55:16 -080034 bool IsELF64;
35 uint16_t ELFMachine;
36 uint32_t ELFFlags;
John Porto56958cb2016-01-14 09:18:18 -080037} ELFTargetInfo[TargetArch_NUM] = {
Jan Voung08c3bcd2014-12-01 17:55:16 -080038#define X(tag, str, is_elf64, e_machine, e_flags) \
39 { is_elf64, e_machine, e_flags } \
40 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080041 TARGETARCH_TABLE
Jan Voung08c3bcd2014-12-01 17:55:16 -080042#undef X
43};
44
John Porto56958cb2016-01-14 09:18:18 -080045bool isELF64(const ClFlags &Flags) {
46 const TargetArch Arch = Flags.getTargetArch();
47 if (Arch >= TargetArch_NUM) {
48 llvm_unreachable("Invalid target arch for isELF64");
49 return false;
50 }
51
Nicolas Capens41ce47c2016-09-16 17:00:12 -040052 if (Flags.getApplicationBinaryInterface() == ABI_PNaCl &&
53 !Flags.getUseSandboxing()) {
54 // Unsandboxed PNaCl code is always ELF32 (pexes are ILP32.)
John Porto56958cb2016-01-14 09:18:18 -080055 return false;
56 }
57
58 return ELFTargetInfo[Arch].IsELF64;
Jan Voung08c3bcd2014-12-01 17:55:16 -080059}
60
61uint16_t getELFMachine(TargetArch Arch) {
62 if (Arch < TargetArch_NUM)
63 return ELFTargetInfo[Arch].ELFMachine;
64 llvm_unreachable("Invalid target arch for getELFMachine");
65 return EM_NONE;
66}
67
68uint32_t getELFFlags(TargetArch Arch) {
69 if (Arch < TargetArch_NUM)
70 return ELFTargetInfo[Arch].ELFFlags;
71 llvm_unreachable("Invalid target arch for getELFFlags");
72 return 0;
73}
74
75} // end of anonymous namespace
76
77ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out)
Karl Schimpfd4699942016-04-02 09:55:31 -070078 : Ctx(Ctx), Str(Out), ELF64(isELF64(getFlags())) {
Jan Voung08c3bcd2014-12-01 17:55:16 -080079 // Create the special bookkeeping sections now.
Jim Stichnoth467ffe52016-03-29 15:01:06 -070080 constexpr char NullSectionName[] = "";
Jan Voung08c3bcd2014-12-01 17:55:16 -080081 NullSection = new (Ctx.allocate<ELFSection>())
82 ELFSection(NullSectionName, SHT_NULL, 0, 0, 0);
83
Jim Stichnoth467ffe52016-03-29 15:01:06 -070084 constexpr char ShStrTabName[] = ".shstrtab";
Jan Voung08c3bcd2014-12-01 17:55:16 -080085 ShStrTab = new (Ctx.allocate<ELFStringTableSection>())
86 ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0);
87 ShStrTab->add(ShStrTabName);
88
Jim Stichnoth467ffe52016-03-29 15:01:06 -070089 constexpr char SymTabName[] = ".symtab";
Jan Voung1f47ad02015-03-20 15:01:26 -070090 const Elf64_Xword SymTabAlign = ELF64 ? 8 : 4;
Jan Voung08c3bcd2014-12-01 17:55:16 -080091 const Elf64_Xword SymTabEntSize =
Jan Voung1f47ad02015-03-20 15:01:26 -070092 ELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
Jan Voung08c3bcd2014-12-01 17:55:16 -080093 static_assert(sizeof(Elf64_Sym) == 24 && sizeof(Elf32_Sym) == 16,
94 "Elf_Sym sizes cannot be derived from sizeof");
95 SymTab = createSection<ELFSymbolTableSection>(SymTabName, SHT_SYMTAB, 0,
96 SymTabAlign, SymTabEntSize);
Jim Stichnoth467ffe52016-03-29 15:01:06 -070097 SymTab->createNullSymbol(NullSection, &Ctx);
Jan Voung08c3bcd2014-12-01 17:55:16 -080098
Jim Stichnoth467ffe52016-03-29 15:01:06 -070099 constexpr char StrTabName[] = ".strtab";
Jan Voung08c3bcd2014-12-01 17:55:16 -0800100 StrTab =
101 createSection<ELFStringTableSection>(StrTabName, SHT_STRTAB, 0, 1, 0);
102}
103
104template <typename T>
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700105T *ELFObjectWriter::createSection(const std::string &Name, Elf64_Word ShType,
Jan Voung08c3bcd2014-12-01 17:55:16 -0800106 Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
107 Elf64_Xword ShEntsize) {
108 assert(!SectionNumbersAssigned);
109 T *NewSection =
110 new (Ctx.allocate<T>()) T(Name, ShType, ShFlags, ShAddralign, ShEntsize);
111 ShStrTab->add(Name);
112 return NewSection;
113}
114
Jan Voung72984d82015-01-29 14:42:38 -0800115ELFRelocationSection *
Jan Voung1f47ad02015-03-20 15:01:26 -0700116ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) {
Andrew Scull57e12682015-09-16 11:30:19 -0700117 // Choice of RELA vs REL is actually separate from elf64 vs elf32, but in
118 // practice we've only had .rela for elf64 (x86-64). In the future, the two
119 // properties may need to be decoupled and the ShEntSize can vary more.
Jan Voung1f47ad02015-03-20 15:01:26 -0700120 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700121 const std::string RelPrefix = ELF64 ? ".rela" : ".rel";
122 const std::string RelSectionName = RelPrefix + RelatedSection->getName();
Jan Voung1f47ad02015-03-20 15:01:26 -0700123 const Elf64_Xword ShAlign = ELF64 ? 8 : 4;
124 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel);
Jan Voung72984d82015-01-29 14:42:38 -0800125 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8,
126 "Elf_Rel/Rela sizes cannot be derived from sizeof");
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700127 constexpr Elf64_Xword ShFlags = 0;
Jan Voung72984d82015-01-29 14:42:38 -0800128 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>(
129 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize);
130 RelSection->setRelatedSection(RelatedSection);
131 return RelSection;
132}
133
Jan Voung08c3bcd2014-12-01 17:55:16 -0800134template <typename UserSectionList>
135void ELFObjectWriter::assignRelSectionNumInPairs(SizeT &CurSectionNumber,
136 UserSectionList &UserSections,
137 RelSectionList &RelSections,
138 SectionList &AllSections) {
139 RelSectionList::iterator RelIt = RelSections.begin();
140 RelSectionList::iterator RelE = RelSections.end();
141 for (ELFSection *UserSection : UserSections) {
142 UserSection->setNumber(CurSectionNumber++);
143 UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName()));
144 AllSections.push_back(UserSection);
145 if (RelIt != RelE) {
Jan Voungec270732015-01-12 17:00:22 -0800146 ELFRelocationSection *RelSection = *RelIt;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800147 if (RelSection->getRelatedSection() == UserSection) {
148 RelSection->setInfoNum(UserSection->getNumber());
149 RelSection->setNumber(CurSectionNumber++);
150 RelSection->setNameStrIndex(ShStrTab->getIndex(RelSection->getName()));
151 AllSections.push_back(RelSection);
152 ++RelIt;
153 }
154 }
155 }
156 // Should finish with UserIt at the same time as RelIt.
157 assert(RelIt == RelE);
158 return;
159}
160
161void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber,
162 RelSectionList &RelSections) {
Jan Voungec270732015-01-12 17:00:22 -0800163 for (ELFRelocationSection *S : RelSections) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800164 S->setLinkNum(SymTabNumber);
165 }
166}
167
168void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) {
Andrew Scull57e12682015-09-16 11:30:19 -0700169 // Go through each section, assigning them section numbers and and fill in
170 // the size for sections that aren't incrementally updated.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800171 assert(!SectionNumbersAssigned);
172 SizeT CurSectionNumber = 0;
173 NullSection->setNumber(CurSectionNumber++);
174 // The rest of the fields are initialized to 0, and stay that way.
175 AllSections.push_back(NullSection);
176
177 assignRelSectionNumInPairs<TextSectionList>(CurSectionNumber, TextSections,
178 RelTextSections, AllSections);
179 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, DataSections,
180 RelDataSections, AllSections);
Jan Voung72984d82015-01-29 14:42:38 -0800181 for (ELFSection *BSSSection : BSSSections) {
182 BSSSection->setNumber(CurSectionNumber++);
183 BSSSection->setNameStrIndex(ShStrTab->getIndex(BSSSection->getName()));
184 AllSections.push_back(BSSSection);
185 }
186 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, RODataSections,
187 RelRODataSections, AllSections);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800188
189 ShStrTab->setNumber(CurSectionNumber++);
190 ShStrTab->setNameStrIndex(ShStrTab->getIndex(ShStrTab->getName()));
191 AllSections.push_back(ShStrTab);
192
193 SymTab->setNumber(CurSectionNumber++);
194 SymTab->setNameStrIndex(ShStrTab->getIndex(SymTab->getName()));
195 AllSections.push_back(SymTab);
196
197 StrTab->setNumber(CurSectionNumber++);
198 StrTab->setNameStrIndex(ShStrTab->getIndex(StrTab->getName()));
199 AllSections.push_back(StrTab);
200
201 SymTab->setLinkNum(StrTab->getNumber());
202 SymTab->setInfoNum(SymTab->getNumLocals());
203
204 assignRelLinkNum(SymTab->getNumber(), RelTextSections);
205 assignRelLinkNum(SymTab->getNumber(), RelDataSections);
Jan Voung72984d82015-01-29 14:42:38 -0800206 assignRelLinkNum(SymTab->getNumber(), RelRODataSections);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800207 SectionNumbersAssigned = true;
208}
209
210Elf64_Off ELFObjectWriter::alignFileOffset(Elf64_Xword Align) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800211 Elf64_Off OffsetInFile = Str.tell();
Jan Voung72984d82015-01-29 14:42:38 -0800212 Elf64_Xword AlignDiff = Utils::OffsetToAlignment(OffsetInFile, Align);
213 if (AlignDiff == 0)
Jan Voung08c3bcd2014-12-01 17:55:16 -0800214 return OffsetInFile;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800215 Str.writeZeroPadding(AlignDiff);
216 OffsetInFile += AlignDiff;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800217 return OffsetInFile;
218}
219
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700220void ELFObjectWriter::writeFunctionCode(GlobalString FuncName, bool IsInternal,
221 Assembler *Asm) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800222 assert(!SectionNumbersAssigned);
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700223 TimerMarker T_func(&Ctx, FuncName.toStringOrEmpty());
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800224 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voungec270732015-01-12 17:00:22 -0800225 ELFTextSection *Section = nullptr;
Jan Voung72984d82015-01-29 14:42:38 -0800226 ELFRelocationSection *RelSection = nullptr;
Karl Schimpfd4699942016-04-02 09:55:31 -0700227 const bool FunctionSections = getFlags().getFunctionSections();
Jan Voungcb165ca2015-02-24 08:53:52 -0800228 if (TextSections.empty() || FunctionSections) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700229 std::string SectionName = ".text";
Jan Voungcb165ca2015-02-24 08:53:52 -0800230 if (FunctionSections)
231 SectionName += "." + FuncName;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700232 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR;
Jan Vounge9079cb2015-02-25 09:08:44 -0800233 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes();
Jan Voung08c3bcd2014-12-01 17:55:16 -0800234 Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags,
235 ShAlign, 0);
236 Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign());
237 Section->setFileOffset(OffsetInFile);
238 TextSections.push_back(Section);
Jan Voung1f47ad02015-03-20 15:01:26 -0700239 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800240 RelTextSections.push_back(RelSection);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800241 } else {
242 Section = TextSections[0];
Jan Voung72984d82015-01-29 14:42:38 -0800243 RelSection = RelTextSections[0];
Jan Voung08c3bcd2014-12-01 17:55:16 -0800244 }
John Porto56958cb2016-01-14 09:18:18 -0800245 const RelocOffsetT OffsetInSection = Section->getCurrentSize();
Andrew Scull57e12682015-09-16 11:30:19 -0700246 // Function symbols are set to 0 size in the symbol table, in contrast to
247 // data symbols which have a proper size.
John Porto56958cb2016-01-14 09:18:18 -0800248 constexpr SizeT SymbolSize = 0;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800249 uint8_t SymbolType;
250 uint8_t SymbolBinding;
Karl Schimpfd4699942016-04-02 09:55:31 -0700251 if (IsInternal && !getFlags().getDisableInternal()) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800252 SymbolType = STT_NOTYPE;
253 SymbolBinding = STB_LOCAL;
254 } else {
255 SymbolType = STT_FUNC;
256 SymbolBinding = STB_GLOBAL;
257 }
258 SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section,
259 OffsetInSection, SymbolSize);
260 StrTab->add(FuncName);
Jan Voungec270732015-01-12 17:00:22 -0800261
Jan Voungcb165ca2015-02-24 08:53:52 -0800262 // Copy the fixup information from per-function Assembler memory to the
263 // object writer's memory, for writing later.
John Porto6e8d3fa2016-02-04 10:35:20 -0800264 const auto &Fixups = Asm->fixups();
265 if (!Fixups.empty()) {
266 if (!RelSection->isRela()) {
267 // This is a non-rela section, so we need to update the instruction stream
268 // with the relocation addends.
269 for (const auto *Fixup : Fixups) {
270 Fixup->emitOffset(Asm);
271 }
272 }
Jim Stichnoth3e324002016-03-08 16:18:40 -0800273 RelSection->addRelocations(OffsetInSection, Asm->fixups(), SymTab);
Jan Voungec270732015-01-12 17:00:22 -0800274 }
John Porto6e8d3fa2016-02-04 10:35:20 -0800275 Section->appendData(Str, Asm->getBufferView());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800276}
277
Jan Voung72984d82015-01-29 14:42:38 -0800278namespace {
279
280ELFObjectWriter::SectionType
281classifyGlobalSection(const VariableDeclaration *Var) {
282 if (Var->getIsConstant())
283 return ELFObjectWriter::ROData;
284 if (Var->hasNonzeroInitializer())
285 return ELFObjectWriter::Data;
286 return ELFObjectWriter::BSS;
287}
288
Andrew Scull57e12682015-09-16 11:30:19 -0700289// Partition the Vars list by SectionType into VarsBySection. If TranslateOnly
290// is non-empty, then only the TranslateOnly variable is kept for emission.
Jan Voung72984d82015-01-29 14:42:38 -0800291void partitionGlobalsBySection(const VariableDeclarationList &Vars,
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700292 VariableDeclarationPartition VarsBySection[]) {
Jan Voung72984d82015-01-29 14:42:38 -0800293 for (VariableDeclaration *Var : Vars) {
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700294 if (getFlags().matchTranslateOnly(Var->getName(), 0)) {
Jan Voung72984d82015-01-29 14:42:38 -0800295 size_t Section = classifyGlobalSection(Var);
JF Bastienae6e12c2015-01-31 10:13:25 -0800296 assert(Section < ELFObjectWriter::NumSectionTypes);
Jan Voung72984d82015-01-29 14:42:38 -0800297 VarsBySection[Section].push_back(Var);
298 }
299 }
300}
301
302} // end of anonymous namespace
303
Jaydeep Patil3da9f652016-11-03 22:54:06 -0700304void ELFObjectWriter::writeTargetRODataSection(const std::string &Name,
305 Elf64_Word ShType,
306 Elf64_Xword ShFlags,
307 Elf64_Xword ShAddralign,
308 Elf64_Xword ShEntsize,
309 const llvm::StringRef &SecData) {
310 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
311 assert(!SectionNumbersAssigned);
312 ELFDataSection *Section = createSection<ELFDataSection>(
313 Name, ShType, ShFlags, ShAddralign, ShEntsize);
314 Section->setFileOffset(alignFileOffset(ShAddralign));
315 Section->appendData(Str, llvm::StringRef(SecData.data(), SecData.size()));
316 RODataSections.push_back(Section);
317}
318
Jan Voung72984d82015-01-29 14:42:38 -0800319void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
John Porto8b1a7052015-06-17 13:20:08 -0700320 FixupKind RelocationKind,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700321 const std::string &SectionSuffix,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800322 bool IsPIC) {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800323 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800324 assert(!SectionNumbersAssigned);
John Portoa78e4ba2016-03-15 09:28:04 -0700325 VariableDeclarationPartition VarsBySection[ELFObjectWriter::NumSectionTypes];
Jan Voung72984d82015-01-29 14:42:38 -0800326 for (auto &SectionList : VarsBySection)
327 SectionList.reserve(Vars.size());
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700328 partitionGlobalsBySection(Vars, VarsBySection);
Jan Voung72984d82015-01-29 14:42:38 -0800329 size_t I = 0;
330 for (auto &SectionList : VarsBySection) {
John Porto8b1a7052015-06-17 13:20:08 -0700331 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800332 SectionSuffix, IsPIC);
Jan Voung72984d82015-01-29 14:42:38 -0800333 }
334}
335
John Porto8b1a7052015-06-17 13:20:08 -0700336namespace {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700337std::string MangleSectionName(const char Base[], const std::string &Suffix) {
John Porto8b1a7052015-06-17 13:20:08 -0700338 if (Suffix.empty())
339 return Base;
340 return Base + ("." + Suffix);
341}
342} // end of anonymous namespace
343
344// TODO(jvoung): Handle fdata-sections.
JF Bastienae6e12c2015-01-31 10:13:25 -0800345void ELFObjectWriter::writeDataOfType(SectionType ST,
John Portoa78e4ba2016-03-15 09:28:04 -0700346 const VariableDeclarationPartition &Vars,
John Porto8b1a7052015-06-17 13:20:08 -0700347 FixupKind RelocationKind,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700348 const std::string &SectionSuffix,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800349 bool IsPIC) {
Jan Voung77973cc2015-02-03 12:48:38 -0800350 if (Vars.empty())
351 return;
Jan Voung72984d82015-01-29 14:42:38 -0800352 ELFDataSection *Section;
353 ELFRelocationSection *RelSection;
Jan Voung77973cc2015-02-03 12:48:38 -0800354 Elf64_Xword ShAddralign = 1;
Jan Voung72984d82015-01-29 14:42:38 -0800355 for (VariableDeclaration *Var : Vars) {
356 Elf64_Xword Align = Var->getAlignment();
357 ShAddralign = std::max(ShAddralign, Align);
358 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700359 constexpr Elf64_Xword ShEntsize = 0; // non-uniform data element size.
Jan Voung72984d82015-01-29 14:42:38 -0800360 // Lift this out, so it can be re-used if we do fdata-sections?
JF Bastienae6e12c2015-01-31 10:13:25 -0800361 switch (ST) {
362 case ROData: {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700363 const std::string SectionName =
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800364 MangleSectionName(IsPIC ? ".data.rel.ro" : ".rodata", SectionSuffix);
Jim Stichnothcaeaa272016-01-10 12:53:44 -0800365 const Elf64_Xword ShFlags = IsPIC ? (SHF_ALLOC | SHF_WRITE) : SHF_ALLOC;
Jan Voung72984d82015-01-29 14:42:38 -0800366 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
367 ShAddralign, ShEntsize);
368 Section->setFileOffset(alignFileOffset(ShAddralign));
369 RODataSections.push_back(Section);
Jan Voung1f47ad02015-03-20 15:01:26 -0700370 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800371 RelRODataSections.push_back(RelSection);
372 break;
373 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800374 case Data: {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700375 const std::string SectionName = MangleSectionName(".data", SectionSuffix);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700376 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
Jan Voung72984d82015-01-29 14:42:38 -0800377 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
378 ShAddralign, ShEntsize);
379 Section->setFileOffset(alignFileOffset(ShAddralign));
380 DataSections.push_back(Section);
Jan Voung1f47ad02015-03-20 15:01:26 -0700381 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800382 RelDataSections.push_back(RelSection);
383 break;
384 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800385 case BSS: {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700386 const std::string SectionName = MangleSectionName(".bss", SectionSuffix);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700387 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
Jan Voung72984d82015-01-29 14:42:38 -0800388 Section = createSection<ELFDataSection>(SectionName, SHT_NOBITS, ShFlags,
389 ShAddralign, ShEntsize);
390 Section->setFileOffset(alignFileOffset(ShAddralign));
391 BSSSections.push_back(Section);
392 break;
393 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800394 case NumSectionTypes:
Jan Voung72984d82015-01-29 14:42:38 -0800395 llvm::report_fatal_error("Unknown SectionType");
396 break;
397 }
398
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700399 constexpr uint8_t SymbolType = STT_OBJECT;
Jan Voung72984d82015-01-29 14:42:38 -0800400 for (VariableDeclaration *Var : Vars) {
Jan Voung77973cc2015-02-03 12:48:38 -0800401 // If the variable declaration does not have an initializer, its symtab
402 // entry will be created separately.
403 if (!Var->hasInitializer())
404 continue;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700405 constexpr Elf64_Xword MinAlign = 1;
John Porto267f2bf2016-03-24 06:11:29 -0700406 const auto Align = std::max<Elf64_Xword>(MinAlign, Var->getAlignment());
Jan Voung72984d82015-01-29 14:42:38 -0800407 Section->padToAlignment(Str, Align);
408 SizeT SymbolSize = Var->getNumBytes();
Karl Schimpfd4699942016-04-02 09:55:31 -0700409 bool IsExternal = Var->isExternal() || getFlags().getDisableInternal();
Jan Voung72984d82015-01-29 14:42:38 -0800410 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700411 GlobalString Name = Var->getName();
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800412 SymTab->createDefinedSym(Name, SymbolType, SymbolBinding, Section,
Jan Voung72984d82015-01-29 14:42:38 -0800413 Section->getCurrentSize(), SymbolSize);
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800414 StrTab->add(Name);
Jan Voung72984d82015-01-29 14:42:38 -0800415 if (!Var->hasNonzeroInitializer()) {
JF Bastienae6e12c2015-01-31 10:13:25 -0800416 assert(ST == BSS || ST == ROData);
417 if (ST == ROData)
Jan Voung72984d82015-01-29 14:42:38 -0800418 Section->appendZeros(Str, SymbolSize);
419 else
420 Section->setSize(Section->getCurrentSize() + SymbolSize);
421 } else {
JF Bastienae6e12c2015-01-31 10:13:25 -0800422 assert(ST != BSS);
John Portoa78e4ba2016-03-15 09:28:04 -0700423 for (const auto *Init : Var->getInitializers()) {
Jan Voung72984d82015-01-29 14:42:38 -0800424 switch (Init->getKind()) {
425 case VariableDeclaration::Initializer::DataInitializerKind: {
Qining Lu7cd53512015-06-26 09:36:00 -0700426 const auto &Data =
John Portoa78e4ba2016-03-15 09:28:04 -0700427 llvm::cast<VariableDeclaration::DataInitializer>(Init)
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700428 ->getContents();
Jan Voung72984d82015-01-29 14:42:38 -0800429 Section->appendData(Str, llvm::StringRef(Data.data(), Data.size()));
430 break;
431 }
432 case VariableDeclaration::Initializer::ZeroInitializerKind:
433 Section->appendZeros(Str, Init->getNumBytes());
434 break;
435 case VariableDeclaration::Initializer::RelocInitializerKind: {
John Portodc619252016-02-10 15:57:16 -0800436 const auto *Reloc =
John Portoa78e4ba2016-03-15 09:28:04 -0700437 llvm::cast<VariableDeclaration::RelocInitializer>(Init);
Jan Voung72984d82015-01-29 14:42:38 -0800438 AssemblerFixup NewFixup;
439 NewFixup.set_position(Section->getCurrentSize());
John Portodc619252016-02-10 15:57:16 -0800440 NewFixup.set_kind(Reloc->hasFixup() ? Reloc->getFixup()
441 : RelocationKind);
442 assert(NewFixup.kind() != llvm::ELF::R_ARM_NONE);
Jan Voung72984d82015-01-29 14:42:38 -0800443 NewFixup.set_value(Ctx.getConstantSym(
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800444 Reloc->getOffset(), Reloc->getDeclaration()->getName()));
Jan Voung72984d82015-01-29 14:42:38 -0800445 RelSection->addRelocation(NewFixup);
446 Section->appendRelocationOffset(Str, RelSection->isRela(),
447 Reloc->getOffset());
448 break;
449 }
450 }
451 }
452 }
453 }
Jan Voung08c3bcd2014-12-01 17:55:16 -0800454}
455
456void ELFObjectWriter::writeInitialELFHeader() {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800457 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800458 assert(!SectionNumbersAssigned);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700459 constexpr Elf64_Off DummySHOffset = 0;
460 constexpr SizeT DummySHStrIndex = 0;
461 constexpr SizeT DummyNumSections = 0;
Jan Voung1f47ad02015-03-20 15:01:26 -0700462 if (ELF64) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800463 writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex,
464 DummyNumSections);
465 } else {
466 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex,
467 DummyNumSections);
468 }
469}
470
471template <bool IsELF64>
Jan Vounga601cc52014-12-03 15:51:22 -0800472void ELFObjectWriter::writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,
Jan Voung08c3bcd2014-12-01 17:55:16 -0800473 SizeT SectHeaderStrIndex,
474 SizeT NumSections) {
Andrew Scull57e12682015-09-16 11:30:19 -0700475 // Write the e_ident: magic number, class, etc. The e_ident is byte order and
476 // ELF class independent.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800477 Str.writeBytes(llvm::StringRef(ElfMagic, strlen(ElfMagic)));
478 Str.write8(IsELF64 ? ELFCLASS64 : ELFCLASS32);
479 Str.write8(ELFDATA2LSB);
480 Str.write8(EV_CURRENT);
481 Str.write8(ELFOSABI_NONE);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700482 constexpr uint8_t ELF_ABIVersion = 0;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800483 Str.write8(ELF_ABIVersion);
484 Str.writeZeroPadding(EI_NIDENT - EI_PAD);
485
Andrew Scull57e12682015-09-16 11:30:19 -0700486 // TODO(jvoung): Handle and test > 64K sections. See the generic ABI doc:
487 // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html e_shnum should
488 // be 0 and then actual number of sections is stored in the sh_size member of
489 // the 0th section.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800490 assert(NumSections < SHN_LORESERVE);
491 assert(SectHeaderStrIndex < SHN_LORESERVE);
492
Karl Schimpfd4699942016-04-02 09:55:31 -0700493 const TargetArch Arch = getFlags().getTargetArch();
Andrew Scull57e12682015-09-16 11:30:19 -0700494 // Write the rest of the file header, which does depend on byte order and ELF
495 // class.
Karl Schimpfd4699942016-04-02 09:55:31 -0700496 Str.writeLE16(ET_REL); // e_type
497 Str.writeLE16(getELFMachine(getFlags().getTargetArch())); // e_machine
498 Str.writeELFWord<IsELF64>(1); // e_version
Andrew Scull57e12682015-09-16 11:30:19 -0700499 // Since this is for a relocatable object, there is no entry point, and no
500 // program headers.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800501 Str.writeAddrOrOffset<IsELF64>(0); // e_entry
502 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff
503 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff
Jan Voung1f47ad02015-03-20 15:01:26 -0700504 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags
Jan Voung08c3bcd2014-12-01 17:55:16 -0800505 Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize
506 static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52,
507 "Elf_Ehdr sizes cannot be derived from sizeof");
508 Str.writeLE16(0); // e_phentsize
509 Str.writeLE16(0); // e_phnum
510 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr)
511 : sizeof(Elf32_Shdr)); // e_shentsize
512 static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40,
513 "Elf_Shdr sizes cannot be derived from sizeof");
514 Str.writeLE16(static_cast<Elf64_Half>(NumSections)); // e_shnum
515 Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx
516}
517
Jan Voung91a3e2c2015-01-09 13:01:42 -0800518template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800519 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voung91a3e2c2015-01-09 13:01:42 -0800520 ConstantList Pool = Ctx.getConstantPool(Ty);
521 if (Pool.empty()) {
522 return;
523 }
524 SizeT Align = typeAlignInBytes(Ty);
525 size_t EntSize = typeWidthInBytes(Ty);
526 char Buf[20];
527 SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf));
Qining Lu253dc8a2015-06-22 10:10:23 -0700528 // Check that we write the full PrimType.
Jan Voung91a3e2c2015-01-09 13:01:42 -0800529 assert(WriteAmt == EntSize);
530 // Assume that writing WriteAmt bytes at a time allows us to avoid aligning
531 // between entries.
532 assert(WriteAmt % Align == 0);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700533 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE;
Jan Voung91a3e2c2015-01-09 13:01:42 -0800534 std::string SecBuffer;
535 llvm::raw_string_ostream SecStrBuf(SecBuffer);
536 SecStrBuf << ".rodata.cst" << WriteAmt;
537 ELFDataSection *Section = createSection<ELFDataSection>(
538 SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt);
Jan Voung72984d82015-01-29 14:42:38 -0800539 RODataSections.push_back(Section);
Jan Voung91a3e2c2015-01-09 13:01:42 -0800540 SizeT OffsetInSection = 0;
Andrew Scull57e12682015-09-16 11:30:19 -0700541 // The symbol table entry doesn't need to know the defined symbol's size
542 // since this is in a section with a fixed Entry Size.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700543 constexpr SizeT SymbolSize = 0;
Jan Voung91a3e2c2015-01-09 13:01:42 -0800544 Section->setFileOffset(alignFileOffset(Align));
545
Qining Lu7cd53512015-06-26 09:36:00 -0700546 // If the -reorder-pooled-constant option is set to true, we should shuffle
547 // the constants before we emit them.
Karl Schimpfd4699942016-04-02 09:55:31 -0700548 if (getFlags().getReorderPooledConstants() && !Pool.empty()) {
Qining Luaee5fa82015-08-20 14:59:03 -0700549 // Use the constant's kind value as the salt for creating random number
550 // generator.
551 Operand::OperandKind K = (*Pool.begin())->getKind();
Karl Schimpfd4699942016-04-02 09:55:31 -0700552 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
Qining Luaee5fa82015-08-20 14:59:03 -0700553 RPE_PooledConstantReordering, K);
554 RandomShuffle(Pool.begin(), Pool.end(),
555 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
556 }
Jan Voung91a3e2c2015-01-09 13:01:42 -0800557 // Write the data.
558 for (Constant *C : Pool) {
Qining Lu253dc8a2015-06-22 10:10:23 -0700559 if (!C->getShouldBePooled())
560 continue;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700561 auto *Const = llvm::cast<ConstType>(C);
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700562 GlobalString SymName = Const->getLabelName();
Jan Voung91a3e2c2015-01-09 13:01:42 -0800563 SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section,
564 OffsetInSection, SymbolSize);
565 StrTab->add(SymName);
566 typename ConstType::PrimType Value = Const->getValue();
567 memcpy(Buf, &Value, WriteAmt);
568 Str.writeBytes(llvm::StringRef(Buf, WriteAmt));
569 OffsetInSection += WriteAmt;
570 }
571 Section->setSize(OffsetInSection);
572}
573
Andrew Scull57e12682015-09-16 11:30:19 -0700574// Instantiate known needed versions of the template, since we are defining the
575// function in the .cpp file instead of the .h file. We may need to instantiate
576// constant pools for integers as well if we do constant-pooling of large
577// integers to remove them from the instruction stream (fewer bytes controlled
578// by an attacker).
Jan Voung91a3e2c2015-01-09 13:01:42 -0800579template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty);
580
581template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty);
582
Qining Lu253dc8a2015-06-22 10:10:23 -0700583template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty);
584
Jan Voung1f47ad02015-03-20 15:01:26 -0700585void ELFObjectWriter::writeAllRelocationSections() {
586 writeRelocationSections(RelTextSections);
587 writeRelocationSections(RelDataSections);
588 writeRelocationSections(RelRODataSections);
Jan Voungec270732015-01-12 17:00:22 -0800589}
590
Andrew Scull86df4e92015-07-30 13:54:44 -0700591void ELFObjectWriter::writeJumpTable(const JumpTableData &JT,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800592 FixupKind RelocationKind, bool IsPIC) {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800593 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Andrew Scull86df4e92015-07-30 13:54:44 -0700594 ELFDataSection *Section;
595 ELFRelocationSection *RelSection;
596 const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType());
597 const Elf64_Xword ShAddralign = PointerSize;
598 const Elf64_Xword ShEntsize = PointerSize;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700599 const std::string SectionName = MangleSectionName(
John Porto03077212016-04-05 06:30:21 -0700600 IsPIC ? ".data.rel.ro" : ".rodata", JT.getSectionName());
Andrew Scull86df4e92015-07-30 13:54:44 -0700601 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC,
602 ShAddralign, ShEntsize);
603 Section->setFileOffset(alignFileOffset(ShAddralign));
604 RODataSections.push_back(Section);
605 RelSection = createRelocationSection(Section);
606 RelRODataSections.push_back(RelSection);
607
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700608 constexpr uint8_t SymbolType = STT_OBJECT;
Andrew Scull86df4e92015-07-30 13:54:44 -0700609 Section->padToAlignment(Str, PointerSize);
Karl Schimpfd4699942016-04-02 09:55:31 -0700610 const bool IsExternal = getFlags().getDisableInternal();
Andrew Scull86df4e92015-07-30 13:54:44 -0700611 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
John Porto03077212016-04-05 06:30:21 -0700612 const auto JumpTableName = JT.getName();
Andrew Scull86df4e92015-07-30 13:54:44 -0700613 SymTab->createDefinedSym(JumpTableName, SymbolType, SymbolBinding, Section,
614 Section->getCurrentSize(), PointerSize);
615 StrTab->add(JumpTableName);
616
617 for (intptr_t TargetOffset : JT.getTargetOffsets()) {
618 AssemblerFixup NewFixup;
619 NewFixup.set_position(Section->getCurrentSize());
620 NewFixup.set_kind(RelocationKind);
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800621 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName()));
Andrew Scull86df4e92015-07-30 13:54:44 -0700622 RelSection->addRelocation(NewFixup);
623 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset);
624 }
625}
626
Jan Voung261cae32015-02-01 10:31:03 -0800627void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800628 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voung261cae32015-02-01 10:31:03 -0800629 for (const Constant *S : UndefSyms) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700630 const auto *Sym = llvm::cast<ConstantRelocatable>(S);
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700631 GlobalString Name = Sym->getName();
632 assert(Name.hasStdString());
Jim Stichnotha67fc442015-03-03 16:13:11 -0800633 bool BadIntrinsic;
634 const Intrinsics::FullIntrinsicInfo *Info =
635 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic);
636 if (Info)
637 continue;
Jim Stichnothdef04822015-09-16 11:27:06 -0700638 // Ignore BadIntrinsic, which is set if the name begins with "llvm." but
639 // doesn't match a known intrinsic. If we want this to turn into an error,
640 // we should catch it early on.
Jan Voung261cae32015-02-01 10:31:03 -0800641 assert(Sym->getOffset() == 0);
Jan Voung261cae32015-02-01 10:31:03 -0800642 SymTab->noteUndefinedSym(Name, NullSection);
643 StrTab->add(Name);
644 }
645}
646
Jan Voung1f47ad02015-03-20 15:01:26 -0700647void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) {
Jan Voungec270732015-01-12 17:00:22 -0800648 for (ELFRelocationSection *RelSec : RelSections) {
649 Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign());
650 RelSec->setFileOffset(Offset);
Jan Voung261cae32015-02-01 10:31:03 -0800651 RelSec->setSize(RelSec->getSectionDataSize());
Jan Voung1f47ad02015-03-20 15:01:26 -0700652 if (ELF64) {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800653 RelSec->writeData<true>(Str, SymTab);
Jan Voungec270732015-01-12 17:00:22 -0800654 } else {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800655 RelSec->writeData<false>(Str, SymTab);
Jan Voungec270732015-01-12 17:00:22 -0800656 }
657 }
658}
659
Jan Voung08c3bcd2014-12-01 17:55:16 -0800660void ELFObjectWriter::writeNonUserSections() {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800661 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
662
Jan Voung08c3bcd2014-12-01 17:55:16 -0800663 // Write out the shstrtab now that all sections are known.
664 ShStrTab->doLayout();
665 ShStrTab->setSize(ShStrTab->getSectionDataSize());
666 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign());
667 ShStrTab->setFileOffset(ShStrTabOffset);
668 Str.writeBytes(ShStrTab->getSectionData());
669
670 SectionList AllSections;
671 assignSectionNumbersInfo(AllSections);
672
673 // Finalize the regular StrTab and fix up references in the SymTab.
674 StrTab->doLayout();
675 StrTab->setSize(StrTab->getSectionDataSize());
676
677 SymTab->updateIndices(StrTab);
678
679 Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign());
680 SymTab->setFileOffset(SymTabOffset);
681 SymTab->setSize(SymTab->getSectionDataSize());
Jan Voung1f47ad02015-03-20 15:01:26 -0700682 SymTab->writeData(Str, ELF64);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800683
684 Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign());
685 StrTab->setFileOffset(StrTabOffset);
686 Str.writeBytes(StrTab->getSectionData());
687
Jan Voung1f47ad02015-03-20 15:01:26 -0700688 writeAllRelocationSections();
Jan Voung08c3bcd2014-12-01 17:55:16 -0800689
690 // Write out the section headers.
Jan Voung1f47ad02015-03-20 15:01:26 -0700691 const size_t ShdrAlign = ELF64 ? 8 : 4;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800692 Elf64_Off ShOffset = alignFileOffset(ShdrAlign);
693 for (const auto S : AllSections) {
Jan Voung1f47ad02015-03-20 15:01:26 -0700694 if (ELF64)
Jan Voung08c3bcd2014-12-01 17:55:16 -0800695 S->writeHeader<true>(Str);
696 else
697 S->writeHeader<false>(Str);
698 }
699
700 // Finally write the updated ELF header w/ the correct number of sections.
701 Str.seek(0);
Jan Voung1f47ad02015-03-20 15:01:26 -0700702 if (ELF64) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800703 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(),
704 AllSections.size());
705 } else {
706 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(),
707 AllSections.size());
708 }
709}
710
711} // end of namespace Ice