blob: 7893354b55e4b96c1ac02fd533d526446bd75cd2 [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
11/// This file defines how ELF sections are represented.
12///
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) {
48 if (IsRela) {
49 appendZeros(Str, RelocAddrSize);
50 return;
51 }
52 static_assert(RelocAddrSize == 4, " writeLE32 assumes RelocAddrSize is 4");
53 Str.writeLE32(RelocOffset);
54 Header.sh_size += RelocAddrSize;
55}
56
57void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) {
58 assert(llvm::isPowerOf2_32(Align));
59 Elf64_Xword AlignDiff = Utils::OffsetToAlignment(Header.sh_size, Align);
60 if (AlignDiff == 0)
61 return;
62 if (Header.sh_type != llvm::ELF::SHT_NOBITS)
63 Str.writeZeroPadding(AlignDiff);
64 Header.sh_size += AlignDiff;
65}
66
Jan Voung08c3bcd2014-12-01 17:55:16 -080067// Relocation sections.
68
Jan Voungec270732015-01-12 17:00:22 -080069void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff,
70 const FixupRefList &FixupRefs) {
71 for (const AssemblerFixup *FR : FixupRefs) {
72 Fixups.push_back(*FR);
73 AssemblerFixup &F = Fixups.back();
74 F.set_position(BaseOff + F.position());
75 }
76}
77
Jan Voung261cae32015-02-01 10:31:03 -080078size_t ELFRelocationSection::getSectionDataSize() const {
79 return Fixups.size() * Header.sh_entsize;
Jan Voungec270732015-01-12 17:00:22 -080080}
81
Jan Voung08c3bcd2014-12-01 17:55:16 -080082// Symbol tables.
83
Jan Voungf644a4b2015-03-19 11:57:52 -070084void ELFSymbolTableSection::createNullSymbol(ELFSection *NullSection) {
85 // The first entry in the symbol table should be a NULL entry,
86 // so make sure the map is still empty.
87 assert(LocalSymbols.empty());
88 const IceString NullSymName("");
89 createDefinedSym(NullSymName, STT_NOTYPE, STB_LOCAL, NullSection, 0, 0);
90 NullSymbol = findSymbol(NullSymName);
91}
92
Jan Voung08c3bcd2014-12-01 17:55:16 -080093void ELFSymbolTableSection::createDefinedSym(const IceString &Name,
94 uint8_t Type, uint8_t Binding,
95 ELFSection *Section,
96 RelocOffsetT Offset, SizeT Size) {
97 ELFSym NewSymbol = ELFSym();
98 NewSymbol.Sym.setBindingAndType(Binding, Type);
99 NewSymbol.Sym.st_value = Offset;
100 NewSymbol.Sym.st_size = Size;
Jan Voungec270732015-01-12 17:00:22 -0800101 NewSymbol.Section = Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800102 NewSymbol.Number = ELFSym::UnknownNumber;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800103 bool Unique;
Jan Voung72984d82015-01-29 14:42:38 -0800104 if (Binding == STB_LOCAL)
Jan Voungec270732015-01-12 17:00:22 -0800105 Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800106 else
Jan Voungec270732015-01-12 17:00:22 -0800107 Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800108 assert(Unique);
Jim Stichnothdddaf9c2014-12-04 14:09:21 -0800109 (void)Unique;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800110}
111
112void ELFSymbolTableSection::noteUndefinedSym(const IceString &Name,
113 ELFSection *NullSection) {
114 ELFSym NewSymbol = ELFSym();
115 NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE);
Jan Voungec270732015-01-12 17:00:22 -0800116 NewSymbol.Section = NullSection;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800117 NewSymbol.Number = ELFSym::UnknownNumber;
Jan Voungf644a4b2015-03-19 11:57:52 -0700118 bool Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
119 assert(Unique);
120 (void)Unique;
Jan Voungec270732015-01-12 17:00:22 -0800121}
122
123const ELFSym *ELFSymbolTableSection::findSymbol(const IceString &Name) const {
124 auto I = LocalSymbols.find(Name);
125 if (I != LocalSymbols.end())
126 return &I->second;
127 I = GlobalSymbols.find(Name);
128 if (I != GlobalSymbols.end())
129 return &I->second;
130 return nullptr;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800131}
132
133void ELFSymbolTableSection::updateIndices(const ELFStringTableSection *StrTab) {
134 SizeT SymNumber = 0;
135 for (auto &KeyValue : LocalSymbols) {
Jan Voungec270732015-01-12 17:00:22 -0800136 const IceString &Name = KeyValue.first;
137 ELFSection *Section = KeyValue.second.Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800138 Elf64_Sym &SymInfo = KeyValue.second.Sym;
139 if (!Name.empty())
140 SymInfo.st_name = StrTab->getIndex(Name);
141 SymInfo.st_shndx = Section->getNumber();
142 KeyValue.second.setNumber(SymNumber++);
143 }
144 for (auto &KeyValue : GlobalSymbols) {
Jan Voungec270732015-01-12 17:00:22 -0800145 const IceString &Name = KeyValue.first;
146 ELFSection *Section = KeyValue.second.Section;
Jan Voung08c3bcd2014-12-01 17:55:16 -0800147 Elf64_Sym &SymInfo = KeyValue.second.Sym;
148 if (!Name.empty())
149 SymInfo.st_name = StrTab->getIndex(Name);
150 SymInfo.st_shndx = Section->getNumber();
151 KeyValue.second.setNumber(SymNumber++);
152 }
153}
154
155void ELFSymbolTableSection::writeData(ELFStreamer &Str, bool IsELF64) {
156 if (IsELF64) {
157 writeSymbolMap<true>(Str, LocalSymbols);
158 writeSymbolMap<true>(Str, GlobalSymbols);
159 } else {
160 writeSymbolMap<false>(Str, LocalSymbols);
161 writeSymbolMap<false>(Str, GlobalSymbols);
162 }
163}
164
165// String tables.
166
167void ELFStringTableSection::add(const IceString &Str) {
168 assert(!isLaidOut());
169 assert(!Str.empty());
170 StringToIndexMap.insert(std::make_pair(Str, UnknownIndex));
171}
172
173size_t ELFStringTableSection::getIndex(const IceString &Str) const {
174 assert(isLaidOut());
175 StringToIndexType::const_iterator It = StringToIndexMap.find(Str);
176 if (It == StringToIndexMap.end()) {
177 llvm_unreachable("String index not found");
178 return UnknownIndex;
179 }
180 return It->second;
181}
182
183bool ELFStringTableSection::SuffixComparator::
184operator()(const IceString &StrA, const IceString &StrB) const {
185 size_t LenA = StrA.size();
186 size_t LenB = StrB.size();
187 size_t CommonLen = std::min(LenA, LenB);
188 // If there is a difference in the common suffix, use that diff to sort.
189 for (size_t i = 0; i < CommonLen; ++i) {
190 char a = StrA[LenA - i - 1];
191 char b = StrB[LenB - i - 1];
192 if (a != b)
193 return a > b;
194 }
195 // If the common suffixes are completely equal, let the longer one come
196 // first, so that it can be laid out first and its characters shared.
197 return LenA > LenB;
198}
199
200void ELFStringTableSection::doLayout() {
201 assert(!isLaidOut());
202 llvm::StringRef Prev;
203
204 // String table starts with 0 byte.
205 StringData.push_back(0);
206
207 for (auto &StringIndex : StringToIndexMap) {
208 assert(StringIndex.second == UnknownIndex);
209 llvm::StringRef Cur = llvm::StringRef(StringIndex.first);
210 if (Prev.endswith(Cur)) {
211 // Prev is already in the StringData, and Cur is shorter than Prev
212 // based on the sort.
213 StringIndex.second = StringData.size() - Cur.size() - 1;
214 continue;
215 }
216 StringIndex.second = StringData.size();
217 std::copy(Cur.begin(), Cur.end(), back_inserter(StringData));
218 StringData.push_back(0);
219 Prev = Cur;
220 }
221}
222
223} // end of namespace Ice