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
205 bool ELFStringTableSection::SuffixComparator::
operator ()(const std::string & StrA,const std::string & StrB) const206 operator()(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