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