blob: cc8e1e5c276d2113fb906106da6d1b42010fed18 [file] [log] [blame]
Jan Voung08c3bcd2014-12-01 17:55:16 -08001//===- 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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Defines how ELF sections are represented.
Andrew Scull9612d322015-07-06 14:53:25 -070012///
Jan Voung08c3bcd2014-12-01 17:55:16 -080013//===----------------------------------------------------------------------===//
14
John Porto67f8de92015-06-25 10:14:17 -070015#include "IceELFSection.h"
Jan Voung72984d82015-01-29 14:42:38 -080016
Jan Voung08c3bcd2014-12-01 17:55:16 -080017#include "IceDefs.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080018#include "IceELFStreamer.h"
John Porto67f8de92015-06-25 10:14:17 -070019#include "llvm/Support/MathExtras.h"
Jan Voung08c3bcd2014-12-01 17:55:16 -080020
21using namespace llvm::ELF;
22
23namespace Ice {
24
25// Text sections.
26
27void 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
35void ELFDataSection::appendData(ELFStreamer &Str,
36 const llvm::StringRef MoreData) {
37 Str.writeBytes(MoreData);
38 Header.sh_size += MoreData.size();
39}
40
Jan Voung72984d82015-01-29 14:42:38 -080041void ELFDataSection::appendZeros(ELFStreamer &Str, SizeT NumBytes) {
42 Str.writeZeroPadding(NumBytes);
43 Header.sh_size += NumBytes;
44}
45
46void ELFDataSection::appendRelocationOffset(ELFStreamer &Str, bool IsRela,
47 RelocOffsetT RelocOffset) {
Nicolas Capens83425de2016-11-01 17:18:51 -040048 const SizeT RelocAddrSize = typeWidthInBytes(getPointerType());
Jan Voung72984d82015-01-29 14:42:38 -080049 if (IsRela) {
50 appendZeros(Str, RelocAddrSize);
51 return;
52 }
Nicolas Capens83425de2016-11-01 17:18:51 -040053 assert(RelocAddrSize == 4 && " writeLE32 assumes RelocAddrSize is 4");
Jan Voung72984d82015-01-29 14:42:38 -080054 Str.writeLE32(RelocOffset);
55 Header.sh_size += RelocAddrSize;
56}
57
58void 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
Jan Voung08c3bcd2014-12-01 17:55:16 -080068// Relocation sections.
69
Jan Voungec270732015-01-12 17:00:22 -080070void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff,
Jim Stichnoth3e324002016-03-08 16:18:40 -080071 const FixupRefList &FixupRefs,
72 ELFSymbolTableSection *SymTab) {
Jan Voungec270732015-01-12 17:00:22 -080073 for (const AssemblerFixup *FR : FixupRefs) {
74 Fixups.push_back(*FR);
75 AssemblerFixup &F = Fixups.back();
76 F.set_position(BaseOff + F.position());
Jim Stichnoth3e324002016-03-08 16:18:40 -080077 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 }
Jan Voungec270732015-01-12 17:00:22 -080089 }
90}
91
Jan Voung261cae32015-02-01 10:31:03 -080092size_t ELFRelocationSection::getSectionDataSize() const {
93 return Fixups.size() * Header.sh_entsize;
Jan Voungec270732015-01-12 17:00:22 -080094}
95
Jan Voung08c3bcd2014-12-01 17:55:16 -080096// Symbol tables.
97
Jim Stichnoth467ffe52016-03-29 15:01:06 -070098void ELFSymbolTableSection::createNullSymbol(ELFSection *NullSection,
99 GlobalContext *Ctx) {
Andrew Scull57e12682015-09-16 11:30:19 -0700100 // The first entry in the symbol table should be a NULL entry, so make sure
101 // the map is still empty.
Jan Voungf644a4b2015-03-19 11:57:52 -0700102 assert(LocalSymbols.empty());
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700103 // 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);
Jan Voungf644a4b2015-03-19 11:57:52 -0700108}
109
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700110void ELFSymbolTableSection::createDefinedSym(GlobalString Name, uint8_t Type,
111 uint8_t Binding,
Jan Voung08c3bcd2014-12-01 17:55:16 -0800112 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;
Jan Voungec270732015-01-12 17:00:22 -0800118 NewSymbol.Section = Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800119 NewSymbol.Number = ELFSym::UnknownNumber;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800120 bool Unique;
Jan Voung72984d82015-01-29 14:42:38 -0800121 if (Binding == STB_LOCAL)
Jan Voungec270732015-01-12 17:00:22 -0800122 Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800123 else
Jan Voungec270732015-01-12 17:00:22 -0800124 Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800125 assert(Unique);
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800126 (void)Unique;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800127}
128
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700129void ELFSymbolTableSection::noteUndefinedSym(GlobalString Name,
Jan Voung08c3bcd2014-12-01 17:55:16 -0800130 ELFSection *NullSection) {
131 ELFSym NewSymbol = ELFSym();
132 NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE);
Jan Voungec270732015-01-12 17:00:22 -0800133 NewSymbol.Section = NullSection;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800134 NewSymbol.Number = ELFSym::UnknownNumber;
Jan Voungf644a4b2015-03-19 11:57:52 -0700135 bool Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700136 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 }
Jan Voungf644a4b2015-03-19 11:57:52 -0700142 (void)Unique;
Jan Voungec270732015-01-12 17:00:22 -0800143}
144
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700145const ELFSym *ELFSymbolTableSection::findSymbol(GlobalString Name) const {
Jan Voungec270732015-01-12 17:00:22 -0800146 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;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800153}
154
155void ELFSymbolTableSection::updateIndices(const ELFStringTableSection *StrTab) {
156 SizeT SymNumber = 0;
157 for (auto &KeyValue : LocalSymbols) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700158 GlobalString Name = KeyValue.first;
Jan Voungec270732015-01-12 17:00:22 -0800159 ELFSection *Section = KeyValue.second.Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800160 Elf64_Sym &SymInfo = KeyValue.second.Sym;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700161 if (Name != NullSymbolName && Name.hasStdString())
162 SymInfo.st_name = StrTab->getIndex(Name.toString());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800163 SymInfo.st_shndx = Section->getNumber();
164 KeyValue.second.setNumber(SymNumber++);
165 }
166 for (auto &KeyValue : GlobalSymbols) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700167 const std::string &Name = KeyValue.first.toString();
Jan Voungec270732015-01-12 17:00:22 -0800168 ELFSection *Section = KeyValue.second.Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800169 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
177void 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
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700189void ELFStringTableSection::add(const std::string &Str) {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800190 assert(!isLaidOut());
191 assert(!Str.empty());
192 StringToIndexMap.insert(std::make_pair(Str, UnknownIndex));
193}
194
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700195size_t ELFStringTableSection::getIndex(const std::string &Str) const {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800196 assert(isLaidOut());
197 StringToIndexType::const_iterator It = StringToIndexMap.find(Str);
198 if (It == StringToIndexMap.end()) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700199 llvm::report_fatal_error("String index not found: " + Str);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800200 return UnknownIndex;
201 }
202 return It->second;
203}
204
205bool ELFStringTableSection::SuffixComparator::
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700206operator()(const std::string &StrA, const std::string &StrB) const {
Jan Voung08c3bcd2014-12-01 17:55:16 -0800207 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
222void 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)) {
Andrew Scull57e12682015-09-16 11:30:19 -0700233 // Prev is already in the StringData, and Cur is shorter than Prev based
234 // on the sort.
Jan Voung08c3bcd2014-12-01 17:55:16 -0800235 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