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