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 ,
41 TARGETARCH_TABLE
42 #undef X
43 };
44
isELF64(const ClFlags & Flags)45 bool 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
52 if (Flags.getApplicationBinaryInterface() == ABI_PNaCl &&
53 !Flags.getUseSandboxing()) {
54 // Unsandboxed PNaCl code is always ELF32 (pexes are ILP32.)
55 return false;
56 }
57
58 return ELFTargetInfo[Arch].IsELF64;
59 }
60
getELFMachine(TargetArch Arch)61 uint16_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
getELFFlags(TargetArch Arch)68 uint32_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
ELFObjectWriter(GlobalContext & Ctx,ELFStreamer & Out)77 ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out)
78 : Ctx(Ctx), Str(Out), ELF64(isELF64(getFlags())) {
79 // Create the special bookkeeping sections now.
80 constexpr char NullSectionName[] = "";
81 NullSection = new (Ctx.allocate<ELFSection>())
82 ELFSection(NullSectionName, SHT_NULL, 0, 0, 0);
83
84 constexpr char ShStrTabName[] = ".shstrtab";
85 ShStrTab = new (Ctx.allocate<ELFStringTableSection>())
86 ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0);
87 ShStrTab->add(ShStrTabName);
88
89 constexpr char SymTabName[] = ".symtab";
90 const Elf64_Xword SymTabAlign = ELF64 ? 8 : 4;
91 const Elf64_Xword SymTabEntSize =
92 ELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
93 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);
97 SymTab->createNullSymbol(NullSection, &Ctx);
98
99 constexpr char StrTabName[] = ".strtab";
100 StrTab =
101 createSection<ELFStringTableSection>(StrTabName, SHT_STRTAB, 0, 1, 0);
102 }
103
104 template <typename T>
createSection(const std::string & Name,Elf64_Word ShType,Elf64_Xword ShFlags,Elf64_Xword ShAddralign,Elf64_Xword ShEntsize)105 T *ELFObjectWriter::createSection(const std::string &Name, Elf64_Word ShType,
106 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
115 ELFRelocationSection *
createRelocationSection(const ELFSection * RelatedSection)116 ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) {
117 // 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.
120 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL;
121 const std::string RelPrefix = ELF64 ? ".rela" : ".rel";
122 const std::string RelSectionName = RelPrefix + RelatedSection->getName();
123 const Elf64_Xword ShAlign = ELF64 ? 8 : 4;
124 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel);
125 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8,
126 "Elf_Rel/Rela sizes cannot be derived from sizeof");
127 constexpr Elf64_Xword ShFlags = 0;
128 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>(
129 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize);
130 RelSection->setRelatedSection(RelatedSection);
131 return RelSection;
132 }
133
134 template <typename UserSectionList>
assignRelSectionNumInPairs(SizeT & CurSectionNumber,UserSectionList & UserSections,RelSectionList & RelSections,SectionList & AllSections)135 void 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) {
146 ELFRelocationSection *RelSection = *RelIt;
147 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
assignRelLinkNum(SizeT SymTabNumber,RelSectionList & RelSections)161 void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber,
162 RelSectionList &RelSections) {
163 for (ELFRelocationSection *S : RelSections) {
164 S->setLinkNum(SymTabNumber);
165 }
166 }
167
assignSectionNumbersInfo(SectionList & AllSections)168 void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) {
169 // Go through each section, assigning them section numbers and and fill in
170 // the size for sections that aren't incrementally updated.
171 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);
181 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);
188
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);
206 assignRelLinkNum(SymTab->getNumber(), RelRODataSections);
207 SectionNumbersAssigned = true;
208 }
209
alignFileOffset(Elf64_Xword Align)210 Elf64_Off ELFObjectWriter::alignFileOffset(Elf64_Xword Align) {
211 Elf64_Off OffsetInFile = Str.tell();
212 Elf64_Xword AlignDiff = Utils::OffsetToAlignment(OffsetInFile, Align);
213 if (AlignDiff == 0)
214 return OffsetInFile;
215 Str.writeZeroPadding(AlignDiff);
216 OffsetInFile += AlignDiff;
217 return OffsetInFile;
218 }
219
writeFunctionCode(GlobalString FuncName,bool IsInternal,Assembler * Asm)220 void ELFObjectWriter::writeFunctionCode(GlobalString FuncName, bool IsInternal,
221 Assembler *Asm) {
222 assert(!SectionNumbersAssigned);
223 TimerMarker T_func(&Ctx, FuncName.toStringOrEmpty());
224 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
225 ELFTextSection *Section = nullptr;
226 ELFRelocationSection *RelSection = nullptr;
227 const bool FunctionSections = getFlags().getFunctionSections();
228 if (TextSections.empty() || FunctionSections) {
229 std::string SectionName = ".text";
230 if (FunctionSections)
231 SectionName += "." + FuncName;
232 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR;
233 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes();
234 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);
239 RelSection = createRelocationSection(Section);
240 RelTextSections.push_back(RelSection);
241 } else {
242 Section = TextSections[0];
243 RelSection = RelTextSections[0];
244 }
245 const RelocOffsetT OffsetInSection = Section->getCurrentSize();
246 // Function symbols are set to 0 size in the symbol table, in contrast to
247 // data symbols which have a proper size.
248 constexpr SizeT SymbolSize = 0;
249 uint8_t SymbolType;
250 uint8_t SymbolBinding;
251 if (IsInternal && !getFlags().getDisableInternal()) {
252 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);
261
262 // Copy the fixup information from per-function Assembler memory to the
263 // object writer's memory, for writing later.
264 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 }
273 RelSection->addRelocations(OffsetInSection, Asm->fixups(), SymTab);
274 }
275 Section->appendData(Str, Asm->getBufferView());
276 }
277
278 namespace {
279
280 ELFObjectWriter::SectionType
classifyGlobalSection(const VariableDeclaration * Var)281 classifyGlobalSection(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
289 // Partition the Vars list by SectionType into VarsBySection. If TranslateOnly
290 // is non-empty, then only the TranslateOnly variable is kept for emission.
partitionGlobalsBySection(const VariableDeclarationList & Vars,VariableDeclarationPartition VarsBySection[])291 void partitionGlobalsBySection(const VariableDeclarationList &Vars,
292 VariableDeclarationPartition VarsBySection[]) {
293 for (VariableDeclaration *Var : Vars) {
294 if (getFlags().matchTranslateOnly(Var->getName(), 0)) {
295 size_t Section = classifyGlobalSection(Var);
296 assert(Section < ELFObjectWriter::NumSectionTypes);
297 VarsBySection[Section].push_back(Var);
298 }
299 }
300 }
301
302 } // end of anonymous namespace
303
writeTargetRODataSection(const std::string & Name,Elf64_Word ShType,Elf64_Xword ShFlags,Elf64_Xword ShAddralign,Elf64_Xword ShEntsize,const llvm::StringRef & SecData)304 void 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
writeDataSection(const VariableDeclarationList & Vars,FixupKind RelocationKind,const std::string & SectionSuffix,bool IsPIC)319 void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
320 FixupKind RelocationKind,
321 const std::string &SectionSuffix,
322 bool IsPIC) {
323 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
324 assert(!SectionNumbersAssigned);
325 VariableDeclarationPartition VarsBySection[ELFObjectWriter::NumSectionTypes];
326 for (auto &SectionList : VarsBySection)
327 SectionList.reserve(Vars.size());
328 partitionGlobalsBySection(Vars, VarsBySection);
329 size_t I = 0;
330 for (auto &SectionList : VarsBySection) {
331 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind,
332 SectionSuffix, IsPIC);
333 }
334 }
335
336 namespace {
MangleSectionName(const char Base[],const std::string & Suffix)337 std::string MangleSectionName(const char Base[], const std::string &Suffix) {
338 if (Suffix.empty())
339 return Base;
340 return Base + ("." + Suffix);
341 }
342 } // end of anonymous namespace
343
344 // TODO(jvoung): Handle fdata-sections.
writeDataOfType(SectionType ST,const VariableDeclarationPartition & Vars,FixupKind RelocationKind,const std::string & SectionSuffix,bool IsPIC)345 void ELFObjectWriter::writeDataOfType(SectionType ST,
346 const VariableDeclarationPartition &Vars,
347 FixupKind RelocationKind,
348 const std::string &SectionSuffix,
349 bool IsPIC) {
350 if (Vars.empty())
351 return;
352 ELFDataSection *Section;
353 ELFRelocationSection *RelSection;
354 Elf64_Xword ShAddralign = 1;
355 for (VariableDeclaration *Var : Vars) {
356 Elf64_Xword Align = Var->getAlignment();
357 ShAddralign = std::max(ShAddralign, Align);
358 }
359 constexpr Elf64_Xword ShEntsize = 0; // non-uniform data element size.
360 // Lift this out, so it can be re-used if we do fdata-sections?
361 switch (ST) {
362 case ROData: {
363 const std::string SectionName =
364 MangleSectionName(IsPIC ? ".data.rel.ro" : ".rodata", SectionSuffix);
365 const Elf64_Xword ShFlags = IsPIC ? (SHF_ALLOC | SHF_WRITE) : SHF_ALLOC;
366 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
367 ShAddralign, ShEntsize);
368 Section->setFileOffset(alignFileOffset(ShAddralign));
369 RODataSections.push_back(Section);
370 RelSection = createRelocationSection(Section);
371 RelRODataSections.push_back(RelSection);
372 break;
373 }
374 case Data: {
375 const std::string SectionName = MangleSectionName(".data", SectionSuffix);
376 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
377 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
378 ShAddralign, ShEntsize);
379 Section->setFileOffset(alignFileOffset(ShAddralign));
380 DataSections.push_back(Section);
381 RelSection = createRelocationSection(Section);
382 RelDataSections.push_back(RelSection);
383 break;
384 }
385 case BSS: {
386 const std::string SectionName = MangleSectionName(".bss", SectionSuffix);
387 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
388 Section = createSection<ELFDataSection>(SectionName, SHT_NOBITS, ShFlags,
389 ShAddralign, ShEntsize);
390 Section->setFileOffset(alignFileOffset(ShAddralign));
391 BSSSections.push_back(Section);
392 break;
393 }
394 case NumSectionTypes:
395 llvm::report_fatal_error("Unknown SectionType");
396 break;
397 }
398
399 constexpr uint8_t SymbolType = STT_OBJECT;
400 for (VariableDeclaration *Var : Vars) {
401 // If the variable declaration does not have an initializer, its symtab
402 // entry will be created separately.
403 if (!Var->hasInitializer())
404 continue;
405 constexpr Elf64_Xword MinAlign = 1;
406 const auto Align = std::max<Elf64_Xword>(MinAlign, Var->getAlignment());
407 Section->padToAlignment(Str, Align);
408 SizeT SymbolSize = Var->getNumBytes();
409 bool IsExternal = Var->isExternal() || getFlags().getDisableInternal();
410 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
411 GlobalString Name = Var->getName();
412 SymTab->createDefinedSym(Name, SymbolType, SymbolBinding, Section,
413 Section->getCurrentSize(), SymbolSize);
414 StrTab->add(Name);
415 if (!Var->hasNonzeroInitializer()) {
416 assert(ST == BSS || ST == ROData);
417 if (ST == ROData)
418 Section->appendZeros(Str, SymbolSize);
419 else
420 Section->setSize(Section->getCurrentSize() + SymbolSize);
421 } else {
422 assert(ST != BSS);
423 for (const auto *Init : Var->getInitializers()) {
424 switch (Init->getKind()) {
425 case VariableDeclaration::Initializer::DataInitializerKind: {
426 const auto &Data =
427 llvm::cast<VariableDeclaration::DataInitializer>(Init)
428 ->getContents();
429 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: {
436 const auto *Reloc =
437 llvm::cast<VariableDeclaration::RelocInitializer>(Init);
438 AssemblerFixup NewFixup;
439 NewFixup.set_position(Section->getCurrentSize());
440 NewFixup.set_kind(Reloc->hasFixup() ? Reloc->getFixup()
441 : RelocationKind);
442 assert(NewFixup.kind() != llvm::ELF::R_ARM_NONE);
443 NewFixup.set_value(Ctx.getConstantSym(
444 Reloc->getOffset(), Reloc->getDeclaration()->getName()));
445 RelSection->addRelocation(NewFixup);
446 Section->appendRelocationOffset(Str, RelSection->isRela(),
447 Reloc->getOffset());
448 break;
449 }
450 }
451 }
452 }
453 }
454 }
455
writeInitialELFHeader()456 void ELFObjectWriter::writeInitialELFHeader() {
457 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
458 assert(!SectionNumbersAssigned);
459 constexpr Elf64_Off DummySHOffset = 0;
460 constexpr SizeT DummySHStrIndex = 0;
461 constexpr SizeT DummyNumSections = 0;
462 if (ELF64) {
463 writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex,
464 DummyNumSections);
465 } else {
466 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex,
467 DummyNumSections);
468 }
469 }
470
471 template <bool IsELF64>
writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,SizeT SectHeaderStrIndex,SizeT NumSections)472 void ELFObjectWriter::writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,
473 SizeT SectHeaderStrIndex,
474 SizeT NumSections) {
475 // Write the e_ident: magic number, class, etc. The e_ident is byte order and
476 // ELF class independent.
477 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);
482 constexpr uint8_t ELF_ABIVersion = 0;
483 Str.write8(ELF_ABIVersion);
484 Str.writeZeroPadding(EI_NIDENT - EI_PAD);
485
486 // 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.
490 assert(NumSections < SHN_LORESERVE);
491 assert(SectHeaderStrIndex < SHN_LORESERVE);
492
493 const TargetArch Arch = getFlags().getTargetArch();
494 // Write the rest of the file header, which does depend on byte order and ELF
495 // class.
496 Str.writeLE16(ET_REL); // e_type
497 Str.writeLE16(getELFMachine(getFlags().getTargetArch())); // e_machine
498 Str.writeELFWord<IsELF64>(1); // e_version
499 // Since this is for a relocatable object, there is no entry point, and no
500 // program headers.
501 Str.writeAddrOrOffset<IsELF64>(0); // e_entry
502 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff
503 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff
504 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags
505 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
writeConstantPool(Type Ty)518 template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
519 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
520 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));
528 // Check that we write the full PrimType.
529 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);
533 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE;
534 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);
539 RODataSections.push_back(Section);
540 SizeT OffsetInSection = 0;
541 // 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.
543 constexpr SizeT SymbolSize = 0;
544 Section->setFileOffset(alignFileOffset(Align));
545
546 // If the -reorder-pooled-constant option is set to true, we should shuffle
547 // the constants before we emit them.
548 if (getFlags().getReorderPooledConstants() && !Pool.empty()) {
549 // Use the constant's kind value as the salt for creating random number
550 // generator.
551 Operand::OperandKind K = (*Pool.begin())->getKind();
552 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
553 RPE_PooledConstantReordering, K);
554 RandomShuffle(Pool.begin(), Pool.end(),
555 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
556 }
557 // Write the data.
558 for (Constant *C : Pool) {
559 if (!C->getShouldBePooled())
560 continue;
561 auto *Const = llvm::cast<ConstType>(C);
562 GlobalString SymName = Const->getLabelName();
563 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
574 // 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).
579 template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty);
580
581 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty);
582
583 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty);
584
writeAllRelocationSections()585 void ELFObjectWriter::writeAllRelocationSections() {
586 writeRelocationSections(RelTextSections);
587 writeRelocationSections(RelDataSections);
588 writeRelocationSections(RelRODataSections);
589 }
590
writeJumpTable(const JumpTableData & JT,FixupKind RelocationKind,bool IsPIC)591 void ELFObjectWriter::writeJumpTable(const JumpTableData &JT,
592 FixupKind RelocationKind, bool IsPIC) {
593 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
594 ELFDataSection *Section;
595 ELFRelocationSection *RelSection;
596 const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType());
597 const Elf64_Xword ShAddralign = PointerSize;
598 const Elf64_Xword ShEntsize = PointerSize;
599 const std::string SectionName = MangleSectionName(
600 IsPIC ? ".data.rel.ro" : ".rodata", JT.getSectionName());
601 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
608 constexpr uint8_t SymbolType = STT_OBJECT;
609 Section->padToAlignment(Str, PointerSize);
610 const bool IsExternal = getFlags().getDisableInternal();
611 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
612 const auto JumpTableName = JT.getName();
613 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);
621 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName()));
622 RelSection->addRelocation(NewFixup);
623 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset);
624 }
625 }
626
setUndefinedSyms(const ConstantList & UndefSyms)627 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) {
628 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
629 for (const Constant *S : UndefSyms) {
630 const auto *Sym = llvm::cast<ConstantRelocatable>(S);
631 GlobalString Name = Sym->getName();
632 assert(Name.hasStdString());
633 bool BadIntrinsic;
634 const Intrinsics::FullIntrinsicInfo *Info =
635 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic);
636 if (Info)
637 continue;
638 // 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.
641 assert(Sym->getOffset() == 0);
642 SymTab->noteUndefinedSym(Name, NullSection);
643 StrTab->add(Name);
644 }
645 }
646
writeRelocationSections(RelSectionList & RelSections)647 void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) {
648 for (ELFRelocationSection *RelSec : RelSections) {
649 Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign());
650 RelSec->setFileOffset(Offset);
651 RelSec->setSize(RelSec->getSectionDataSize());
652 if (ELF64) {
653 RelSec->writeData<true>(Str, SymTab);
654 } else {
655 RelSec->writeData<false>(Str, SymTab);
656 }
657 }
658 }
659
writeNonUserSections()660 void ELFObjectWriter::writeNonUserSections() {
661 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
662
663 // 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());
682 SymTab->writeData(Str, ELF64);
683
684 Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign());
685 StrTab->setFileOffset(StrTabOffset);
686 Str.writeBytes(StrTab->getSectionData());
687
688 writeAllRelocationSections();
689
690 // Write out the section headers.
691 const size_t ShdrAlign = ELF64 ? 8 : 4;
692 Elf64_Off ShOffset = alignFileOffset(ShdrAlign);
693 for (const auto S : AllSections) {
694 if (ELF64)
695 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);
702 if (ELF64) {
703 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
712