xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceELFSection.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceELFSection.h - Model of ELF sections ------*- C++ -*-===//
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 Representation of ELF sections.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEELFSECTION_H
16*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEELFSECTION_H
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "IceELFStreamer.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceFixups.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceStringPool.h"
23*03ce13f7SAndroid Build Coastguard Worker 
24*03ce13f7SAndroid Build Coastguard Worker using namespace llvm::ELF;
25*03ce13f7SAndroid Build Coastguard Worker 
26*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
27*03ce13f7SAndroid Build Coastguard Worker 
28*03ce13f7SAndroid Build Coastguard Worker class ELFStreamer;
29*03ce13f7SAndroid Build Coastguard Worker class ELFStringTableSection;
30*03ce13f7SAndroid Build Coastguard Worker 
31*03ce13f7SAndroid Build Coastguard Worker /// Base representation of an ELF section.
32*03ce13f7SAndroid Build Coastguard Worker class ELFSection {
33*03ce13f7SAndroid Build Coastguard Worker   ELFSection() = delete;
34*03ce13f7SAndroid Build Coastguard Worker   ELFSection(const ELFSection &) = delete;
35*03ce13f7SAndroid Build Coastguard Worker   ELFSection &operator=(const ELFSection &) = delete;
36*03ce13f7SAndroid Build Coastguard Worker 
37*03ce13f7SAndroid Build Coastguard Worker public:
38*03ce13f7SAndroid Build Coastguard Worker   virtual ~ELFSection() = default;
39*03ce13f7SAndroid Build Coastguard Worker 
40*03ce13f7SAndroid Build Coastguard Worker   /// Sentinel value for a section number/index for before the final section
41*03ce13f7SAndroid Build Coastguard Worker   /// index is actually known. The dummy NULL section will be assigned number 0,
42*03ce13f7SAndroid Build Coastguard Worker   /// and it is referenced by the dummy 0-th symbol in the symbol table, so use
43*03ce13f7SAndroid Build Coastguard Worker   /// max() instead of 0.
44*03ce13f7SAndroid Build Coastguard Worker   enum { NoSectionNumber = std::numeric_limits<SizeT>::max() };
45*03ce13f7SAndroid Build Coastguard Worker 
46*03ce13f7SAndroid Build Coastguard Worker   /// Constructs an ELF section, filling in fields that will be known once the
47*03ce13f7SAndroid Build Coastguard Worker   /// *type* of section is decided. Other fields may be updated incrementally or
48*03ce13f7SAndroid Build Coastguard Worker   /// only after the program is completely defined.
ELFSection(const std::string & Name,Elf64_Word ShType,Elf64_Xword ShFlags,Elf64_Xword ShAddralign,Elf64_Xword ShEntsize)49*03ce13f7SAndroid Build Coastguard Worker   ELFSection(const std::string &Name, Elf64_Word ShType, Elf64_Xword ShFlags,
50*03ce13f7SAndroid Build Coastguard Worker              Elf64_Xword ShAddralign, Elf64_Xword ShEntsize)
51*03ce13f7SAndroid Build Coastguard Worker       : Name(Name), Header() {
52*03ce13f7SAndroid Build Coastguard Worker     Header.sh_type = ShType;
53*03ce13f7SAndroid Build Coastguard Worker     Header.sh_flags = ShFlags;
54*03ce13f7SAndroid Build Coastguard Worker     Header.sh_addralign = ShAddralign;
55*03ce13f7SAndroid Build Coastguard Worker     Header.sh_entsize = ShEntsize;
56*03ce13f7SAndroid Build Coastguard Worker   }
57*03ce13f7SAndroid Build Coastguard Worker 
58*03ce13f7SAndroid Build Coastguard Worker   /// Set the section number/index after it is finally known.
setNumber(SizeT N)59*03ce13f7SAndroid Build Coastguard Worker   void setNumber(SizeT N) {
60*03ce13f7SAndroid Build Coastguard Worker     // Should only set the number once: from NoSectionNumber -> N.
61*03ce13f7SAndroid Build Coastguard Worker     assert(Number == NoSectionNumber);
62*03ce13f7SAndroid Build Coastguard Worker     Number = N;
63*03ce13f7SAndroid Build Coastguard Worker   }
getNumber()64*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumber() const {
65*03ce13f7SAndroid Build Coastguard Worker     assert(Number != NoSectionNumber);
66*03ce13f7SAndroid Build Coastguard Worker     return Number;
67*03ce13f7SAndroid Build Coastguard Worker   }
68*03ce13f7SAndroid Build Coastguard Worker 
setSize(Elf64_Xword sh_size)69*03ce13f7SAndroid Build Coastguard Worker   void setSize(Elf64_Xword sh_size) { Header.sh_size = sh_size; }
getCurrentSize()70*03ce13f7SAndroid Build Coastguard Worker   SizeT getCurrentSize() const { return Header.sh_size; }
71*03ce13f7SAndroid Build Coastguard Worker 
setNameStrIndex(Elf64_Word sh_name)72*03ce13f7SAndroid Build Coastguard Worker   void setNameStrIndex(Elf64_Word sh_name) { Header.sh_name = sh_name; }
73*03ce13f7SAndroid Build Coastguard Worker 
getName()74*03ce13f7SAndroid Build Coastguard Worker   const std::string &getName() const { return Name; }
75*03ce13f7SAndroid Build Coastguard Worker 
setLinkNum(Elf64_Word sh_link)76*03ce13f7SAndroid Build Coastguard Worker   void setLinkNum(Elf64_Word sh_link) { Header.sh_link = sh_link; }
77*03ce13f7SAndroid Build Coastguard Worker 
setInfoNum(Elf64_Word sh_info)78*03ce13f7SAndroid Build Coastguard Worker   void setInfoNum(Elf64_Word sh_info) { Header.sh_info = sh_info; }
79*03ce13f7SAndroid Build Coastguard Worker 
setFileOffset(Elf64_Off sh_offset)80*03ce13f7SAndroid Build Coastguard Worker   void setFileOffset(Elf64_Off sh_offset) { Header.sh_offset = sh_offset; }
81*03ce13f7SAndroid Build Coastguard Worker 
getSectionAlign()82*03ce13f7SAndroid Build Coastguard Worker   Elf64_Xword getSectionAlign() const { return Header.sh_addralign; }
83*03ce13f7SAndroid Build Coastguard Worker 
84*03ce13f7SAndroid Build Coastguard Worker   /// Write the section header out with the given streamer.
85*03ce13f7SAndroid Build Coastguard Worker   template <bool IsELF64> void writeHeader(ELFStreamer &Str);
86*03ce13f7SAndroid Build Coastguard Worker 
87*03ce13f7SAndroid Build Coastguard Worker protected:
88*03ce13f7SAndroid Build Coastguard Worker   /// Name of the section in convenient string form (instead of a index into the
89*03ce13f7SAndroid Build Coastguard Worker   /// Section Header String Table, which is not known till later).
90*03ce13f7SAndroid Build Coastguard Worker   const std::string Name;
91*03ce13f7SAndroid Build Coastguard Worker 
92*03ce13f7SAndroid Build Coastguard Worker   // The fields of the header. May only be partially initialized, but should
93*03ce13f7SAndroid Build Coastguard Worker   // be fully initialized before writing.
94*03ce13f7SAndroid Build Coastguard Worker   Elf64_Shdr Header;
95*03ce13f7SAndroid Build Coastguard Worker 
96*03ce13f7SAndroid Build Coastguard Worker   /// The number of the section after laying out sections.
97*03ce13f7SAndroid Build Coastguard Worker   SizeT Number = NoSectionNumber;
98*03ce13f7SAndroid Build Coastguard Worker };
99*03ce13f7SAndroid Build Coastguard Worker 
100*03ce13f7SAndroid Build Coastguard Worker /// Models text/code sections. Code is written out incrementally and the size of
101*03ce13f7SAndroid Build Coastguard Worker /// the section is then updated incrementally.
102*03ce13f7SAndroid Build Coastguard Worker class ELFTextSection : public ELFSection {
103*03ce13f7SAndroid Build Coastguard Worker   ELFTextSection() = delete;
104*03ce13f7SAndroid Build Coastguard Worker   ELFTextSection(const ELFTextSection &) = delete;
105*03ce13f7SAndroid Build Coastguard Worker   ELFTextSection &operator=(const ELFTextSection &) = delete;
106*03ce13f7SAndroid Build Coastguard Worker 
107*03ce13f7SAndroid Build Coastguard Worker public:
108*03ce13f7SAndroid Build Coastguard Worker   using ELFSection::ELFSection;
109*03ce13f7SAndroid Build Coastguard Worker 
110*03ce13f7SAndroid Build Coastguard Worker   void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
111*03ce13f7SAndroid Build Coastguard Worker };
112*03ce13f7SAndroid Build Coastguard Worker 
113*03ce13f7SAndroid Build Coastguard Worker /// Models data/rodata sections. Data is written out incrementally and the size
114*03ce13f7SAndroid Build Coastguard Worker /// of the section is then updated incrementally. Some rodata sections may have
115*03ce13f7SAndroid Build Coastguard Worker /// fixed entsize and duplicates may be mergeable.
116*03ce13f7SAndroid Build Coastguard Worker class ELFDataSection : public ELFSection {
117*03ce13f7SAndroid Build Coastguard Worker   ELFDataSection() = delete;
118*03ce13f7SAndroid Build Coastguard Worker   ELFDataSection(const ELFDataSection &) = delete;
119*03ce13f7SAndroid Build Coastguard Worker   ELFDataSection &operator=(const ELFDataSection &) = delete;
120*03ce13f7SAndroid Build Coastguard Worker 
121*03ce13f7SAndroid Build Coastguard Worker public:
122*03ce13f7SAndroid Build Coastguard Worker   using ELFSection::ELFSection;
123*03ce13f7SAndroid Build Coastguard Worker 
124*03ce13f7SAndroid Build Coastguard Worker   void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
125*03ce13f7SAndroid Build Coastguard Worker 
126*03ce13f7SAndroid Build Coastguard Worker   void appendZeros(ELFStreamer &Str, SizeT NumBytes);
127*03ce13f7SAndroid Build Coastguard Worker 
128*03ce13f7SAndroid Build Coastguard Worker   void appendRelocationOffset(ELFStreamer &Str, bool IsRela,
129*03ce13f7SAndroid Build Coastguard Worker                               RelocOffsetT RelocOffset);
130*03ce13f7SAndroid Build Coastguard Worker 
131*03ce13f7SAndroid Build Coastguard Worker   /// Pad the next section offset for writing data elements to the requested
132*03ce13f7SAndroid Build Coastguard Worker   /// alignment. If the section is NOBITS then do not actually write out the
133*03ce13f7SAndroid Build Coastguard Worker   /// padding and only update the section size.
134*03ce13f7SAndroid Build Coastguard Worker   void padToAlignment(ELFStreamer &Str, Elf64_Xword Align);
135*03ce13f7SAndroid Build Coastguard Worker };
136*03ce13f7SAndroid Build Coastguard Worker 
137*03ce13f7SAndroid Build Coastguard Worker /// Model of ELF symbol table entries. Besides keeping track of the fields
138*03ce13f7SAndroid Build Coastguard Worker /// required for an elf symbol table entry it also tracks the number that
139*03ce13f7SAndroid Build Coastguard Worker /// represents the symbol's final index in the symbol table.
140*03ce13f7SAndroid Build Coastguard Worker struct ELFSym {
141*03ce13f7SAndroid Build Coastguard Worker   Elf64_Sym Sym;
142*03ce13f7SAndroid Build Coastguard Worker   ELFSection *Section;
143*03ce13f7SAndroid Build Coastguard Worker   SizeT Number;
144*03ce13f7SAndroid Build Coastguard Worker 
145*03ce13f7SAndroid Build Coastguard Worker   /// Sentinel value for symbols that haven't been assigned a number yet. The
146*03ce13f7SAndroid Build Coastguard Worker   /// dummy 0-th symbol will be assigned number 0, so don't use that.
147*03ce13f7SAndroid Build Coastguard Worker   enum { UnknownNumber = std::numeric_limits<SizeT>::max() };
148*03ce13f7SAndroid Build Coastguard Worker 
setNumberELFSym149*03ce13f7SAndroid Build Coastguard Worker   void setNumber(SizeT N) {
150*03ce13f7SAndroid Build Coastguard Worker     assert(Number == UnknownNumber);
151*03ce13f7SAndroid Build Coastguard Worker     Number = N;
152*03ce13f7SAndroid Build Coastguard Worker   }
153*03ce13f7SAndroid Build Coastguard Worker 
getNumberELFSym154*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumber() const {
155*03ce13f7SAndroid Build Coastguard Worker     assert(Number != UnknownNumber);
156*03ce13f7SAndroid Build Coastguard Worker     return Number;
157*03ce13f7SAndroid Build Coastguard Worker   }
158*03ce13f7SAndroid Build Coastguard Worker };
159*03ce13f7SAndroid Build Coastguard Worker 
160*03ce13f7SAndroid Build Coastguard Worker /// Models a symbol table. Symbols may be added up until updateIndices is
161*03ce13f7SAndroid Build Coastguard Worker /// called. At that point the indices of each symbol will be finalized.
162*03ce13f7SAndroid Build Coastguard Worker class ELFSymbolTableSection : public ELFSection {
163*03ce13f7SAndroid Build Coastguard Worker   ELFSymbolTableSection() = delete;
164*03ce13f7SAndroid Build Coastguard Worker   ELFSymbolTableSection(const ELFSymbolTableSection &) = delete;
165*03ce13f7SAndroid Build Coastguard Worker   ELFSymbolTableSection &operator=(const ELFSymbolTableSection &) = delete;
166*03ce13f7SAndroid Build Coastguard Worker 
167*03ce13f7SAndroid Build Coastguard Worker public:
ELFSymbolTableSection(const std::string & Name,Elf64_Word ShType,Elf64_Xword ShFlags,Elf64_Xword ShAddralign,Elf64_Xword ShEntsize)168*03ce13f7SAndroid Build Coastguard Worker   ELFSymbolTableSection(const std::string &Name, Elf64_Word ShType,
169*03ce13f7SAndroid Build Coastguard Worker                         Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
170*03ce13f7SAndroid Build Coastguard Worker                         Elf64_Xword ShEntsize)
171*03ce13f7SAndroid Build Coastguard Worker       : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize),
172*03ce13f7SAndroid Build Coastguard Worker         NullSymbolName(), NullSymbol(nullptr) {}
173*03ce13f7SAndroid Build Coastguard Worker 
174*03ce13f7SAndroid Build Coastguard Worker   /// Create initial entry for a symbol when it is defined. Each entry should
175*03ce13f7SAndroid Build Coastguard Worker   /// only be defined once. We might want to allow Name to be a dummy name
176*03ce13f7SAndroid Build Coastguard Worker   /// initially, then get updated to the real thing, since Data initializers are
177*03ce13f7SAndroid Build Coastguard Worker   /// read before the bitcode's symbol table is read.
178*03ce13f7SAndroid Build Coastguard Worker   void createDefinedSym(GlobalString Name, uint8_t Type, uint8_t Binding,
179*03ce13f7SAndroid Build Coastguard Worker                         ELFSection *Section, RelocOffsetT Offset, SizeT Size);
180*03ce13f7SAndroid Build Coastguard Worker 
181*03ce13f7SAndroid Build Coastguard Worker   /// Note that a symbol table entry needs to be created for the given symbol
182*03ce13f7SAndroid Build Coastguard Worker   /// because it is undefined.
183*03ce13f7SAndroid Build Coastguard Worker   void noteUndefinedSym(GlobalString Name, ELFSection *NullSection);
184*03ce13f7SAndroid Build Coastguard Worker 
185*03ce13f7SAndroid Build Coastguard Worker   const ELFSym *findSymbol(GlobalString Name) const;
186*03ce13f7SAndroid Build Coastguard Worker 
187*03ce13f7SAndroid Build Coastguard Worker   void createNullSymbol(ELFSection *NullSection, GlobalContext *Ctx);
getNullSymbol()188*03ce13f7SAndroid Build Coastguard Worker   const ELFSym *getNullSymbol() const { return NullSymbol; }
189*03ce13f7SAndroid Build Coastguard Worker 
getSectionDataSize()190*03ce13f7SAndroid Build Coastguard Worker   size_t getSectionDataSize() const {
191*03ce13f7SAndroid Build Coastguard Worker     return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize;
192*03ce13f7SAndroid Build Coastguard Worker   }
193*03ce13f7SAndroid Build Coastguard Worker 
getNumLocals()194*03ce13f7SAndroid Build Coastguard Worker   size_t getNumLocals() const { return LocalSymbols.size(); }
195*03ce13f7SAndroid Build Coastguard Worker 
196*03ce13f7SAndroid Build Coastguard Worker   void updateIndices(const ELFStringTableSection *StrTab);
197*03ce13f7SAndroid Build Coastguard Worker 
198*03ce13f7SAndroid Build Coastguard Worker   void writeData(ELFStreamer &Str, bool IsELF64);
199*03ce13f7SAndroid Build Coastguard Worker 
200*03ce13f7SAndroid Build Coastguard Worker private:
201*03ce13f7SAndroid Build Coastguard Worker   // Map from symbol name to its symbol information. This assumes symbols are
202*03ce13f7SAndroid Build Coastguard Worker   // unique across all sections.
203*03ce13f7SAndroid Build Coastguard Worker   using SymtabKey = GlobalString;
204*03ce13f7SAndroid Build Coastguard Worker   using SymMap = std::map<SymtabKey, ELFSym>;
205*03ce13f7SAndroid Build Coastguard Worker 
206*03ce13f7SAndroid Build Coastguard Worker   template <bool IsELF64>
207*03ce13f7SAndroid Build Coastguard Worker   void writeSymbolMap(ELFStreamer &Str, const SymMap &Map);
208*03ce13f7SAndroid Build Coastguard Worker 
209*03ce13f7SAndroid Build Coastguard Worker   GlobalString NullSymbolName;
210*03ce13f7SAndroid Build Coastguard Worker   const ELFSym *NullSymbol;
211*03ce13f7SAndroid Build Coastguard Worker   // Keep Local and Global symbols separate, since the sh_info needs to know
212*03ce13f7SAndroid Build Coastguard Worker   // the index of the last LOCAL.
213*03ce13f7SAndroid Build Coastguard Worker   SymMap LocalSymbols;
214*03ce13f7SAndroid Build Coastguard Worker   SymMap GlobalSymbols;
215*03ce13f7SAndroid Build Coastguard Worker };
216*03ce13f7SAndroid Build Coastguard Worker 
217*03ce13f7SAndroid Build Coastguard Worker /// Models a relocation section.
218*03ce13f7SAndroid Build Coastguard Worker class ELFRelocationSection : public ELFSection {
219*03ce13f7SAndroid Build Coastguard Worker   ELFRelocationSection() = delete;
220*03ce13f7SAndroid Build Coastguard Worker   ELFRelocationSection(const ELFRelocationSection &) = delete;
221*03ce13f7SAndroid Build Coastguard Worker   ELFRelocationSection &operator=(const ELFRelocationSection &) = delete;
222*03ce13f7SAndroid Build Coastguard Worker 
223*03ce13f7SAndroid Build Coastguard Worker public:
ELFRelocationSection(const std::string & Name,Elf64_Word ShType,Elf64_Xword ShFlags,Elf64_Xword ShAddralign,Elf64_Xword ShEntsize)224*03ce13f7SAndroid Build Coastguard Worker   ELFRelocationSection(const std::string &Name, Elf64_Word ShType,
225*03ce13f7SAndroid Build Coastguard Worker                        Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
226*03ce13f7SAndroid Build Coastguard Worker                        Elf64_Xword ShEntsize)
227*03ce13f7SAndroid Build Coastguard Worker       : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize),
228*03ce13f7SAndroid Build Coastguard Worker         RelatedSection(nullptr) {}
229*03ce13f7SAndroid Build Coastguard Worker 
getRelatedSection()230*03ce13f7SAndroid Build Coastguard Worker   const ELFSection *getRelatedSection() const { return RelatedSection; }
setRelatedSection(const ELFSection * Section)231*03ce13f7SAndroid Build Coastguard Worker   void setRelatedSection(const ELFSection *Section) {
232*03ce13f7SAndroid Build Coastguard Worker     RelatedSection = Section;
233*03ce13f7SAndroid Build Coastguard Worker   }
234*03ce13f7SAndroid Build Coastguard Worker 
235*03ce13f7SAndroid Build Coastguard Worker   /// Track additional relocations which start out relative to offset 0, but
236*03ce13f7SAndroid Build Coastguard Worker   /// should be adjusted to be relative to BaseOff.
237*03ce13f7SAndroid Build Coastguard Worker   void addRelocations(RelocOffsetT BaseOff, const FixupRefList &FixupRefs,
238*03ce13f7SAndroid Build Coastguard Worker                       ELFSymbolTableSection *SymTab);
239*03ce13f7SAndroid Build Coastguard Worker 
240*03ce13f7SAndroid Build Coastguard Worker   /// Track a single additional relocation.
addRelocation(const AssemblerFixup & Fixup)241*03ce13f7SAndroid Build Coastguard Worker   void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); }
242*03ce13f7SAndroid Build Coastguard Worker 
243*03ce13f7SAndroid Build Coastguard Worker   size_t getSectionDataSize() const;
244*03ce13f7SAndroid Build Coastguard Worker 
245*03ce13f7SAndroid Build Coastguard Worker   template <bool IsELF64>
246*03ce13f7SAndroid Build Coastguard Worker   void writeData(ELFStreamer &Str, const ELFSymbolTableSection *SymTab);
247*03ce13f7SAndroid Build Coastguard Worker 
isRela()248*03ce13f7SAndroid Build Coastguard Worker   bool isRela() const { return Header.sh_type == SHT_RELA; }
249*03ce13f7SAndroid Build Coastguard Worker 
250*03ce13f7SAndroid Build Coastguard Worker private:
251*03ce13f7SAndroid Build Coastguard Worker   const ELFSection *RelatedSection;
252*03ce13f7SAndroid Build Coastguard Worker   FixupList Fixups;
253*03ce13f7SAndroid Build Coastguard Worker };
254*03ce13f7SAndroid Build Coastguard Worker 
255*03ce13f7SAndroid Build Coastguard Worker /// Models a string table. The user will build the string table by adding
256*03ce13f7SAndroid Build Coastguard Worker /// strings incrementally. At some point, all strings should be known and
257*03ce13f7SAndroid Build Coastguard Worker /// doLayout() should be called. After that, no other strings may be added.
258*03ce13f7SAndroid Build Coastguard Worker /// However, the final offsets of the strings can be discovered and used to fill
259*03ce13f7SAndroid Build Coastguard Worker /// out section headers and symbol table entries.
260*03ce13f7SAndroid Build Coastguard Worker class ELFStringTableSection : public ELFSection {
261*03ce13f7SAndroid Build Coastguard Worker   ELFStringTableSection() = delete;
262*03ce13f7SAndroid Build Coastguard Worker   ELFStringTableSection(const ELFStringTableSection &) = delete;
263*03ce13f7SAndroid Build Coastguard Worker   ELFStringTableSection &operator=(const ELFStringTableSection &) = delete;
264*03ce13f7SAndroid Build Coastguard Worker 
265*03ce13f7SAndroid Build Coastguard Worker public:
266*03ce13f7SAndroid Build Coastguard Worker   using ELFSection::ELFSection;
267*03ce13f7SAndroid Build Coastguard Worker 
268*03ce13f7SAndroid Build Coastguard Worker   /// Add a string to the table, in preparation for final layout.
269*03ce13f7SAndroid Build Coastguard Worker   void add(const std::string &Str);
add(GlobalString Str)270*03ce13f7SAndroid Build Coastguard Worker   void add(GlobalString Str) {
271*03ce13f7SAndroid Build Coastguard Worker     if (Str.hasStdString())
272*03ce13f7SAndroid Build Coastguard Worker       add(Str.toString());
273*03ce13f7SAndroid Build Coastguard Worker   }
274*03ce13f7SAndroid Build Coastguard Worker 
275*03ce13f7SAndroid Build Coastguard Worker   /// Finalizes the layout of the string table and fills in the section Data.
276*03ce13f7SAndroid Build Coastguard Worker   void doLayout();
277*03ce13f7SAndroid Build Coastguard Worker 
278*03ce13f7SAndroid Build Coastguard Worker   /// The first byte of the string table should be \0, so it is an invalid
279*03ce13f7SAndroid Build Coastguard Worker   /// index. Indices start out as unknown until layout is complete.
280*03ce13f7SAndroid Build Coastguard Worker   enum { UnknownIndex = 0 };
281*03ce13f7SAndroid Build Coastguard Worker 
282*03ce13f7SAndroid Build Coastguard Worker   /// Grabs the final index of a string after layout. Returns UnknownIndex if
283*03ce13f7SAndroid Build Coastguard Worker   /// the string's index is not found.
284*03ce13f7SAndroid Build Coastguard Worker   size_t getIndex(const std::string &Str) const;
285*03ce13f7SAndroid Build Coastguard Worker 
getSectionData()286*03ce13f7SAndroid Build Coastguard Worker   llvm::StringRef getSectionData() const {
287*03ce13f7SAndroid Build Coastguard Worker     assert(isLaidOut());
288*03ce13f7SAndroid Build Coastguard Worker     return llvm::StringRef(reinterpret_cast<const char *>(StringData.data()),
289*03ce13f7SAndroid Build Coastguard Worker                            StringData.size());
290*03ce13f7SAndroid Build Coastguard Worker   }
291*03ce13f7SAndroid Build Coastguard Worker 
getSectionDataSize()292*03ce13f7SAndroid Build Coastguard Worker   size_t getSectionDataSize() const { return getSectionData().size(); }
293*03ce13f7SAndroid Build Coastguard Worker 
294*03ce13f7SAndroid Build Coastguard Worker private:
isLaidOut()295*03ce13f7SAndroid Build Coastguard Worker   bool isLaidOut() const { return !StringData.empty(); }
296*03ce13f7SAndroid Build Coastguard Worker 
297*03ce13f7SAndroid Build Coastguard Worker   /// Strings can share a string table entry if they share the same suffix.
298*03ce13f7SAndroid Build Coastguard Worker   /// E.g., "pop" and "lollipop" can both use the characters in "lollipop", but
299*03ce13f7SAndroid Build Coastguard Worker   /// "pops" cannot, and "unpop" cannot either. Though, "pop", "lollipop", and
300*03ce13f7SAndroid Build Coastguard Worker   /// "unpop" share "pop" as the suffix, "pop" can only share the characters
301*03ce13f7SAndroid Build Coastguard Worker   /// with one of them.
302*03ce13f7SAndroid Build Coastguard Worker   struct SuffixComparator {
303*03ce13f7SAndroid Build Coastguard Worker     bool operator()(const std::string &StrA, const std::string &StrB) const;
304*03ce13f7SAndroid Build Coastguard Worker   };
305*03ce13f7SAndroid Build Coastguard Worker 
306*03ce13f7SAndroid Build Coastguard Worker   using StringToIndexType = std::map<std::string, size_t, SuffixComparator>;
307*03ce13f7SAndroid Build Coastguard Worker 
308*03ce13f7SAndroid Build Coastguard Worker   /// Track strings to their index. Index will be UnknownIndex if not yet laid
309*03ce13f7SAndroid Build Coastguard Worker   /// out.
310*03ce13f7SAndroid Build Coastguard Worker   StringToIndexType StringToIndexMap;
311*03ce13f7SAndroid Build Coastguard Worker 
312*03ce13f7SAndroid Build Coastguard Worker   using RawDataType = std::vector<uint8_t>;
313*03ce13f7SAndroid Build Coastguard Worker   RawDataType StringData;
314*03ce13f7SAndroid Build Coastguard Worker };
315*03ce13f7SAndroid Build Coastguard Worker 
writeHeader(ELFStreamer & Str)316*03ce13f7SAndroid Build Coastguard Worker template <bool IsELF64> void ELFSection::writeHeader(ELFStreamer &Str) {
317*03ce13f7SAndroid Build Coastguard Worker   Str.writeELFWord<IsELF64>(Header.sh_name);
318*03ce13f7SAndroid Build Coastguard Worker   Str.writeELFWord<IsELF64>(Header.sh_type);
319*03ce13f7SAndroid Build Coastguard Worker   Str.writeELFXword<IsELF64>(Header.sh_flags);
320*03ce13f7SAndroid Build Coastguard Worker   Str.writeAddrOrOffset<IsELF64>(Header.sh_addr);
321*03ce13f7SAndroid Build Coastguard Worker   Str.writeAddrOrOffset<IsELF64>(Header.sh_offset);
322*03ce13f7SAndroid Build Coastguard Worker   Str.writeELFXword<IsELF64>(Header.sh_size);
323*03ce13f7SAndroid Build Coastguard Worker   Str.writeELFWord<IsELF64>(Header.sh_link);
324*03ce13f7SAndroid Build Coastguard Worker   Str.writeELFWord<IsELF64>(Header.sh_info);
325*03ce13f7SAndroid Build Coastguard Worker   Str.writeELFXword<IsELF64>(Header.sh_addralign);
326*03ce13f7SAndroid Build Coastguard Worker   Str.writeELFXword<IsELF64>(Header.sh_entsize);
327*03ce13f7SAndroid Build Coastguard Worker }
328*03ce13f7SAndroid Build Coastguard Worker 
329*03ce13f7SAndroid Build Coastguard Worker template <bool IsELF64>
writeSymbolMap(ELFStreamer & Str,const SymMap & Map)330*03ce13f7SAndroid Build Coastguard Worker void ELFSymbolTableSection::writeSymbolMap(ELFStreamer &Str,
331*03ce13f7SAndroid Build Coastguard Worker                                            const SymMap &Map) {
332*03ce13f7SAndroid Build Coastguard Worker   // The order of the fields is different, so branch on IsELF64.
333*03ce13f7SAndroid Build Coastguard Worker   if (IsELF64) {
334*03ce13f7SAndroid Build Coastguard Worker     for (auto &KeyValue : Map) {
335*03ce13f7SAndroid Build Coastguard Worker       const Elf64_Sym &SymInfo = KeyValue.second.Sym;
336*03ce13f7SAndroid Build Coastguard Worker       Str.writeELFWord<IsELF64>(SymInfo.st_name);
337*03ce13f7SAndroid Build Coastguard Worker       Str.write8(SymInfo.st_info);
338*03ce13f7SAndroid Build Coastguard Worker       Str.write8(SymInfo.st_other);
339*03ce13f7SAndroid Build Coastguard Worker       Str.writeLE16(SymInfo.st_shndx);
340*03ce13f7SAndroid Build Coastguard Worker       Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value);
341*03ce13f7SAndroid Build Coastguard Worker       Str.writeELFXword<IsELF64>(SymInfo.st_size);
342*03ce13f7SAndroid Build Coastguard Worker     }
343*03ce13f7SAndroid Build Coastguard Worker   } else {
344*03ce13f7SAndroid Build Coastguard Worker     for (auto &KeyValue : Map) {
345*03ce13f7SAndroid Build Coastguard Worker       const Elf64_Sym &SymInfo = KeyValue.second.Sym;
346*03ce13f7SAndroid Build Coastguard Worker       Str.writeELFWord<IsELF64>(SymInfo.st_name);
347*03ce13f7SAndroid Build Coastguard Worker       Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value);
348*03ce13f7SAndroid Build Coastguard Worker       Str.writeELFWord<IsELF64>(SymInfo.st_size);
349*03ce13f7SAndroid Build Coastguard Worker       Str.write8(SymInfo.st_info);
350*03ce13f7SAndroid Build Coastguard Worker       Str.write8(SymInfo.st_other);
351*03ce13f7SAndroid Build Coastguard Worker       Str.writeLE16(SymInfo.st_shndx);
352*03ce13f7SAndroid Build Coastguard Worker     }
353*03ce13f7SAndroid Build Coastguard Worker   }
354*03ce13f7SAndroid Build Coastguard Worker }
355*03ce13f7SAndroid Build Coastguard Worker 
356*03ce13f7SAndroid Build Coastguard Worker template <bool IsELF64>
writeData(ELFStreamer & Str,const ELFSymbolTableSection * SymTab)357*03ce13f7SAndroid Build Coastguard Worker void ELFRelocationSection::writeData(ELFStreamer &Str,
358*03ce13f7SAndroid Build Coastguard Worker                                      const ELFSymbolTableSection *SymTab) {
359*03ce13f7SAndroid Build Coastguard Worker   for (const AssemblerFixup &Fixup : Fixups) {
360*03ce13f7SAndroid Build Coastguard Worker     const ELFSym *Symbol;
361*03ce13f7SAndroid Build Coastguard Worker     if (Fixup.isNullSymbol()) {
362*03ce13f7SAndroid Build Coastguard Worker       Symbol = SymTab->getNullSymbol();
363*03ce13f7SAndroid Build Coastguard Worker     } else if (Fixup.valueIsSymbol()) {
364*03ce13f7SAndroid Build Coastguard Worker       Symbol = Fixup.getSymbolValue();
365*03ce13f7SAndroid Build Coastguard Worker     } else {
366*03ce13f7SAndroid Build Coastguard Worker       GlobalString Name = Fixup.symbol();
367*03ce13f7SAndroid Build Coastguard Worker       Symbol = SymTab->findSymbol(Name);
368*03ce13f7SAndroid Build Coastguard Worker       if (!Symbol)
369*03ce13f7SAndroid Build Coastguard Worker         llvm::report_fatal_error(Name + ": Missing symbol mentioned in reloc");
370*03ce13f7SAndroid Build Coastguard Worker     }
371*03ce13f7SAndroid Build Coastguard Worker 
372*03ce13f7SAndroid Build Coastguard Worker     if (IsELF64) {
373*03ce13f7SAndroid Build Coastguard Worker       Elf64_Rela Rela;
374*03ce13f7SAndroid Build Coastguard Worker       Rela.r_offset = Fixup.position();
375*03ce13f7SAndroid Build Coastguard Worker       Rela.setSymbolAndType(Symbol->getNumber(), Fixup.kind());
376*03ce13f7SAndroid Build Coastguard Worker       Rela.r_addend = Fixup.offset();
377*03ce13f7SAndroid Build Coastguard Worker       Str.writeAddrOrOffset<IsELF64>(Rela.r_offset);
378*03ce13f7SAndroid Build Coastguard Worker       Str.writeELFXword<IsELF64>(Rela.r_info);
379*03ce13f7SAndroid Build Coastguard Worker       Str.writeELFXword<IsELF64>(Rela.r_addend);
380*03ce13f7SAndroid Build Coastguard Worker     } else {
381*03ce13f7SAndroid Build Coastguard Worker       Elf32_Rel Rel;
382*03ce13f7SAndroid Build Coastguard Worker       Rel.r_offset = Fixup.position();
383*03ce13f7SAndroid Build Coastguard Worker       Rel.setSymbolAndType(Symbol->getNumber(), Fixup.kind());
384*03ce13f7SAndroid Build Coastguard Worker       Str.writeAddrOrOffset<IsELF64>(Rel.r_offset);
385*03ce13f7SAndroid Build Coastguard Worker       Str.writeELFWord<IsELF64>(Rel.r_info);
386*03ce13f7SAndroid Build Coastguard Worker     }
387*03ce13f7SAndroid Build Coastguard Worker   }
388*03ce13f7SAndroid Build Coastguard Worker }
389*03ce13f7SAndroid Build Coastguard Worker 
390*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
391*03ce13f7SAndroid Build Coastguard Worker 
392*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEELFSECTION_H
393