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