blob: 4ca2de470950c095065fd4cf677d47c71da6b3e0 [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//===----------------------------------------------------------------------===//
9//
10// This file defines how ELF sections are represented.
11//
12//===----------------------------------------------------------------------===//
13
Jan Voung72984d82015-01-29 14:42:38 -080014#include "llvm/Support/MathExtras.h"
15
Jan Voung08c3bcd2014-12-01 17:55:16 -080016#include "IceDefs.h"
17#include "IceELFSection.h"
18#include "IceELFStreamer.h"
19
20using namespace llvm::ELF;
21
22namespace Ice {
23
24// Text sections.
25
26void ELFTextSection::appendData(ELFStreamer &Str,
27 const llvm::StringRef MoreData) {
28 Str.writeBytes(MoreData);
29 Header.sh_size += MoreData.size();
30}
31
32// Data sections.
33
34void ELFDataSection::appendData(ELFStreamer &Str,
35 const llvm::StringRef MoreData) {
36 Str.writeBytes(MoreData);
37 Header.sh_size += MoreData.size();
38}
39
Jan Voung72984d82015-01-29 14:42:38 -080040void ELFDataSection::appendZeros(ELFStreamer &Str, SizeT NumBytes) {
41 Str.writeZeroPadding(NumBytes);
42 Header.sh_size += NumBytes;
43}
44
45void ELFDataSection::appendRelocationOffset(ELFStreamer &Str, bool IsRela,
46 RelocOffsetT RelocOffset) {
47 if (IsRela) {
48 appendZeros(Str, RelocAddrSize);
49 return;
50 }
51 static_assert(RelocAddrSize == 4, " writeLE32 assumes RelocAddrSize is 4");
52 Str.writeLE32(RelocOffset);
53 Header.sh_size += RelocAddrSize;
54}
55
56void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) {
57 assert(llvm::isPowerOf2_32(Align));
58 Elf64_Xword AlignDiff = Utils::OffsetToAlignment(Header.sh_size, Align);
59 if (AlignDiff == 0)
60 return;
61 if (Header.sh_type != llvm::ELF::SHT_NOBITS)
62 Str.writeZeroPadding(AlignDiff);
63 Header.sh_size += AlignDiff;
64}
65
Jan Voung08c3bcd2014-12-01 17:55:16 -080066// Relocation sections.
67
Jan Voungec270732015-01-12 17:00:22 -080068void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff,
69 const FixupRefList &FixupRefs) {
70 for (const AssemblerFixup *FR : FixupRefs) {
71 Fixups.push_back(*FR);
72 AssemblerFixup &F = Fixups.back();
73 F.set_position(BaseOff + F.position());
74 }
75}
76
Jan Voung261cae32015-02-01 10:31:03 -080077size_t ELFRelocationSection::getSectionDataSize() const {
78 return Fixups.size() * Header.sh_entsize;
Jan Voungec270732015-01-12 17:00:22 -080079}
80
Jan Voung08c3bcd2014-12-01 17:55:16 -080081// Symbol tables.
82
Jan Voungf644a4b2015-03-19 11:57:52 -070083void ELFSymbolTableSection::createNullSymbol(ELFSection *NullSection) {
84 // The first entry in the symbol table should be a NULL entry,
85 // so make sure the map is still empty.
86 assert(LocalSymbols.empty());
87 const IceString NullSymName("");
88 createDefinedSym(NullSymName, STT_NOTYPE, STB_LOCAL, NullSection, 0, 0);
89 NullSymbol = findSymbol(NullSymName);
90}
91
Jan Voung08c3bcd2014-12-01 17:55:16 -080092void ELFSymbolTableSection::createDefinedSym(const IceString &Name,
93 uint8_t Type, uint8_t Binding,
94 ELFSection *Section,
95 RelocOffsetT Offset, SizeT Size) {
96 ELFSym NewSymbol = ELFSym();
97 NewSymbol.Sym.setBindingAndType(Binding, Type);
98 NewSymbol.Sym.st_value = Offset;
99 NewSymbol.Sym.st_size = Size;
Jan Voungec270732015-01-12 17:00:22 -0800100 NewSymbol.Section = Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800101 NewSymbol.Number = ELFSym::UnknownNumber;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800102 bool Unique;
Jan Voung72984d82015-01-29 14:42:38 -0800103 if (Binding == STB_LOCAL)
Jan Voungec270732015-01-12 17:00:22 -0800104 Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800105 else
Jan Voungec270732015-01-12 17:00:22 -0800106 Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800107 assert(Unique);
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800108 (void)Unique;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800109}
110
111void ELFSymbolTableSection::noteUndefinedSym(const IceString &Name,
112 ELFSection *NullSection) {
113 ELFSym NewSymbol = ELFSym();
114 NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE);
Jan Voungec270732015-01-12 17:00:22 -0800115 NewSymbol.Section = NullSection;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800116 NewSymbol.Number = ELFSym::UnknownNumber;
Jan Voungf644a4b2015-03-19 11:57:52 -0700117 bool Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
118 assert(Unique);
119 (void)Unique;
Jan Voungec270732015-01-12 17:00:22 -0800120}
121
122const ELFSym *ELFSymbolTableSection::findSymbol(const IceString &Name) const {
123 auto I = LocalSymbols.find(Name);
124 if (I != LocalSymbols.end())
125 return &I->second;
126 I = GlobalSymbols.find(Name);
127 if (I != GlobalSymbols.end())
128 return &I->second;
129 return nullptr;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800130}
131
132void ELFSymbolTableSection::updateIndices(const ELFStringTableSection *StrTab) {
133 SizeT SymNumber = 0;
134 for (auto &KeyValue : LocalSymbols) {
Jan Voungec270732015-01-12 17:00:22 -0800135 const IceString &Name = KeyValue.first;
136 ELFSection *Section = KeyValue.second.Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800137 Elf64_Sym &SymInfo = KeyValue.second.Sym;
138 if (!Name.empty())
139 SymInfo.st_name = StrTab->getIndex(Name);
140 SymInfo.st_shndx = Section->getNumber();
141 KeyValue.second.setNumber(SymNumber++);
142 }
143 for (auto &KeyValue : GlobalSymbols) {
Jan Voungec270732015-01-12 17:00:22 -0800144 const IceString &Name = KeyValue.first;
145 ELFSection *Section = KeyValue.second.Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800146 Elf64_Sym &SymInfo = KeyValue.second.Sym;
147 if (!Name.empty())
148 SymInfo.st_name = StrTab->getIndex(Name);
149 SymInfo.st_shndx = Section->getNumber();
150 KeyValue.second.setNumber(SymNumber++);
151 }
152}
153
154void ELFSymbolTableSection::writeData(ELFStreamer &Str, bool IsELF64) {
155 if (IsELF64) {
156 writeSymbolMap<true>(Str, LocalSymbols);
157 writeSymbolMap<true>(Str, GlobalSymbols);
158 } else {
159 writeSymbolMap<false>(Str, LocalSymbols);
160 writeSymbolMap<false>(Str, GlobalSymbols);
161 }
162}
163
164// String tables.
165
166void ELFStringTableSection::add(const IceString &Str) {
167 assert(!isLaidOut());
168 assert(!Str.empty());
169 StringToIndexMap.insert(std::make_pair(Str, UnknownIndex));
170}
171
172size_t ELFStringTableSection::getIndex(const IceString &Str) const {
173 assert(isLaidOut());
174 StringToIndexType::const_iterator It = StringToIndexMap.find(Str);
175 if (It == StringToIndexMap.end()) {
176 llvm_unreachable("String index not found");
177 return UnknownIndex;
178 }
179 return It->second;
180}
181
182bool ELFStringTableSection::SuffixComparator::
183operator()(const IceString &StrA, const IceString &StrB) const {
184 size_t LenA = StrA.size();
185 size_t LenB = StrB.size();
186 size_t CommonLen = std::min(LenA, LenB);
187 // If there is a difference in the common suffix, use that diff to sort.
188 for (size_t i = 0; i < CommonLen; ++i) {
189 char a = StrA[LenA - i - 1];
190 char b = StrB[LenB - i - 1];
191 if (a != b)
192 return a > b;
193 }
194 // If the common suffixes are completely equal, let the longer one come
195 // first, so that it can be laid out first and its characters shared.
196 return LenA > LenB;
197}
198
199void ELFStringTableSection::doLayout() {
200 assert(!isLaidOut());
201 llvm::StringRef Prev;
202
203 // String table starts with 0 byte.
204 StringData.push_back(0);
205
206 for (auto &StringIndex : StringToIndexMap) {
207 assert(StringIndex.second == UnknownIndex);
208 llvm::StringRef Cur = llvm::StringRef(StringIndex.first);
209 if (Prev.endswith(Cur)) {
210 // Prev is already in the StringData, and Cur is shorter than Prev
211 // based on the sort.
212 StringIndex.second = StringData.size() - Cur.size() - 1;
213 continue;
214 }
215 StringIndex.second = StringData.size();
216 std::copy(Cur.begin(), Cur.end(), back_inserter(StringData));
217 StringData.push_back(0);
218 Prev = Cur;
219 }
220}
221
222} // end of namespace Ice