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