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