blob: 874b36a72db82c8283595d308450a7562df4a919 [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
John Portoaff4ccf2015-06-10 16:35:06 -070016#include "IceAssembler.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)
Jan Voung1f47ad02015-03-20 15:01:26 -070067 : Ctx(Ctx), Str(Out), SectionNumbersAssigned(false),
68 ELF64(isELF64(Ctx.getFlags().getTargetArch())) {
Jan Voung08c3bcd2014-12-01 17:55:16 -080069 // Create the special bookkeeping sections now.
70 const IceString NullSectionName("");
71 NullSection = new (Ctx.allocate<ELFSection>())
72 ELFSection(NullSectionName, SHT_NULL, 0, 0, 0);
73
74 const IceString ShStrTabName(".shstrtab");
75 ShStrTab = new (Ctx.allocate<ELFStringTableSection>())
76 ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0);
77 ShStrTab->add(ShStrTabName);
78
79 const IceString SymTabName(".symtab");
Jan Voung1f47ad02015-03-20 15:01:26 -070080 const Elf64_Xword SymTabAlign = ELF64 ? 8 : 4;
Jan Voung08c3bcd2014-12-01 17:55:16 -080081 const Elf64_Xword SymTabEntSize =
Jan Voung1f47ad02015-03-20 15:01:26 -070082 ELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
Jan Voung08c3bcd2014-12-01 17:55:16 -080083 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);
Jan Voungf644a4b2015-03-19 11:57:52 -070087 SymTab->createNullSymbol(NullSection);
Jan Voung08c3bcd2014-12-01 17:55:16 -080088
89 const IceString StrTabName(".strtab");
90 StrTab =
91 createSection<ELFStringTableSection>(StrTabName, SHT_STRTAB, 0, 1, 0);
92}
93
94template <typename T>
95T *ELFObjectWriter::createSection(const IceString &Name, Elf64_Word ShType,
96 Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
97 Elf64_Xword ShEntsize) {
98 assert(!SectionNumbersAssigned);
99 T *NewSection =
100 new (Ctx.allocate<T>()) T(Name, ShType, ShFlags, ShAddralign, ShEntsize);
101 ShStrTab->add(Name);
102 return NewSection;
103}
104
Jan Voung72984d82015-01-29 14:42:38 -0800105ELFRelocationSection *
Jan Voung1f47ad02015-03-20 15:01:26 -0700106ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) {
Jan Voung72984d82015-01-29 14:42:38 -0800107 // Choice of RELA vs REL is actually separate from elf64 vs elf32,
108 // but in practice we've only had .rela for elf64 (x86-64).
109 // In the future, the two properties may need to be decoupled
110 // and the ShEntSize can vary more.
Jan Voung1f47ad02015-03-20 15:01:26 -0700111 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL;
112 IceString RelPrefix = ELF64 ? ".rela" : ".rel";
Jan Voung72984d82015-01-29 14:42:38 -0800113 IceString RelSectionName = RelPrefix + RelatedSection->getName();
Jan Voung1f47ad02015-03-20 15:01:26 -0700114 const Elf64_Xword ShAlign = ELF64 ? 8 : 4;
115 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel);
Jan Voung72984d82015-01-29 14:42:38 -0800116 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8,
117 "Elf_Rel/Rela sizes cannot be derived from sizeof");
118 const Elf64_Xword ShFlags = 0;
119 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>(
120 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize);
121 RelSection->setRelatedSection(RelatedSection);
122 return RelSection;
123}
124
Jan Voung08c3bcd2014-12-01 17:55:16 -0800125template <typename UserSectionList>
126void ELFObjectWriter::assignRelSectionNumInPairs(SizeT &CurSectionNumber,
127 UserSectionList &UserSections,
128 RelSectionList &RelSections,
129 SectionList &AllSections) {
130 RelSectionList::iterator RelIt = RelSections.begin();
131 RelSectionList::iterator RelE = RelSections.end();
132 for (ELFSection *UserSection : UserSections) {
133 UserSection->setNumber(CurSectionNumber++);
134 UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName()));
135 AllSections.push_back(UserSection);
136 if (RelIt != RelE) {
Jan Voungec270732015-01-12 17:00:22 -0800137 ELFRelocationSection *RelSection = *RelIt;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800138 if (RelSection->getRelatedSection() == UserSection) {
139 RelSection->setInfoNum(UserSection->getNumber());
140 RelSection->setNumber(CurSectionNumber++);
141 RelSection->setNameStrIndex(ShStrTab->getIndex(RelSection->getName()));
142 AllSections.push_back(RelSection);
143 ++RelIt;
144 }
145 }
146 }
147 // Should finish with UserIt at the same time as RelIt.
148 assert(RelIt == RelE);
149 return;
150}
151
152void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber,
153 RelSectionList &RelSections) {
Jan Voungec270732015-01-12 17:00:22 -0800154 for (ELFRelocationSection *S : RelSections) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800155 S->setLinkNum(SymTabNumber);
156 }
157}
158
159void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) {
160 // Go through each section, assigning them section numbers and
161 // and fill in the size for sections that aren't incrementally updated.
162 assert(!SectionNumbersAssigned);
163 SizeT CurSectionNumber = 0;
164 NullSection->setNumber(CurSectionNumber++);
165 // The rest of the fields are initialized to 0, and stay that way.
166 AllSections.push_back(NullSection);
167
168 assignRelSectionNumInPairs<TextSectionList>(CurSectionNumber, TextSections,
169 RelTextSections, AllSections);
170 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, DataSections,
171 RelDataSections, AllSections);
Jan Voung72984d82015-01-29 14:42:38 -0800172 for (ELFSection *BSSSection : BSSSections) {
173 BSSSection->setNumber(CurSectionNumber++);
174 BSSSection->setNameStrIndex(ShStrTab->getIndex(BSSSection->getName()));
175 AllSections.push_back(BSSSection);
176 }
177 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, RODataSections,
178 RelRODataSections, AllSections);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800179
180 ShStrTab->setNumber(CurSectionNumber++);
181 ShStrTab->setNameStrIndex(ShStrTab->getIndex(ShStrTab->getName()));
182 AllSections.push_back(ShStrTab);
183
184 SymTab->setNumber(CurSectionNumber++);
185 SymTab->setNameStrIndex(ShStrTab->getIndex(SymTab->getName()));
186 AllSections.push_back(SymTab);
187
188 StrTab->setNumber(CurSectionNumber++);
189 StrTab->setNameStrIndex(ShStrTab->getIndex(StrTab->getName()));
190 AllSections.push_back(StrTab);
191
192 SymTab->setLinkNum(StrTab->getNumber());
193 SymTab->setInfoNum(SymTab->getNumLocals());
194
195 assignRelLinkNum(SymTab->getNumber(), RelTextSections);
196 assignRelLinkNum(SymTab->getNumber(), RelDataSections);
Jan Voung72984d82015-01-29 14:42:38 -0800197 assignRelLinkNum(SymTab->getNumber(), RelRODataSections);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800198 SectionNumbersAssigned = true;
199}
200
201Elf64_Off ELFObjectWriter::alignFileOffset(Elf64_Xword Align) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800202 Elf64_Off OffsetInFile = Str.tell();
Jan Voung72984d82015-01-29 14:42:38 -0800203 Elf64_Xword AlignDiff = Utils::OffsetToAlignment(OffsetInFile, Align);
204 if (AlignDiff == 0)
Jan Voung08c3bcd2014-12-01 17:55:16 -0800205 return OffsetInFile;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800206 Str.writeZeroPadding(AlignDiff);
207 OffsetInFile += AlignDiff;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800208 return OffsetInFile;
209}
210
211void ELFObjectWriter::writeFunctionCode(const IceString &FuncName,
Jan Voungec270732015-01-12 17:00:22 -0800212 bool IsInternal, const Assembler *Asm) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800213 assert(!SectionNumbersAssigned);
Jan Voungec270732015-01-12 17:00:22 -0800214 ELFTextSection *Section = nullptr;
Jan Voung72984d82015-01-29 14:42:38 -0800215 ELFRelocationSection *RelSection = nullptr;
Jan Voungcb165ca2015-02-24 08:53:52 -0800216 const bool FunctionSections = Ctx.getFlags().getFunctionSections();
217 if (TextSections.empty() || FunctionSections) {
Jan Voung72984d82015-01-29 14:42:38 -0800218 IceString SectionName = ".text";
Jan Voungcb165ca2015-02-24 08:53:52 -0800219 if (FunctionSections)
220 SectionName += "." + FuncName;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800221 const Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR;
Jan Vounge9079cb2015-02-25 09:08:44 -0800222 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes();
Jan Voung08c3bcd2014-12-01 17:55:16 -0800223 Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags,
224 ShAlign, 0);
225 Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign());
226 Section->setFileOffset(OffsetInFile);
227 TextSections.push_back(Section);
Jan Voung1f47ad02015-03-20 15:01:26 -0700228 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800229 RelTextSections.push_back(RelSection);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800230 } else {
231 Section = TextSections[0];
Jan Voung72984d82015-01-29 14:42:38 -0800232 RelSection = RelTextSections[0];
Jan Voung08c3bcd2014-12-01 17:55:16 -0800233 }
234 RelocOffsetT OffsetInSection = Section->getCurrentSize();
235 // Function symbols are set to 0 size in the symbol table,
236 // in contrast to data symbols which have a proper size.
237 SizeT SymbolSize = 0;
Jan Voungec270732015-01-12 17:00:22 -0800238 Section->appendData(Str, Asm->getBufferView());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800239 uint8_t SymbolType;
240 uint8_t SymbolBinding;
Jim Stichnotha67fc442015-03-03 16:13:11 -0800241 if (IsInternal && !Ctx.getFlags().getDisableInternal()) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800242 SymbolType = STT_NOTYPE;
243 SymbolBinding = STB_LOCAL;
244 } else {
245 SymbolType = STT_FUNC;
246 SymbolBinding = STB_GLOBAL;
247 }
248 SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section,
249 OffsetInSection, SymbolSize);
250 StrTab->add(FuncName);
Jan Voungec270732015-01-12 17:00:22 -0800251
Jan Voungcb165ca2015-02-24 08:53:52 -0800252 // Copy the fixup information from per-function Assembler memory to the
253 // object writer's memory, for writing later.
Jan Voungec270732015-01-12 17:00:22 -0800254 if (!Asm->fixups().empty()) {
Jan Voungec270732015-01-12 17:00:22 -0800255 RelSection->addRelocations(OffsetInSection, Asm->fixups());
256 }
Jan Voung08c3bcd2014-12-01 17:55:16 -0800257}
258
Jan Voung72984d82015-01-29 14:42:38 -0800259namespace {
260
261ELFObjectWriter::SectionType
262classifyGlobalSection(const VariableDeclaration *Var) {
263 if (Var->getIsConstant())
264 return ELFObjectWriter::ROData;
265 if (Var->hasNonzeroInitializer())
266 return ELFObjectWriter::Data;
267 return ELFObjectWriter::BSS;
268}
269
270// Partition the Vars list by SectionType into VarsBySection.
271// If TranslateOnly is non-empty, then only the TranslateOnly variable
272// is kept for emission.
273void partitionGlobalsBySection(const VariableDeclarationList &Vars,
274 VariableDeclarationList VarsBySection[],
275 const IceString &TranslateOnly) {
276 for (VariableDeclaration *Var : Vars) {
277 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
278 size_t Section = classifyGlobalSection(Var);
JF Bastienae6e12c2015-01-31 10:13:25 -0800279 assert(Section < ELFObjectWriter::NumSectionTypes);
Jan Voung72984d82015-01-29 14:42:38 -0800280 VarsBySection[Section].push_back(Var);
281 }
282 }
283}
284
285} // end of anonymous namespace
286
287void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
John Porto8b1a7052015-06-17 13:20:08 -0700288 FixupKind RelocationKind,
289 const IceString &SectionSuffix) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800290 assert(!SectionNumbersAssigned);
Jan Voung72984d82015-01-29 14:42:38 -0800291 VariableDeclarationList VarsBySection[ELFObjectWriter::NumSectionTypes];
292 for (auto &SectionList : VarsBySection)
293 SectionList.reserve(Vars.size());
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800294 partitionGlobalsBySection(Vars, VarsBySection,
295 Ctx.getFlags().getTranslateOnly());
Jan Voung72984d82015-01-29 14:42:38 -0800296 size_t I = 0;
297 for (auto &SectionList : VarsBySection) {
John Porto8b1a7052015-06-17 13:20:08 -0700298 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind,
299 SectionSuffix);
Jan Voung72984d82015-01-29 14:42:38 -0800300 }
301}
302
John Porto8b1a7052015-06-17 13:20:08 -0700303namespace {
304IceString MangleSectionName(const char Base[], const IceString &Suffix) {
305 if (Suffix.empty())
306 return Base;
307 return Base + ("." + Suffix);
308}
309} // end of anonymous namespace
310
311// TODO(jvoung): Handle fdata-sections.
JF Bastienae6e12c2015-01-31 10:13:25 -0800312void ELFObjectWriter::writeDataOfType(SectionType ST,
Jan Voung72984d82015-01-29 14:42:38 -0800313 const VariableDeclarationList &Vars,
John Porto8b1a7052015-06-17 13:20:08 -0700314 FixupKind RelocationKind,
315 const IceString &SectionSuffix) {
Jan Voung77973cc2015-02-03 12:48:38 -0800316 if (Vars.empty())
317 return;
Jan Voung72984d82015-01-29 14:42:38 -0800318 ELFDataSection *Section;
319 ELFRelocationSection *RelSection;
Jan Voung72984d82015-01-29 14:42:38 -0800320 IceString SectionName;
Jan Voung77973cc2015-02-03 12:48:38 -0800321 Elf64_Xword ShAddralign = 1;
Jan Voung72984d82015-01-29 14:42:38 -0800322 for (VariableDeclaration *Var : Vars) {
323 Elf64_Xword Align = Var->getAlignment();
324 ShAddralign = std::max(ShAddralign, Align);
325 }
326 const Elf64_Xword ShEntsize = 0; // non-uniform data element size.
327 // Lift this out, so it can be re-used if we do fdata-sections?
JF Bastienae6e12c2015-01-31 10:13:25 -0800328 switch (ST) {
329 case ROData: {
John Porto8b1a7052015-06-17 13:20:08 -0700330 const IceString SectionName = MangleSectionName(".rodata", SectionSuffix);
Jan Voung72984d82015-01-29 14:42:38 -0800331 const Elf64_Xword ShFlags = SHF_ALLOC;
332 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
333 ShAddralign, ShEntsize);
334 Section->setFileOffset(alignFileOffset(ShAddralign));
335 RODataSections.push_back(Section);
Jan Voung1f47ad02015-03-20 15:01:26 -0700336 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800337 RelRODataSections.push_back(RelSection);
338 break;
339 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800340 case Data: {
John Porto8b1a7052015-06-17 13:20:08 -0700341 const IceString SectionName = MangleSectionName(".data", SectionSuffix);
Jan Voung72984d82015-01-29 14:42:38 -0800342 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);
Jan Voung1f47ad02015-03-20 15:01:26 -0700347 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800348 RelDataSections.push_back(RelSection);
349 break;
350 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800351 case BSS: {
John Porto8b1a7052015-06-17 13:20:08 -0700352 const IceString SectionName = MangleSectionName(".bss", SectionSuffix);
Jan Voung72984d82015-01-29 14:42:38 -0800353 const Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
354 Section = createSection<ELFDataSection>(SectionName, SHT_NOBITS, ShFlags,
355 ShAddralign, ShEntsize);
356 Section->setFileOffset(alignFileOffset(ShAddralign));
357 BSSSections.push_back(Section);
358 break;
359 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800360 case NumSectionTypes:
Jan Voung72984d82015-01-29 14:42:38 -0800361 llvm::report_fatal_error("Unknown SectionType");
362 break;
363 }
364
365 const uint8_t SymbolType = STT_OBJECT;
366 for (VariableDeclaration *Var : Vars) {
Jan Voung77973cc2015-02-03 12:48:38 -0800367 // If the variable declaration does not have an initializer, its symtab
368 // entry will be created separately.
369 if (!Var->hasInitializer())
370 continue;
Jan Voung72984d82015-01-29 14:42:38 -0800371 Elf64_Xword Align = Var->getAlignment();
Jim Stichnoth729dbd02015-02-25 14:48:43 -0800372 const Elf64_Xword MinAlign = 1;
373 Align = std::max(Align, MinAlign);
Jan Voung72984d82015-01-29 14:42:38 -0800374 Section->padToAlignment(Str, Align);
375 SizeT SymbolSize = Var->getNumBytes();
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800376 bool IsExternal = Var->isExternal() || Ctx.getFlags().getDisableInternal();
Jan Voung72984d82015-01-29 14:42:38 -0800377 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
378 IceString MangledName = Var->mangleName(&Ctx);
379 SymTab->createDefinedSym(MangledName, SymbolType, SymbolBinding, Section,
380 Section->getCurrentSize(), SymbolSize);
381 StrTab->add(MangledName);
382 if (!Var->hasNonzeroInitializer()) {
JF Bastienae6e12c2015-01-31 10:13:25 -0800383 assert(ST == BSS || ST == ROData);
384 if (ST == ROData)
Jan Voung72984d82015-01-29 14:42:38 -0800385 Section->appendZeros(Str, SymbolSize);
386 else
387 Section->setSize(Section->getCurrentSize() + SymbolSize);
388 } else {
JF Bastienae6e12c2015-01-31 10:13:25 -0800389 assert(ST != BSS);
Jan Voung72984d82015-01-29 14:42:38 -0800390 for (VariableDeclaration::Initializer *Init : Var->getInitializers()) {
391 switch (Init->getKind()) {
392 case VariableDeclaration::Initializer::DataInitializerKind: {
Jim Stichnothcac003e2015-06-18 12:48:58 -0700393 const auto Data =
394 llvm::cast<VariableDeclaration::DataInitializer>(Init)
395 ->getContents();
Jan Voung72984d82015-01-29 14:42:38 -0800396 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;
Jan Voung1f47ad02015-03-20 15:01:26 -0700428 if (ELF64) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800429 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
Jan Voung1f47ad02015-03-20 15:01:26 -0700459 const TargetArch Arch = Ctx.getFlags().getTargetArch();
Jan Voung08c3bcd2014-12-01 17:55:16 -0800460 // Write the rest of the file header, which does depend on byte order
461 // and ELF class.
Jan Voung1f47ad02015-03-20 15:01:26 -0700462 Str.writeLE16(ET_REL); // e_type
463 Str.writeLE16(getELFMachine(Ctx.getFlags().getTargetArch())); // e_machine
464 Str.writeELFWord<IsELF64>(1); // e_version
Jan Voung08c3bcd2014-12-01 17:55:16 -0800465 // Since this is for a relocatable object, there is no entry point,
466 // and no program headers.
467 Str.writeAddrOrOffset<IsELF64>(0); // e_entry
468 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff
469 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff
Jan Voung1f47ad02015-03-20 15:01:26 -0700470 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags
Jan Voung08c3bcd2014-12-01 17:55:16 -0800471 Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize
472 static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52,
473 "Elf_Ehdr sizes cannot be derived from sizeof");
474 Str.writeLE16(0); // e_phentsize
475 Str.writeLE16(0); // e_phnum
476 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr)
477 : sizeof(Elf32_Shdr)); // e_shentsize
478 static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40,
479 "Elf_Shdr sizes cannot be derived from sizeof");
480 Str.writeLE16(static_cast<Elf64_Half>(NumSections)); // e_shnum
481 Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx
482}
483
Jan Voung91a3e2c2015-01-09 13:01:42 -0800484template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
485 ConstantList Pool = Ctx.getConstantPool(Ty);
486 if (Pool.empty()) {
487 return;
488 }
489 SizeT Align = typeAlignInBytes(Ty);
490 size_t EntSize = typeWidthInBytes(Ty);
491 char Buf[20];
492 SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf));
Qining Lu253dc8a2015-06-22 10:10:23 -0700493 // Check that we write the full PrimType.
Jan Voung91a3e2c2015-01-09 13:01:42 -0800494 assert(WriteAmt == EntSize);
495 // Assume that writing WriteAmt bytes at a time allows us to avoid aligning
496 // between entries.
497 assert(WriteAmt % Align == 0);
Jan Voung91a3e2c2015-01-09 13:01:42 -0800498 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) {
Qining Lu253dc8a2015-06-22 10:10:23 -0700513 if (!C->getShouldBePooled())
514 continue;
Jan Voung91a3e2c2015-01-09 13:01:42 -0800515 auto Const = llvm::cast<ConstType>(C);
516 std::string SymBuffer;
517 llvm::raw_string_ostream SymStrBuf(SymBuffer);
Jan Voung1d62cf02015-01-09 14:57:32 -0800518 Const->emitPoolLabel(SymStrBuf);
Jan Voung91a3e2c2015-01-09 13:01:42 -0800519 std::string &SymName = SymStrBuf.str();
520 SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section,
521 OffsetInSection, SymbolSize);
522 StrTab->add(SymName);
523 typename ConstType::PrimType Value = Const->getValue();
524 memcpy(Buf, &Value, WriteAmt);
525 Str.writeBytes(llvm::StringRef(Buf, WriteAmt));
526 OffsetInSection += WriteAmt;
527 }
528 Section->setSize(OffsetInSection);
529}
530
531// Instantiate known needed versions of the template, since we are
532// defining the function in the .cpp file instead of the .h file.
533// We may need to instantiate constant pools for integers as well
534// if we do constant-pooling of large integers to remove them
535// from the instruction stream (fewer bytes controlled by an attacker).
536template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty);
537
538template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty);
539
Qining Lu253dc8a2015-06-22 10:10:23 -0700540template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty);
541
Jan Voung1f47ad02015-03-20 15:01:26 -0700542void ELFObjectWriter::writeAllRelocationSections() {
543 writeRelocationSections(RelTextSections);
544 writeRelocationSections(RelDataSections);
545 writeRelocationSections(RelRODataSections);
Jan Voungec270732015-01-12 17:00:22 -0800546}
547
Jan Voung261cae32015-02-01 10:31:03 -0800548void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) {
549 for (const Constant *S : UndefSyms) {
550 const auto Sym = llvm::cast<ConstantRelocatable>(S);
Jan Voungc9ec5792015-02-05 17:31:28 -0800551 const IceString &Name = Sym->getName();
Jim Stichnotha67fc442015-03-03 16:13:11 -0800552 bool BadIntrinsic;
553 const Intrinsics::FullIntrinsicInfo *Info =
554 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic);
555 if (Info)
556 continue;
557 assert(!BadIntrinsic);
Jan Voung261cae32015-02-01 10:31:03 -0800558 assert(Sym->getOffset() == 0);
559 assert(Sym->getSuppressMangling());
560 SymTab->noteUndefinedSym(Name, NullSection);
561 StrTab->add(Name);
562 }
563}
564
Jan Voung1f47ad02015-03-20 15:01:26 -0700565void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) {
Jan Voungec270732015-01-12 17:00:22 -0800566 for (ELFRelocationSection *RelSec : RelSections) {
567 Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign());
568 RelSec->setFileOffset(Offset);
Jan Voung261cae32015-02-01 10:31:03 -0800569 RelSec->setSize(RelSec->getSectionDataSize());
Jan Voung1f47ad02015-03-20 15:01:26 -0700570 if (ELF64) {
Jan Voungec270732015-01-12 17:00:22 -0800571 RelSec->writeData<true>(Ctx, Str, SymTab);
572 } else {
573 RelSec->writeData<false>(Ctx, Str, SymTab);
574 }
575 }
576}
577
Jan Voung08c3bcd2014-12-01 17:55:16 -0800578void ELFObjectWriter::writeNonUserSections() {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800579 // Write out the shstrtab now that all sections are known.
580 ShStrTab->doLayout();
581 ShStrTab->setSize(ShStrTab->getSectionDataSize());
582 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign());
583 ShStrTab->setFileOffset(ShStrTabOffset);
584 Str.writeBytes(ShStrTab->getSectionData());
585
586 SectionList AllSections;
587 assignSectionNumbersInfo(AllSections);
588
589 // Finalize the regular StrTab and fix up references in the SymTab.
590 StrTab->doLayout();
591 StrTab->setSize(StrTab->getSectionDataSize());
592
593 SymTab->updateIndices(StrTab);
594
595 Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign());
596 SymTab->setFileOffset(SymTabOffset);
597 SymTab->setSize(SymTab->getSectionDataSize());
Jan Voung1f47ad02015-03-20 15:01:26 -0700598 SymTab->writeData(Str, ELF64);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800599
600 Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign());
601 StrTab->setFileOffset(StrTabOffset);
602 Str.writeBytes(StrTab->getSectionData());
603
Jan Voung1f47ad02015-03-20 15:01:26 -0700604 writeAllRelocationSections();
Jan Voung08c3bcd2014-12-01 17:55:16 -0800605
606 // Write out the section headers.
Jan Voung1f47ad02015-03-20 15:01:26 -0700607 const size_t ShdrAlign = ELF64 ? 8 : 4;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800608 Elf64_Off ShOffset = alignFileOffset(ShdrAlign);
609 for (const auto S : AllSections) {
Jan Voung1f47ad02015-03-20 15:01:26 -0700610 if (ELF64)
Jan Voung08c3bcd2014-12-01 17:55:16 -0800611 S->writeHeader<true>(Str);
612 else
613 S->writeHeader<false>(Str);
614 }
615
616 // Finally write the updated ELF header w/ the correct number of sections.
617 Str.seek(0);
Jan Voung1f47ad02015-03-20 15:01:26 -0700618 if (ELF64) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800619 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(),
620 AllSections.size());
621 } else {
622 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(),
623 AllSections.size());
624 }
625}
626
627} // end of namespace Ice