xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceELFSection.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceELFSection.cpp - Representation of ELF sections -----===//
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 how ELF sections are represented.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "IceELFSection.h"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
18*03ce13f7SAndroid Build Coastguard Worker #include "IceELFStreamer.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
20*03ce13f7SAndroid Build Coastguard Worker 
21*03ce13f7SAndroid Build Coastguard Worker using namespace llvm::ELF;
22*03ce13f7SAndroid Build Coastguard Worker 
23*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker // Text sections.
26*03ce13f7SAndroid Build Coastguard Worker 
appendData(ELFStreamer & Str,const llvm::StringRef MoreData)27*03ce13f7SAndroid Build Coastguard Worker void ELFTextSection::appendData(ELFStreamer &Str,
28*03ce13f7SAndroid Build Coastguard Worker                                 const llvm::StringRef MoreData) {
29*03ce13f7SAndroid Build Coastguard Worker   Str.writeBytes(MoreData);
30*03ce13f7SAndroid Build Coastguard Worker   Header.sh_size += MoreData.size();
31*03ce13f7SAndroid Build Coastguard Worker }
32*03ce13f7SAndroid Build Coastguard Worker 
33*03ce13f7SAndroid Build Coastguard Worker // Data sections.
34*03ce13f7SAndroid Build Coastguard Worker 
appendData(ELFStreamer & Str,const llvm::StringRef MoreData)35*03ce13f7SAndroid Build Coastguard Worker void ELFDataSection::appendData(ELFStreamer &Str,
36*03ce13f7SAndroid Build Coastguard Worker                                 const llvm::StringRef MoreData) {
37*03ce13f7SAndroid Build Coastguard Worker   Str.writeBytes(MoreData);
38*03ce13f7SAndroid Build Coastguard Worker   Header.sh_size += MoreData.size();
39*03ce13f7SAndroid Build Coastguard Worker }
40*03ce13f7SAndroid Build Coastguard Worker 
appendZeros(ELFStreamer & Str,SizeT NumBytes)41*03ce13f7SAndroid Build Coastguard Worker void ELFDataSection::appendZeros(ELFStreamer &Str, SizeT NumBytes) {
42*03ce13f7SAndroid Build Coastguard Worker   Str.writeZeroPadding(NumBytes);
43*03ce13f7SAndroid Build Coastguard Worker   Header.sh_size += NumBytes;
44*03ce13f7SAndroid Build Coastguard Worker }
45*03ce13f7SAndroid Build Coastguard Worker 
appendRelocationOffset(ELFStreamer & Str,bool IsRela,RelocOffsetT RelocOffset)46*03ce13f7SAndroid Build Coastguard Worker void ELFDataSection::appendRelocationOffset(ELFStreamer &Str, bool IsRela,
47*03ce13f7SAndroid Build Coastguard Worker                                             RelocOffsetT RelocOffset) {
48*03ce13f7SAndroid Build Coastguard Worker   const SizeT RelocAddrSize = typeWidthInBytes(getPointerType());
49*03ce13f7SAndroid Build Coastguard Worker   if (IsRela) {
50*03ce13f7SAndroid Build Coastguard Worker     appendZeros(Str, RelocAddrSize);
51*03ce13f7SAndroid Build Coastguard Worker     return;
52*03ce13f7SAndroid Build Coastguard Worker   }
53*03ce13f7SAndroid Build Coastguard Worker   assert(RelocAddrSize == 4 && " writeLE32 assumes RelocAddrSize is 4");
54*03ce13f7SAndroid Build Coastguard Worker   Str.writeLE32(RelocOffset);
55*03ce13f7SAndroid Build Coastguard Worker   Header.sh_size += RelocAddrSize;
56*03ce13f7SAndroid Build Coastguard Worker }
57*03ce13f7SAndroid Build Coastguard Worker 
padToAlignment(ELFStreamer & Str,Elf64_Xword Align)58*03ce13f7SAndroid Build Coastguard Worker void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) {
59*03ce13f7SAndroid Build Coastguard Worker   assert(llvm::isPowerOf2_32(Align));
60*03ce13f7SAndroid Build Coastguard Worker   Elf64_Xword AlignDiff = Utils::OffsetToAlignment(Header.sh_size, Align);
61*03ce13f7SAndroid Build Coastguard Worker   if (AlignDiff == 0)
62*03ce13f7SAndroid Build Coastguard Worker     return;
63*03ce13f7SAndroid Build Coastguard Worker   if (Header.sh_type != llvm::ELF::SHT_NOBITS)
64*03ce13f7SAndroid Build Coastguard Worker     Str.writeZeroPadding(AlignDiff);
65*03ce13f7SAndroid Build Coastguard Worker   Header.sh_size += AlignDiff;
66*03ce13f7SAndroid Build Coastguard Worker }
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker // Relocation sections.
69*03ce13f7SAndroid Build Coastguard Worker 
addRelocations(RelocOffsetT BaseOff,const FixupRefList & FixupRefs,ELFSymbolTableSection * SymTab)70*03ce13f7SAndroid Build Coastguard Worker void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff,
71*03ce13f7SAndroid Build Coastguard Worker                                           const FixupRefList &FixupRefs,
72*03ce13f7SAndroid Build Coastguard Worker                                           ELFSymbolTableSection *SymTab) {
73*03ce13f7SAndroid Build Coastguard Worker   for (const AssemblerFixup *FR : FixupRefs) {
74*03ce13f7SAndroid Build Coastguard Worker     Fixups.push_back(*FR);
75*03ce13f7SAndroid Build Coastguard Worker     AssemblerFixup &F = Fixups.back();
76*03ce13f7SAndroid Build Coastguard Worker     F.set_position(BaseOff + F.position());
77*03ce13f7SAndroid Build Coastguard Worker     assert(!F.valueIsSymbol());
78*03ce13f7SAndroid Build Coastguard Worker     if (!F.isNullSymbol()) {
79*03ce13f7SAndroid Build Coastguard Worker       // Do an early lookup in the symbol table.  If the symbol is found,
80*03ce13f7SAndroid Build Coastguard Worker       // replace the Constant in the symbol with the ELFSym, and calculate the
81*03ce13f7SAndroid Build Coastguard Worker       // final value of the addend.  As such, a local label allocated from the
82*03ce13f7SAndroid Build Coastguard Worker       // Assembler arena will be converted to a symbol before the Assembler
83*03ce13f7SAndroid Build Coastguard Worker       // arena goes away.
84*03ce13f7SAndroid Build Coastguard Worker       if (const ELFSym *Sym = SymTab->findSymbol(F.symbol())) {
85*03ce13f7SAndroid Build Coastguard Worker         F.set_addend(F.offset());
86*03ce13f7SAndroid Build Coastguard Worker         F.set_value(Sym);
87*03ce13f7SAndroid Build Coastguard Worker       }
88*03ce13f7SAndroid Build Coastguard Worker     }
89*03ce13f7SAndroid Build Coastguard Worker   }
90*03ce13f7SAndroid Build Coastguard Worker }
91*03ce13f7SAndroid Build Coastguard Worker 
getSectionDataSize() const92*03ce13f7SAndroid Build Coastguard Worker size_t ELFRelocationSection::getSectionDataSize() const {
93*03ce13f7SAndroid Build Coastguard Worker   return Fixups.size() * Header.sh_entsize;
94*03ce13f7SAndroid Build Coastguard Worker }
95*03ce13f7SAndroid Build Coastguard Worker 
96*03ce13f7SAndroid Build Coastguard Worker // Symbol tables.
97*03ce13f7SAndroid Build Coastguard Worker 
createNullSymbol(ELFSection * NullSection,GlobalContext * Ctx)98*03ce13f7SAndroid Build Coastguard Worker void ELFSymbolTableSection::createNullSymbol(ELFSection *NullSection,
99*03ce13f7SAndroid Build Coastguard Worker                                              GlobalContext *Ctx) {
100*03ce13f7SAndroid Build Coastguard Worker   // The first entry in the symbol table should be a NULL entry, so make sure
101*03ce13f7SAndroid Build Coastguard Worker   // the map is still empty.
102*03ce13f7SAndroid Build Coastguard Worker   assert(LocalSymbols.empty());
103*03ce13f7SAndroid Build Coastguard Worker   // Explicitly set the null symbol name to the empty string, so that
104*03ce13f7SAndroid Build Coastguard Worker   // GlobalString::operator<() orders the null string first.
105*03ce13f7SAndroid Build Coastguard Worker   NullSymbolName = GlobalString::createWithString(Ctx, "");
106*03ce13f7SAndroid Build Coastguard Worker   createDefinedSym(NullSymbolName, STT_NOTYPE, STB_LOCAL, NullSection, 0, 0);
107*03ce13f7SAndroid Build Coastguard Worker   NullSymbol = findSymbol(NullSymbolName);
108*03ce13f7SAndroid Build Coastguard Worker }
109*03ce13f7SAndroid Build Coastguard Worker 
createDefinedSym(GlobalString Name,uint8_t Type,uint8_t Binding,ELFSection * Section,RelocOffsetT Offset,SizeT Size)110*03ce13f7SAndroid Build Coastguard Worker void ELFSymbolTableSection::createDefinedSym(GlobalString Name, uint8_t Type,
111*03ce13f7SAndroid Build Coastguard Worker                                              uint8_t Binding,
112*03ce13f7SAndroid Build Coastguard Worker                                              ELFSection *Section,
113*03ce13f7SAndroid Build Coastguard Worker                                              RelocOffsetT Offset, SizeT Size) {
114*03ce13f7SAndroid Build Coastguard Worker   ELFSym NewSymbol = ELFSym();
115*03ce13f7SAndroid Build Coastguard Worker   NewSymbol.Sym.setBindingAndType(Binding, Type);
116*03ce13f7SAndroid Build Coastguard Worker   NewSymbol.Sym.st_value = Offset;
117*03ce13f7SAndroid Build Coastguard Worker   NewSymbol.Sym.st_size = Size;
118*03ce13f7SAndroid Build Coastguard Worker   NewSymbol.Section = Section;
119*03ce13f7SAndroid Build Coastguard Worker   NewSymbol.Number = ELFSym::UnknownNumber;
120*03ce13f7SAndroid Build Coastguard Worker   bool Unique;
121*03ce13f7SAndroid Build Coastguard Worker   if (Binding == STB_LOCAL)
122*03ce13f7SAndroid Build Coastguard Worker     Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
123*03ce13f7SAndroid Build Coastguard Worker   else
124*03ce13f7SAndroid Build Coastguard Worker     Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
125*03ce13f7SAndroid Build Coastguard Worker   assert(Unique);
126*03ce13f7SAndroid Build Coastguard Worker   (void)Unique;
127*03ce13f7SAndroid Build Coastguard Worker }
128*03ce13f7SAndroid Build Coastguard Worker 
noteUndefinedSym(GlobalString Name,ELFSection * NullSection)129*03ce13f7SAndroid Build Coastguard Worker void ELFSymbolTableSection::noteUndefinedSym(GlobalString Name,
130*03ce13f7SAndroid Build Coastguard Worker                                              ELFSection *NullSection) {
131*03ce13f7SAndroid Build Coastguard Worker   ELFSym NewSymbol = ELFSym();
132*03ce13f7SAndroid Build Coastguard Worker   NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE);
133*03ce13f7SAndroid Build Coastguard Worker   NewSymbol.Section = NullSection;
134*03ce13f7SAndroid Build Coastguard Worker   NewSymbol.Number = ELFSym::UnknownNumber;
135*03ce13f7SAndroid Build Coastguard Worker   bool Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
136*03ce13f7SAndroid Build Coastguard Worker   if (!Unique) {
137*03ce13f7SAndroid Build Coastguard Worker     std::string Buffer;
138*03ce13f7SAndroid Build Coastguard Worker     llvm::raw_string_ostream StrBuf(Buffer);
139*03ce13f7SAndroid Build Coastguard Worker     StrBuf << "Symbol external and defined: " << Name;
140*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error(StrBuf.str());
141*03ce13f7SAndroid Build Coastguard Worker   }
142*03ce13f7SAndroid Build Coastguard Worker   (void)Unique;
143*03ce13f7SAndroid Build Coastguard Worker }
144*03ce13f7SAndroid Build Coastguard Worker 
findSymbol(GlobalString Name) const145*03ce13f7SAndroid Build Coastguard Worker const ELFSym *ELFSymbolTableSection::findSymbol(GlobalString Name) const {
146*03ce13f7SAndroid Build Coastguard Worker   auto I = LocalSymbols.find(Name);
147*03ce13f7SAndroid Build Coastguard Worker   if (I != LocalSymbols.end())
148*03ce13f7SAndroid Build Coastguard Worker     return &I->second;
149*03ce13f7SAndroid Build Coastguard Worker   I = GlobalSymbols.find(Name);
150*03ce13f7SAndroid Build Coastguard Worker   if (I != GlobalSymbols.end())
151*03ce13f7SAndroid Build Coastguard Worker     return &I->second;
152*03ce13f7SAndroid Build Coastguard Worker   return nullptr;
153*03ce13f7SAndroid Build Coastguard Worker }
154*03ce13f7SAndroid Build Coastguard Worker 
updateIndices(const ELFStringTableSection * StrTab)155*03ce13f7SAndroid Build Coastguard Worker void ELFSymbolTableSection::updateIndices(const ELFStringTableSection *StrTab) {
156*03ce13f7SAndroid Build Coastguard Worker   SizeT SymNumber = 0;
157*03ce13f7SAndroid Build Coastguard Worker   for (auto &KeyValue : LocalSymbols) {
158*03ce13f7SAndroid Build Coastguard Worker     GlobalString Name = KeyValue.first;
159*03ce13f7SAndroid Build Coastguard Worker     ELFSection *Section = KeyValue.second.Section;
160*03ce13f7SAndroid Build Coastguard Worker     Elf64_Sym &SymInfo = KeyValue.second.Sym;
161*03ce13f7SAndroid Build Coastguard Worker     if (Name != NullSymbolName && Name.hasStdString())
162*03ce13f7SAndroid Build Coastguard Worker       SymInfo.st_name = StrTab->getIndex(Name.toString());
163*03ce13f7SAndroid Build Coastguard Worker     SymInfo.st_shndx = Section->getNumber();
164*03ce13f7SAndroid Build Coastguard Worker     KeyValue.second.setNumber(SymNumber++);
165*03ce13f7SAndroid Build Coastguard Worker   }
166*03ce13f7SAndroid Build Coastguard Worker   for (auto &KeyValue : GlobalSymbols) {
167*03ce13f7SAndroid Build Coastguard Worker     const std::string &Name = KeyValue.first.toString();
168*03ce13f7SAndroid Build Coastguard Worker     ELFSection *Section = KeyValue.second.Section;
169*03ce13f7SAndroid Build Coastguard Worker     Elf64_Sym &SymInfo = KeyValue.second.Sym;
170*03ce13f7SAndroid Build Coastguard Worker     if (!Name.empty())
171*03ce13f7SAndroid Build Coastguard Worker       SymInfo.st_name = StrTab->getIndex(Name);
172*03ce13f7SAndroid Build Coastguard Worker     SymInfo.st_shndx = Section->getNumber();
173*03ce13f7SAndroid Build Coastguard Worker     KeyValue.second.setNumber(SymNumber++);
174*03ce13f7SAndroid Build Coastguard Worker   }
175*03ce13f7SAndroid Build Coastguard Worker }
176*03ce13f7SAndroid Build Coastguard Worker 
writeData(ELFStreamer & Str,bool IsELF64)177*03ce13f7SAndroid Build Coastguard Worker void ELFSymbolTableSection::writeData(ELFStreamer &Str, bool IsELF64) {
178*03ce13f7SAndroid Build Coastguard Worker   if (IsELF64) {
179*03ce13f7SAndroid Build Coastguard Worker     writeSymbolMap<true>(Str, LocalSymbols);
180*03ce13f7SAndroid Build Coastguard Worker     writeSymbolMap<true>(Str, GlobalSymbols);
181*03ce13f7SAndroid Build Coastguard Worker   } else {
182*03ce13f7SAndroid Build Coastguard Worker     writeSymbolMap<false>(Str, LocalSymbols);
183*03ce13f7SAndroid Build Coastguard Worker     writeSymbolMap<false>(Str, GlobalSymbols);
184*03ce13f7SAndroid Build Coastguard Worker   }
185*03ce13f7SAndroid Build Coastguard Worker }
186*03ce13f7SAndroid Build Coastguard Worker 
187*03ce13f7SAndroid Build Coastguard Worker // String tables.
188*03ce13f7SAndroid Build Coastguard Worker 
add(const std::string & Str)189*03ce13f7SAndroid Build Coastguard Worker void ELFStringTableSection::add(const std::string &Str) {
190*03ce13f7SAndroid Build Coastguard Worker   assert(!isLaidOut());
191*03ce13f7SAndroid Build Coastguard Worker   assert(!Str.empty());
192*03ce13f7SAndroid Build Coastguard Worker   StringToIndexMap.insert(std::make_pair(Str, UnknownIndex));
193*03ce13f7SAndroid Build Coastguard Worker }
194*03ce13f7SAndroid Build Coastguard Worker 
getIndex(const std::string & Str) const195*03ce13f7SAndroid Build Coastguard Worker size_t ELFStringTableSection::getIndex(const std::string &Str) const {
196*03ce13f7SAndroid Build Coastguard Worker   assert(isLaidOut());
197*03ce13f7SAndroid Build Coastguard Worker   StringToIndexType::const_iterator It = StringToIndexMap.find(Str);
198*03ce13f7SAndroid Build Coastguard Worker   if (It == StringToIndexMap.end()) {
199*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("String index not found: " + Str);
200*03ce13f7SAndroid Build Coastguard Worker     return UnknownIndex;
201*03ce13f7SAndroid Build Coastguard Worker   }
202*03ce13f7SAndroid Build Coastguard Worker   return It->second;
203*03ce13f7SAndroid Build Coastguard Worker }
204*03ce13f7SAndroid Build Coastguard Worker 
operator ()(const std::string & StrA,const std::string & StrB) const205*03ce13f7SAndroid Build Coastguard Worker bool ELFStringTableSection::SuffixComparator::operator()(
206*03ce13f7SAndroid Build Coastguard Worker     const std::string &StrA, const std::string &StrB) const {
207*03ce13f7SAndroid Build Coastguard Worker   size_t LenA = StrA.size();
208*03ce13f7SAndroid Build Coastguard Worker   size_t LenB = StrB.size();
209*03ce13f7SAndroid Build Coastguard Worker   size_t CommonLen = std::min(LenA, LenB);
210*03ce13f7SAndroid Build Coastguard Worker   // If there is a difference in the common suffix, use that diff to sort.
211*03ce13f7SAndroid Build Coastguard Worker   for (size_t i = 0; i < CommonLen; ++i) {
212*03ce13f7SAndroid Build Coastguard Worker     char a = StrA[LenA - i - 1];
213*03ce13f7SAndroid Build Coastguard Worker     char b = StrB[LenB - i - 1];
214*03ce13f7SAndroid Build Coastguard Worker     if (a != b)
215*03ce13f7SAndroid Build Coastguard Worker       return a > b;
216*03ce13f7SAndroid Build Coastguard Worker   }
217*03ce13f7SAndroid Build Coastguard Worker   // If the common suffixes are completely equal, let the longer one come
218*03ce13f7SAndroid Build Coastguard Worker   // first, so that it can be laid out first and its characters shared.
219*03ce13f7SAndroid Build Coastguard Worker   return LenA > LenB;
220*03ce13f7SAndroid Build Coastguard Worker }
221*03ce13f7SAndroid Build Coastguard Worker 
doLayout()222*03ce13f7SAndroid Build Coastguard Worker void ELFStringTableSection::doLayout() {
223*03ce13f7SAndroid Build Coastguard Worker   assert(!isLaidOut());
224*03ce13f7SAndroid Build Coastguard Worker   llvm::StringRef Prev;
225*03ce13f7SAndroid Build Coastguard Worker 
226*03ce13f7SAndroid Build Coastguard Worker   // String table starts with 0 byte.
227*03ce13f7SAndroid Build Coastguard Worker   StringData.push_back(0);
228*03ce13f7SAndroid Build Coastguard Worker 
229*03ce13f7SAndroid Build Coastguard Worker   for (auto &StringIndex : StringToIndexMap) {
230*03ce13f7SAndroid Build Coastguard Worker     assert(StringIndex.second == UnknownIndex);
231*03ce13f7SAndroid Build Coastguard Worker     llvm::StringRef Cur = llvm::StringRef(StringIndex.first);
232*03ce13f7SAndroid Build Coastguard Worker     if (Prev.endswith(Cur)) {
233*03ce13f7SAndroid Build Coastguard Worker       // Prev is already in the StringData, and Cur is shorter than Prev based
234*03ce13f7SAndroid Build Coastguard Worker       // on the sort.
235*03ce13f7SAndroid Build Coastguard Worker       StringIndex.second = StringData.size() - Cur.size() - 1;
236*03ce13f7SAndroid Build Coastguard Worker       continue;
237*03ce13f7SAndroid Build Coastguard Worker     }
238*03ce13f7SAndroid Build Coastguard Worker     StringIndex.second = StringData.size();
239*03ce13f7SAndroid Build Coastguard Worker     std::copy(Cur.begin(), Cur.end(), back_inserter(StringData));
240*03ce13f7SAndroid Build Coastguard Worker     StringData.push_back(0);
241*03ce13f7SAndroid Build Coastguard Worker     Prev = Cur;
242*03ce13f7SAndroid Build Coastguard Worker   }
243*03ce13f7SAndroid Build Coastguard Worker }
244*03ce13f7SAndroid Build Coastguard Worker 
245*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
246