blob: 1643397c0f9ef3f0f3823b3adef581c11f90586d [file] [log] [blame]
Jan Voung08c3bcd2014-12-01 17:55:16 -08001//===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Defines the writer for ELF relocatable object files.
Andrew Scull9612d322015-07-06 14:53:25 -070012///
Jan Voung08c3bcd2014-12-01 17:55:16 -080013//===----------------------------------------------------------------------===//
14
John Porto67f8de92015-06-25 10:14:17 -070015#include "IceELFObjectWriter.h"
Jan Voung72984d82015-01-29 14:42:38 -080016
John Portoaff4ccf2015-06-10 16:35:06 -070017#include "IceAssembler.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080018#include "IceDefs.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080019#include "IceELFSection.h"
20#include "IceELFStreamer.h"
21#include "IceGlobalContext.h"
22#include "IceGlobalInits.h"
Andrew Scull86df4e92015-07-30 13:54:44 -070023#include "IceInst.h"
Jan Voung91a3e2c2015-01-09 13:01:42 -080024#include "IceOperand.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080025
John Portodc619252016-02-10 15:57:16 -080026#include "llvm/Support/ELF.h"
27#include "llvm/Support/MathExtras.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080028
29namespace Ice {
30
31namespace {
32
John Porto56958cb2016-01-14 09:18:18 -080033constexpr struct {
Jan Voung08c3bcd2014-12-01 17:55:16 -080034 bool IsELF64;
35 uint16_t ELFMachine;
36 uint32_t ELFFlags;
John Porto56958cb2016-01-14 09:18:18 -080037} ELFTargetInfo[TargetArch_NUM] = {
Jan Voung08c3bcd2014-12-01 17:55:16 -080038#define X(tag, str, is_elf64, e_machine, e_flags) \
Antonio Maioranodebdfa22020-11-10 16:28:34 -050039 {is_elf64, e_machine, e_flags},
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080040 TARGETARCH_TABLE
Jan Voung08c3bcd2014-12-01 17:55:16 -080041#undef X
42};
43
John Porto56958cb2016-01-14 09:18:18 -080044bool 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
John Porto56958cb2016-01-14 09:18:18 -080051 return ELFTargetInfo[Arch].IsELF64;
Jan Voung08c3bcd2014-12-01 17:55:16 -080052}
53
54uint16_t getELFMachine(TargetArch Arch) {
55 if (Arch < TargetArch_NUM)
56 return ELFTargetInfo[Arch].ELFMachine;
57 llvm_unreachable("Invalid target arch for getELFMachine");
58 return EM_NONE;
59}
60
61uint32_t getELFFlags(TargetArch Arch) {
62 if (Arch < TargetArch_NUM)
63 return ELFTargetInfo[Arch].ELFFlags;
64 llvm_unreachable("Invalid target arch for getELFFlags");
65 return 0;
66}
67
68} // end of anonymous namespace
69
70ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out)
Karl Schimpfd4699942016-04-02 09:55:31 -070071 : Ctx(Ctx), Str(Out), ELF64(isELF64(getFlags())) {
Jan Voung08c3bcd2014-12-01 17:55:16 -080072 // Create the special bookkeeping sections now.
Jim Stichnoth467ffe52016-03-29 15:01:06 -070073 constexpr char NullSectionName[] = "";
Jan Voung08c3bcd2014-12-01 17:55:16 -080074 NullSection = new (Ctx.allocate<ELFSection>())
75 ELFSection(NullSectionName, SHT_NULL, 0, 0, 0);
76
Jim Stichnoth467ffe52016-03-29 15:01:06 -070077 constexpr char ShStrTabName[] = ".shstrtab";
Jan Voung08c3bcd2014-12-01 17:55:16 -080078 ShStrTab = new (Ctx.allocate<ELFStringTableSection>())
79 ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0);
80 ShStrTab->add(ShStrTabName);
81
Jim Stichnoth467ffe52016-03-29 15:01:06 -070082 constexpr char SymTabName[] = ".symtab";
Jan Voung1f47ad02015-03-20 15:01:26 -070083 const Elf64_Xword SymTabAlign = ELF64 ? 8 : 4;
Jan Voung08c3bcd2014-12-01 17:55:16 -080084 const Elf64_Xword SymTabEntSize =
Jan Voung1f47ad02015-03-20 15:01:26 -070085 ELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
Jan Voung08c3bcd2014-12-01 17:55:16 -080086 static_assert(sizeof(Elf64_Sym) == 24 && sizeof(Elf32_Sym) == 16,
87 "Elf_Sym sizes cannot be derived from sizeof");
88 SymTab = createSection<ELFSymbolTableSection>(SymTabName, SHT_SYMTAB, 0,
89 SymTabAlign, SymTabEntSize);
Jim Stichnoth467ffe52016-03-29 15:01:06 -070090 SymTab->createNullSymbol(NullSection, &Ctx);
Jan Voung08c3bcd2014-12-01 17:55:16 -080091
Jim Stichnoth467ffe52016-03-29 15:01:06 -070092 constexpr char StrTabName[] = ".strtab";
Jan Voung08c3bcd2014-12-01 17:55:16 -080093 StrTab =
94 createSection<ELFStringTableSection>(StrTabName, SHT_STRTAB, 0, 1, 0);
95}
96
97template <typename T>
Jim Stichnoth467ffe52016-03-29 15:01:06 -070098T *ELFObjectWriter::createSection(const std::string &Name, Elf64_Word ShType,
Jan Voung08c3bcd2014-12-01 17:55:16 -080099 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 *
Jan Voung1f47ad02015-03-20 15:01:26 -0700109ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) {
Andrew Scull57e12682015-09-16 11:30:19 -0700110 // Choice of RELA vs REL is actually separate from elf64 vs elf32, but in
111 // practice we've only had .rela for elf64 (x86-64). In the future, the two
112 // properties may need to be decoupled and the ShEntSize can vary more.
Jan Voung1f47ad02015-03-20 15:01:26 -0700113 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700114 const std::string RelPrefix = ELF64 ? ".rela" : ".rel";
115 const std::string RelSectionName = RelPrefix + RelatedSection->getName();
Jan Voung1f47ad02015-03-20 15:01:26 -0700116 const Elf64_Xword ShAlign = ELF64 ? 8 : 4;
117 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel);
Jan Voung72984d82015-01-29 14:42:38 -0800118 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8,
119 "Elf_Rel/Rela sizes cannot be derived from sizeof");
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700120 constexpr Elf64_Xword ShFlags = 0;
Jan Voung72984d82015-01-29 14:42:38 -0800121 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>(
122 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize);
123 RelSection->setRelatedSection(RelatedSection);
124 return RelSection;
125}
126
Jan Voung08c3bcd2014-12-01 17:55:16 -0800127template <typename UserSectionList>
128void ELFObjectWriter::assignRelSectionNumInPairs(SizeT &CurSectionNumber,
129 UserSectionList &UserSections,
130 RelSectionList &RelSections,
131 SectionList &AllSections) {
132 RelSectionList::iterator RelIt = RelSections.begin();
133 RelSectionList::iterator RelE = RelSections.end();
134 for (ELFSection *UserSection : UserSections) {
135 UserSection->setNumber(CurSectionNumber++);
136 UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName()));
137 AllSections.push_back(UserSection);
138 if (RelIt != RelE) {
Jan Voungec270732015-01-12 17:00:22 -0800139 ELFRelocationSection *RelSection = *RelIt;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800140 if (RelSection->getRelatedSection() == UserSection) {
141 RelSection->setInfoNum(UserSection->getNumber());
142 RelSection->setNumber(CurSectionNumber++);
143 RelSection->setNameStrIndex(ShStrTab->getIndex(RelSection->getName()));
144 AllSections.push_back(RelSection);
145 ++RelIt;
146 }
147 }
148 }
149 // Should finish with UserIt at the same time as RelIt.
150 assert(RelIt == RelE);
151 return;
152}
153
154void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber,
155 RelSectionList &RelSections) {
Jan Voungec270732015-01-12 17:00:22 -0800156 for (ELFRelocationSection *S : RelSections) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800157 S->setLinkNum(SymTabNumber);
158 }
159}
160
161void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) {
Andrew Scull57e12682015-09-16 11:30:19 -0700162 // Go through each section, assigning them section numbers and and fill in
163 // the size for sections that aren't incrementally updated.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800164 assert(!SectionNumbersAssigned);
165 SizeT CurSectionNumber = 0;
166 NullSection->setNumber(CurSectionNumber++);
167 // The rest of the fields are initialized to 0, and stay that way.
168 AllSections.push_back(NullSection);
169
170 assignRelSectionNumInPairs<TextSectionList>(CurSectionNumber, TextSections,
171 RelTextSections, AllSections);
172 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, DataSections,
173 RelDataSections, AllSections);
Jan Voung72984d82015-01-29 14:42:38 -0800174 for (ELFSection *BSSSection : BSSSections) {
175 BSSSection->setNumber(CurSectionNumber++);
176 BSSSection->setNameStrIndex(ShStrTab->getIndex(BSSSection->getName()));
177 AllSections.push_back(BSSSection);
178 }
179 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, RODataSections,
180 RelRODataSections, AllSections);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800181
182 ShStrTab->setNumber(CurSectionNumber++);
183 ShStrTab->setNameStrIndex(ShStrTab->getIndex(ShStrTab->getName()));
184 AllSections.push_back(ShStrTab);
185
186 SymTab->setNumber(CurSectionNumber++);
187 SymTab->setNameStrIndex(ShStrTab->getIndex(SymTab->getName()));
188 AllSections.push_back(SymTab);
189
190 StrTab->setNumber(CurSectionNumber++);
191 StrTab->setNameStrIndex(ShStrTab->getIndex(StrTab->getName()));
192 AllSections.push_back(StrTab);
193
194 SymTab->setLinkNum(StrTab->getNumber());
195 SymTab->setInfoNum(SymTab->getNumLocals());
196
197 assignRelLinkNum(SymTab->getNumber(), RelTextSections);
198 assignRelLinkNum(SymTab->getNumber(), RelDataSections);
Jan Voung72984d82015-01-29 14:42:38 -0800199 assignRelLinkNum(SymTab->getNumber(), RelRODataSections);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800200 SectionNumbersAssigned = true;
201}
202
203Elf64_Off ELFObjectWriter::alignFileOffset(Elf64_Xword Align) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800204 Elf64_Off OffsetInFile = Str.tell();
Jan Voung72984d82015-01-29 14:42:38 -0800205 Elf64_Xword AlignDiff = Utils::OffsetToAlignment(OffsetInFile, Align);
206 if (AlignDiff == 0)
Jan Voung08c3bcd2014-12-01 17:55:16 -0800207 return OffsetInFile;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800208 Str.writeZeroPadding(AlignDiff);
209 OffsetInFile += AlignDiff;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800210 return OffsetInFile;
211}
212
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700213void ELFObjectWriter::writeFunctionCode(GlobalString FuncName, bool IsInternal,
214 Assembler *Asm) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800215 assert(!SectionNumbersAssigned);
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700216 TimerMarker T_func(&Ctx, FuncName.toStringOrEmpty());
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800217 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voungec270732015-01-12 17:00:22 -0800218 ELFTextSection *Section = nullptr;
Jan Voung72984d82015-01-29 14:42:38 -0800219 ELFRelocationSection *RelSection = nullptr;
Karl Schimpfd4699942016-04-02 09:55:31 -0700220 const bool FunctionSections = getFlags().getFunctionSections();
Jan Voungcb165ca2015-02-24 08:53:52 -0800221 if (TextSections.empty() || FunctionSections) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700222 std::string SectionName = ".text";
Jan Voungcb165ca2015-02-24 08:53:52 -0800223 if (FunctionSections)
224 SectionName += "." + FuncName;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700225 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR;
Jan Vounge9079cb2015-02-25 09:08:44 -0800226 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes();
Jan Voung08c3bcd2014-12-01 17:55:16 -0800227 Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags,
228 ShAlign, 0);
229 Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign());
230 Section->setFileOffset(OffsetInFile);
231 TextSections.push_back(Section);
Jan Voung1f47ad02015-03-20 15:01:26 -0700232 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800233 RelTextSections.push_back(RelSection);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800234 } else {
235 Section = TextSections[0];
Jan Voung72984d82015-01-29 14:42:38 -0800236 RelSection = RelTextSections[0];
Jan Voung08c3bcd2014-12-01 17:55:16 -0800237 }
John Porto56958cb2016-01-14 09:18:18 -0800238 const RelocOffsetT OffsetInSection = Section->getCurrentSize();
Andrew Scull57e12682015-09-16 11:30:19 -0700239 // Function symbols are set to 0 size in the symbol table, in contrast to
240 // data symbols which have a proper size.
John Porto56958cb2016-01-14 09:18:18 -0800241 constexpr SizeT SymbolSize = 0;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800242 uint8_t SymbolType;
243 uint8_t SymbolBinding;
Karl Schimpfd4699942016-04-02 09:55:31 -0700244 if (IsInternal && !getFlags().getDisableInternal()) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800245 SymbolType = STT_NOTYPE;
246 SymbolBinding = STB_LOCAL;
247 } else {
248 SymbolType = STT_FUNC;
249 SymbolBinding = STB_GLOBAL;
250 }
251 SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section,
252 OffsetInSection, SymbolSize);
253 StrTab->add(FuncName);
Jan Voungec270732015-01-12 17:00:22 -0800254
Jan Voungcb165ca2015-02-24 08:53:52 -0800255 // Copy the fixup information from per-function Assembler memory to the
256 // object writer's memory, for writing later.
John Porto6e8d3fa2016-02-04 10:35:20 -0800257 const auto &Fixups = Asm->fixups();
258 if (!Fixups.empty()) {
259 if (!RelSection->isRela()) {
260 // This is a non-rela section, so we need to update the instruction stream
261 // with the relocation addends.
262 for (const auto *Fixup : Fixups) {
263 Fixup->emitOffset(Asm);
264 }
265 }
Jim Stichnoth3e324002016-03-08 16:18:40 -0800266 RelSection->addRelocations(OffsetInSection, Asm->fixups(), SymTab);
Jan Voungec270732015-01-12 17:00:22 -0800267 }
John Porto6e8d3fa2016-02-04 10:35:20 -0800268 Section->appendData(Str, Asm->getBufferView());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800269}
270
Jan Voung72984d82015-01-29 14:42:38 -0800271namespace {
272
273ELFObjectWriter::SectionType
274classifyGlobalSection(const VariableDeclaration *Var) {
275 if (Var->getIsConstant())
276 return ELFObjectWriter::ROData;
277 if (Var->hasNonzeroInitializer())
278 return ELFObjectWriter::Data;
279 return ELFObjectWriter::BSS;
280}
281
Andrew Scull57e12682015-09-16 11:30:19 -0700282// Partition the Vars list by SectionType into VarsBySection. If TranslateOnly
283// is non-empty, then only the TranslateOnly variable is kept for emission.
Jan Voung72984d82015-01-29 14:42:38 -0800284void partitionGlobalsBySection(const VariableDeclarationList &Vars,
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700285 VariableDeclarationPartition VarsBySection[]) {
Jan Voung72984d82015-01-29 14:42:38 -0800286 for (VariableDeclaration *Var : Vars) {
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700287 if (getFlags().matchTranslateOnly(Var->getName(), 0)) {
Jan Voung72984d82015-01-29 14:42:38 -0800288 size_t Section = classifyGlobalSection(Var);
JF Bastienae6e12c2015-01-31 10:13:25 -0800289 assert(Section < ELFObjectWriter::NumSectionTypes);
Jan Voung72984d82015-01-29 14:42:38 -0800290 VarsBySection[Section].push_back(Var);
291 }
292 }
293}
294
295} // end of anonymous namespace
296
Jaydeep Patil3da9f652016-11-03 22:54:06 -0700297void ELFObjectWriter::writeTargetRODataSection(const std::string &Name,
298 Elf64_Word ShType,
299 Elf64_Xword ShFlags,
300 Elf64_Xword ShAddralign,
301 Elf64_Xword ShEntsize,
302 const llvm::StringRef &SecData) {
303 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
304 assert(!SectionNumbersAssigned);
305 ELFDataSection *Section = createSection<ELFDataSection>(
306 Name, ShType, ShFlags, ShAddralign, ShEntsize);
307 Section->setFileOffset(alignFileOffset(ShAddralign));
308 Section->appendData(Str, llvm::StringRef(SecData.data(), SecData.size()));
309 RODataSections.push_back(Section);
310}
311
Jan Voung72984d82015-01-29 14:42:38 -0800312void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
John Porto8b1a7052015-06-17 13:20:08 -0700313 FixupKind RelocationKind,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700314 const std::string &SectionSuffix,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800315 bool IsPIC) {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800316 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800317 assert(!SectionNumbersAssigned);
John Portoa78e4ba2016-03-15 09:28:04 -0700318 VariableDeclarationPartition VarsBySection[ELFObjectWriter::NumSectionTypes];
Jan Voung72984d82015-01-29 14:42:38 -0800319 for (auto &SectionList : VarsBySection)
320 SectionList.reserve(Vars.size());
Jim Stichnothdd6dcfa2016-04-18 12:52:09 -0700321 partitionGlobalsBySection(Vars, VarsBySection);
Jan Voung72984d82015-01-29 14:42:38 -0800322 size_t I = 0;
323 for (auto &SectionList : VarsBySection) {
John Porto8b1a7052015-06-17 13:20:08 -0700324 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800325 SectionSuffix, IsPIC);
Jan Voung72984d82015-01-29 14:42:38 -0800326 }
327}
328
John Porto8b1a7052015-06-17 13:20:08 -0700329namespace {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700330std::string MangleSectionName(const char Base[], const std::string &Suffix) {
John Porto8b1a7052015-06-17 13:20:08 -0700331 if (Suffix.empty())
332 return Base;
333 return Base + ("." + Suffix);
334}
335} // end of anonymous namespace
336
337// TODO(jvoung): Handle fdata-sections.
JF Bastienae6e12c2015-01-31 10:13:25 -0800338void ELFObjectWriter::writeDataOfType(SectionType ST,
John Portoa78e4ba2016-03-15 09:28:04 -0700339 const VariableDeclarationPartition &Vars,
John Porto8b1a7052015-06-17 13:20:08 -0700340 FixupKind RelocationKind,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700341 const std::string &SectionSuffix,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800342 bool IsPIC) {
Jan Voung77973cc2015-02-03 12:48:38 -0800343 if (Vars.empty())
344 return;
Jan Voung72984d82015-01-29 14:42:38 -0800345 ELFDataSection *Section;
346 ELFRelocationSection *RelSection;
Jan Voung77973cc2015-02-03 12:48:38 -0800347 Elf64_Xword ShAddralign = 1;
Jan Voung72984d82015-01-29 14:42:38 -0800348 for (VariableDeclaration *Var : Vars) {
349 Elf64_Xword Align = Var->getAlignment();
350 ShAddralign = std::max(ShAddralign, Align);
351 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700352 constexpr Elf64_Xword ShEntsize = 0; // non-uniform data element size.
Jan Voung72984d82015-01-29 14:42:38 -0800353 // Lift this out, so it can be re-used if we do fdata-sections?
JF Bastienae6e12c2015-01-31 10:13:25 -0800354 switch (ST) {
355 case ROData: {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700356 const std::string SectionName =
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800357 MangleSectionName(IsPIC ? ".data.rel.ro" : ".rodata", SectionSuffix);
Jim Stichnothcaeaa272016-01-10 12:53:44 -0800358 const Elf64_Xword ShFlags = IsPIC ? (SHF_ALLOC | SHF_WRITE) : SHF_ALLOC;
Jan Voung72984d82015-01-29 14:42:38 -0800359 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
360 ShAddralign, ShEntsize);
361 Section->setFileOffset(alignFileOffset(ShAddralign));
362 RODataSections.push_back(Section);
Jan Voung1f47ad02015-03-20 15:01:26 -0700363 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800364 RelRODataSections.push_back(RelSection);
365 break;
366 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800367 case Data: {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700368 const std::string SectionName = MangleSectionName(".data", SectionSuffix);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700369 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
Jan Voung72984d82015-01-29 14:42:38 -0800370 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
371 ShAddralign, ShEntsize);
372 Section->setFileOffset(alignFileOffset(ShAddralign));
373 DataSections.push_back(Section);
Jan Voung1f47ad02015-03-20 15:01:26 -0700374 RelSection = createRelocationSection(Section);
Jan Voung72984d82015-01-29 14:42:38 -0800375 RelDataSections.push_back(RelSection);
376 break;
377 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800378 case BSS: {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700379 const std::string SectionName = MangleSectionName(".bss", SectionSuffix);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700380 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
Jan Voung72984d82015-01-29 14:42:38 -0800381 Section = createSection<ELFDataSection>(SectionName, SHT_NOBITS, ShFlags,
382 ShAddralign, ShEntsize);
383 Section->setFileOffset(alignFileOffset(ShAddralign));
384 BSSSections.push_back(Section);
385 break;
386 }
JF Bastienae6e12c2015-01-31 10:13:25 -0800387 case NumSectionTypes:
Jan Voung72984d82015-01-29 14:42:38 -0800388 llvm::report_fatal_error("Unknown SectionType");
389 break;
390 }
391
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700392 constexpr uint8_t SymbolType = STT_OBJECT;
Jan Voung72984d82015-01-29 14:42:38 -0800393 for (VariableDeclaration *Var : Vars) {
Jan Voung77973cc2015-02-03 12:48:38 -0800394 // If the variable declaration does not have an initializer, its symtab
395 // entry will be created separately.
396 if (!Var->hasInitializer())
397 continue;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700398 constexpr Elf64_Xword MinAlign = 1;
John Porto267f2bf2016-03-24 06:11:29 -0700399 const auto Align = std::max<Elf64_Xword>(MinAlign, Var->getAlignment());
Jan Voung72984d82015-01-29 14:42:38 -0800400 Section->padToAlignment(Str, Align);
401 SizeT SymbolSize = Var->getNumBytes();
Karl Schimpfd4699942016-04-02 09:55:31 -0700402 bool IsExternal = Var->isExternal() || getFlags().getDisableInternal();
Jan Voung72984d82015-01-29 14:42:38 -0800403 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700404 GlobalString Name = Var->getName();
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800405 SymTab->createDefinedSym(Name, SymbolType, SymbolBinding, Section,
Jan Voung72984d82015-01-29 14:42:38 -0800406 Section->getCurrentSize(), SymbolSize);
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800407 StrTab->add(Name);
Jan Voung72984d82015-01-29 14:42:38 -0800408 if (!Var->hasNonzeroInitializer()) {
JF Bastienae6e12c2015-01-31 10:13:25 -0800409 assert(ST == BSS || ST == ROData);
410 if (ST == ROData)
Jan Voung72984d82015-01-29 14:42:38 -0800411 Section->appendZeros(Str, SymbolSize);
412 else
413 Section->setSize(Section->getCurrentSize() + SymbolSize);
414 } else {
JF Bastienae6e12c2015-01-31 10:13:25 -0800415 assert(ST != BSS);
John Portoa78e4ba2016-03-15 09:28:04 -0700416 for (const auto *Init : Var->getInitializers()) {
Jan Voung72984d82015-01-29 14:42:38 -0800417 switch (Init->getKind()) {
418 case VariableDeclaration::Initializer::DataInitializerKind: {
Qining Lu7cd53512015-06-26 09:36:00 -0700419 const auto &Data =
John Portoa78e4ba2016-03-15 09:28:04 -0700420 llvm::cast<VariableDeclaration::DataInitializer>(Init)
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700421 ->getContents();
Jan Voung72984d82015-01-29 14:42:38 -0800422 Section->appendData(Str, llvm::StringRef(Data.data(), Data.size()));
423 break;
424 }
425 case VariableDeclaration::Initializer::ZeroInitializerKind:
426 Section->appendZeros(Str, Init->getNumBytes());
427 break;
428 case VariableDeclaration::Initializer::RelocInitializerKind: {
John Portodc619252016-02-10 15:57:16 -0800429 const auto *Reloc =
John Portoa78e4ba2016-03-15 09:28:04 -0700430 llvm::cast<VariableDeclaration::RelocInitializer>(Init);
Jan Voung72984d82015-01-29 14:42:38 -0800431 AssemblerFixup NewFixup;
432 NewFixup.set_position(Section->getCurrentSize());
John Portodc619252016-02-10 15:57:16 -0800433 NewFixup.set_kind(Reloc->hasFixup() ? Reloc->getFixup()
434 : RelocationKind);
435 assert(NewFixup.kind() != llvm::ELF::R_ARM_NONE);
Jan Voung72984d82015-01-29 14:42:38 -0800436 NewFixup.set_value(Ctx.getConstantSym(
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800437 Reloc->getOffset(), Reloc->getDeclaration()->getName()));
Jan Voung72984d82015-01-29 14:42:38 -0800438 RelSection->addRelocation(NewFixup);
439 Section->appendRelocationOffset(Str, RelSection->isRela(),
440 Reloc->getOffset());
441 break;
442 }
443 }
444 }
445 }
446 }
Jan Voung08c3bcd2014-12-01 17:55:16 -0800447}
448
449void ELFObjectWriter::writeInitialELFHeader() {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800450 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800451 assert(!SectionNumbersAssigned);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700452 constexpr Elf64_Off DummySHOffset = 0;
453 constexpr SizeT DummySHStrIndex = 0;
454 constexpr SizeT DummyNumSections = 0;
Jan Voung1f47ad02015-03-20 15:01:26 -0700455 if (ELF64) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800456 writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex,
457 DummyNumSections);
458 } else {
459 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex,
460 DummyNumSections);
461 }
462}
463
464template <bool IsELF64>
Jan Vounga601cc52014-12-03 15:51:22 -0800465void ELFObjectWriter::writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,
Jan Voung08c3bcd2014-12-01 17:55:16 -0800466 SizeT SectHeaderStrIndex,
467 SizeT NumSections) {
Andrew Scull57e12682015-09-16 11:30:19 -0700468 // Write the e_ident: magic number, class, etc. The e_ident is byte order and
469 // ELF class independent.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800470 Str.writeBytes(llvm::StringRef(ElfMagic, strlen(ElfMagic)));
471 Str.write8(IsELF64 ? ELFCLASS64 : ELFCLASS32);
472 Str.write8(ELFDATA2LSB);
473 Str.write8(EV_CURRENT);
474 Str.write8(ELFOSABI_NONE);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700475 constexpr uint8_t ELF_ABIVersion = 0;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800476 Str.write8(ELF_ABIVersion);
477 Str.writeZeroPadding(EI_NIDENT - EI_PAD);
478
Andrew Scull57e12682015-09-16 11:30:19 -0700479 // TODO(jvoung): Handle and test > 64K sections. See the generic ABI doc:
480 // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html e_shnum should
481 // be 0 and then actual number of sections is stored in the sh_size member of
482 // the 0th section.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800483 assert(NumSections < SHN_LORESERVE);
484 assert(SectHeaderStrIndex < SHN_LORESERVE);
485
Karl Schimpfd4699942016-04-02 09:55:31 -0700486 const TargetArch Arch = getFlags().getTargetArch();
Andrew Scull57e12682015-09-16 11:30:19 -0700487 // Write the rest of the file header, which does depend on byte order and ELF
488 // class.
Karl Schimpfd4699942016-04-02 09:55:31 -0700489 Str.writeLE16(ET_REL); // e_type
490 Str.writeLE16(getELFMachine(getFlags().getTargetArch())); // e_machine
491 Str.writeELFWord<IsELF64>(1); // e_version
Andrew Scull57e12682015-09-16 11:30:19 -0700492 // Since this is for a relocatable object, there is no entry point, and no
493 // program headers.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800494 Str.writeAddrOrOffset<IsELF64>(0); // e_entry
495 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff
496 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff
Jan Voung1f47ad02015-03-20 15:01:26 -0700497 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags
Jan Voung08c3bcd2014-12-01 17:55:16 -0800498 Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize
499 static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52,
500 "Elf_Ehdr sizes cannot be derived from sizeof");
501 Str.writeLE16(0); // e_phentsize
502 Str.writeLE16(0); // e_phnum
503 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr)
504 : sizeof(Elf32_Shdr)); // e_shentsize
505 static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40,
506 "Elf_Shdr sizes cannot be derived from sizeof");
507 Str.writeLE16(static_cast<Elf64_Half>(NumSections)); // e_shnum
508 Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx
509}
510
Jan Voung91a3e2c2015-01-09 13:01:42 -0800511template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800512 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voung91a3e2c2015-01-09 13:01:42 -0800513 ConstantList Pool = Ctx.getConstantPool(Ty);
514 if (Pool.empty()) {
515 return;
516 }
517 SizeT Align = typeAlignInBytes(Ty);
518 size_t EntSize = typeWidthInBytes(Ty);
519 char Buf[20];
520 SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf));
Qining Lu253dc8a2015-06-22 10:10:23 -0700521 // Check that we write the full PrimType.
Jan Voung91a3e2c2015-01-09 13:01:42 -0800522 assert(WriteAmt == EntSize);
523 // Assume that writing WriteAmt bytes at a time allows us to avoid aligning
524 // between entries.
525 assert(WriteAmt % Align == 0);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700526 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE;
Jan Voung91a3e2c2015-01-09 13:01:42 -0800527 std::string SecBuffer;
528 llvm::raw_string_ostream SecStrBuf(SecBuffer);
529 SecStrBuf << ".rodata.cst" << WriteAmt;
530 ELFDataSection *Section = createSection<ELFDataSection>(
531 SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt);
Jan Voung72984d82015-01-29 14:42:38 -0800532 RODataSections.push_back(Section);
Jan Voung91a3e2c2015-01-09 13:01:42 -0800533 SizeT OffsetInSection = 0;
Andrew Scull57e12682015-09-16 11:30:19 -0700534 // The symbol table entry doesn't need to know the defined symbol's size
535 // since this is in a section with a fixed Entry Size.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700536 constexpr SizeT SymbolSize = 0;
Jan Voung91a3e2c2015-01-09 13:01:42 -0800537 Section->setFileOffset(alignFileOffset(Align));
538
539 // Write the data.
540 for (Constant *C : Pool) {
Qining Lu253dc8a2015-06-22 10:10:23 -0700541 if (!C->getShouldBePooled())
542 continue;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700543 auto *Const = llvm::cast<ConstType>(C);
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700544 GlobalString SymName = Const->getLabelName();
Jan Voung91a3e2c2015-01-09 13:01:42 -0800545 SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section,
546 OffsetInSection, SymbolSize);
547 StrTab->add(SymName);
548 typename ConstType::PrimType Value = Const->getValue();
549 memcpy(Buf, &Value, WriteAmt);
550 Str.writeBytes(llvm::StringRef(Buf, WriteAmt));
551 OffsetInSection += WriteAmt;
552 }
553 Section->setSize(OffsetInSection);
554}
555
Andrew Scull57e12682015-09-16 11:30:19 -0700556// Instantiate known needed versions of the template, since we are defining the
557// function in the .cpp file instead of the .h file. We may need to instantiate
558// constant pools for integers as well if we do constant-pooling of large
559// integers to remove them from the instruction stream (fewer bytes controlled
560// by an attacker).
Jan Voung91a3e2c2015-01-09 13:01:42 -0800561template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty);
562
563template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty);
564
Qining Lu253dc8a2015-06-22 10:10:23 -0700565template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty);
566
Jan Voung1f47ad02015-03-20 15:01:26 -0700567void ELFObjectWriter::writeAllRelocationSections() {
568 writeRelocationSections(RelTextSections);
569 writeRelocationSections(RelDataSections);
570 writeRelocationSections(RelRODataSections);
Jan Voungec270732015-01-12 17:00:22 -0800571}
572
Andrew Scull86df4e92015-07-30 13:54:44 -0700573void ELFObjectWriter::writeJumpTable(const JumpTableData &JT,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800574 FixupKind RelocationKind, bool IsPIC) {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800575 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Andrew Scull86df4e92015-07-30 13:54:44 -0700576 ELFDataSection *Section;
577 ELFRelocationSection *RelSection;
578 const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType());
579 const Elf64_Xword ShAddralign = PointerSize;
580 const Elf64_Xword ShEntsize = PointerSize;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700581 const std::string SectionName = MangleSectionName(
John Porto03077212016-04-05 06:30:21 -0700582 IsPIC ? ".data.rel.ro" : ".rodata", JT.getSectionName());
Andrew Scull86df4e92015-07-30 13:54:44 -0700583 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC,
584 ShAddralign, ShEntsize);
585 Section->setFileOffset(alignFileOffset(ShAddralign));
586 RODataSections.push_back(Section);
587 RelSection = createRelocationSection(Section);
588 RelRODataSections.push_back(RelSection);
589
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700590 constexpr uint8_t SymbolType = STT_OBJECT;
Andrew Scull86df4e92015-07-30 13:54:44 -0700591 Section->padToAlignment(Str, PointerSize);
Karl Schimpfd4699942016-04-02 09:55:31 -0700592 const bool IsExternal = getFlags().getDisableInternal();
Andrew Scull86df4e92015-07-30 13:54:44 -0700593 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
John Porto03077212016-04-05 06:30:21 -0700594 const auto JumpTableName = JT.getName();
Andrew Scull86df4e92015-07-30 13:54:44 -0700595 SymTab->createDefinedSym(JumpTableName, SymbolType, SymbolBinding, Section,
596 Section->getCurrentSize(), PointerSize);
597 StrTab->add(JumpTableName);
598
599 for (intptr_t TargetOffset : JT.getTargetOffsets()) {
600 AssemblerFixup NewFixup;
601 NewFixup.set_position(Section->getCurrentSize());
602 NewFixup.set_kind(RelocationKind);
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800603 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName()));
Andrew Scull86df4e92015-07-30 13:54:44 -0700604 RelSection->addRelocation(NewFixup);
605 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset);
606 }
607}
608
Jan Voung261cae32015-02-01 10:31:03 -0800609void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800610 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
Jan Voung261cae32015-02-01 10:31:03 -0800611 for (const Constant *S : UndefSyms) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700612 const auto *Sym = llvm::cast<ConstantRelocatable>(S);
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700613 GlobalString Name = Sym->getName();
614 assert(Name.hasStdString());
Jan Voung261cae32015-02-01 10:31:03 -0800615 assert(Sym->getOffset() == 0);
Jan Voung261cae32015-02-01 10:31:03 -0800616 SymTab->noteUndefinedSym(Name, NullSection);
617 StrTab->add(Name);
618 }
619}
620
Jan Voung1f47ad02015-03-20 15:01:26 -0700621void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) {
Jan Voungec270732015-01-12 17:00:22 -0800622 for (ELFRelocationSection *RelSec : RelSections) {
623 Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign());
624 RelSec->setFileOffset(Offset);
Jan Voung261cae32015-02-01 10:31:03 -0800625 RelSec->setSize(RelSec->getSectionDataSize());
Jan Voung1f47ad02015-03-20 15:01:26 -0700626 if (ELF64) {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800627 RelSec->writeData<true>(Str, SymTab);
Jan Voungec270732015-01-12 17:00:22 -0800628 } else {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800629 RelSec->writeData<false>(Str, SymTab);
Jan Voungec270732015-01-12 17:00:22 -0800630 }
631 }
632}
633
Jan Voung08c3bcd2014-12-01 17:55:16 -0800634void ELFObjectWriter::writeNonUserSections() {
Karl Schimpfb6e9b892016-03-08 12:27:12 -0800635 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
636
Jan Voung08c3bcd2014-12-01 17:55:16 -0800637 // Write out the shstrtab now that all sections are known.
638 ShStrTab->doLayout();
639 ShStrTab->setSize(ShStrTab->getSectionDataSize());
640 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign());
641 ShStrTab->setFileOffset(ShStrTabOffset);
642 Str.writeBytes(ShStrTab->getSectionData());
643
644 SectionList AllSections;
645 assignSectionNumbersInfo(AllSections);
646
647 // Finalize the regular StrTab and fix up references in the SymTab.
648 StrTab->doLayout();
649 StrTab->setSize(StrTab->getSectionDataSize());
650
651 SymTab->updateIndices(StrTab);
652
653 Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign());
654 SymTab->setFileOffset(SymTabOffset);
655 SymTab->setSize(SymTab->getSectionDataSize());
Jan Voung1f47ad02015-03-20 15:01:26 -0700656 SymTab->writeData(Str, ELF64);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800657
658 Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign());
659 StrTab->setFileOffset(StrTabOffset);
660 Str.writeBytes(StrTab->getSectionData());
661
Jan Voung1f47ad02015-03-20 15:01:26 -0700662 writeAllRelocationSections();
Jan Voung08c3bcd2014-12-01 17:55:16 -0800663
664 // Write out the section headers.
Jan Voung1f47ad02015-03-20 15:01:26 -0700665 const size_t ShdrAlign = ELF64 ? 8 : 4;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800666 Elf64_Off ShOffset = alignFileOffset(ShdrAlign);
667 for (const auto S : AllSections) {
Jan Voung1f47ad02015-03-20 15:01:26 -0700668 if (ELF64)
Jan Voung08c3bcd2014-12-01 17:55:16 -0800669 S->writeHeader<true>(Str);
670 else
671 S->writeHeader<false>(Str);
672 }
673
674 // Finally write the updated ELF header w/ the correct number of sections.
675 Str.seek(0);
Jan Voung1f47ad02015-03-20 15:01:26 -0700676 if (ELF64) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800677 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(),
678 AllSections.size());
679 } else {
680 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(),
681 AllSections.size());
682 }
683}
684
685} // end of namespace Ice