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