blob: 2e1008695766457d82ea9bebd5c030e0d7a0cd98 [file] [log] [blame]
Rafael Espindola5805c4f2015-09-21 21:38:08 +00001//===- OutputSections.h -----------------------------------------*- C++ -*-===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLD_ELF_OUTPUT_SECTIONS_H
11#define LLD_ELF_OUTPUT_SECTIONS_H
12
13#include "lld/Core/LLVM.h"
14
15#include "llvm/MC/StringTableBuilder.h"
16#include "llvm/Object/ELF.h"
17
18#include <type_traits>
19
20namespace lld {
21namespace elf2 {
22
23class SymbolBody;
24class SymbolTable;
25template <class ELFT> class SymbolTableSection;
26template <bool Is64Bits> class StringTableSection;
27template <class ELFT> class InputSection;
28template <class ELFT> class OutputSection;
29template <class ELFT> class ObjectFile;
30template <class ELFT> class DefinedRegular;
31
32bool relocNeedsPLT(uint32_t Type);
33bool relocNeedsGOT(uint32_t Type);
34
35template <class ELFT>
36typename llvm::object::ELFFile<ELFT>::uintX_t
37getSymVA(const DefinedRegular<ELFT> *DR);
38
39template <class ELFT>
40typename llvm::object::ELFFile<ELFT>::uintX_t
41getLocalSymVA(const typename llvm::object::ELFFile<ELFT>::Elf_Sym *Sym,
42 const ObjectFile<ELFT> &File);
43
44bool includeInSymtab(const SymbolBody &B);
45
46// OutputSection represents a section in an output file. It's a
47// container of chunks. OutputSection and Chunk are 1:N relationship.
48// Chunks cannot belong to more than one OutputSections. The writer
49// creates multiple OutputSections and assign them unique,
50// non-overlapping file offsets and VAs.
51template <bool Is64Bits> class OutputSectionBase {
52public:
53 typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
54 typedef typename std::conditional<Is64Bits, llvm::ELF::Elf64_Shdr,
55 llvm::ELF::Elf32_Shdr>::type HeaderT;
56
57 OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
58 void setVA(uintX_t VA) { Header.sh_addr = VA; }
59 uintX_t getVA() const { return Header.sh_addr; }
60 void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
61 template <llvm::object::endianness E>
62 void writeHeaderTo(typename llvm::object::ELFFile<
63 llvm::object::ELFType<E, Is64Bits>>::Elf_Shdr *SHdr);
64 StringRef getName() { return Name; }
65 void setNameOffset(uintX_t Offset) { Header.sh_name = Offset; }
66
67 unsigned getSectionIndex() const { return SectionIndex; }
68 void setSectionIndex(unsigned I) { SectionIndex = I; }
69
70 // Returns the size of the section in the output file.
71 uintX_t getSize() { return Header.sh_size; }
72 void setSize(uintX_t Val) { Header.sh_size = Val; }
73 uintX_t getFlags() { return Header.sh_flags; }
74 uintX_t getFileOff() { return Header.sh_offset; }
75 uintX_t getAlign() {
76 // The ELF spec states that a value of 0 means the section has no alignment
77 // constraits.
78 return std::max<uintX_t>(Header.sh_addralign, 1);
79 }
80 uint32_t getType() { return Header.sh_type; }
81
82 static unsigned getAddrSize() { return Is64Bits ? 8 : 4; }
83
84 virtual void finalize() {}
85 virtual void writeTo(uint8_t *Buf) = 0;
86
87protected:
88 StringRef Name;
89 HeaderT Header;
90 unsigned SectionIndex;
91 ~OutputSectionBase() = default;
92};
93
94template <class ELFT>
95class GotSection final : public OutputSectionBase<ELFT::Is64Bits> {
96 typedef OutputSectionBase<ELFT::Is64Bits> Base;
97 typedef typename Base::uintX_t uintX_t;
98
99public:
100 GotSection()
101 : OutputSectionBase<ELFT::Is64Bits>(".got", llvm::ELF::SHT_PROGBITS,
102 llvm::ELF::SHF_ALLOC |
103 llvm::ELF::SHF_WRITE) {
104 this->Header.sh_addralign = this->getAddrSize();
105 }
106 void finalize() override {
107 this->Header.sh_size = Entries.size() * this->getAddrSize();
108 }
109 void writeTo(uint8_t *Buf) override {}
110 void addEntry(SymbolBody *Sym);
111 bool empty() const { return Entries.empty(); }
112 uintX_t getEntryAddr(const SymbolBody &B) const;
113
114private:
115 std::vector<const SymbolBody *> Entries;
116};
117
118template <class ELFT>
119class PltSection final : public OutputSectionBase<ELFT::Is64Bits> {
120 typedef OutputSectionBase<ELFT::Is64Bits> Base;
121 typedef typename Base::uintX_t uintX_t;
122
123public:
124 PltSection(const GotSection<ELFT> &GotSec)
125 : OutputSectionBase<ELFT::Is64Bits>(".plt", llvm::ELF::SHT_PROGBITS,
126 llvm::ELF::SHF_ALLOC |
127 llvm::ELF::SHF_EXECINSTR),
128 GotSec(GotSec) {
129 this->Header.sh_addralign = 16;
130 }
131 void finalize() override {
132 this->Header.sh_size = Entries.size() * EntrySize;
133 }
134 void writeTo(uint8_t *Buf) override;
135 void addEntry(SymbolBody *Sym);
136 bool empty() const { return Entries.empty(); }
137 uintX_t getEntryAddr(const SymbolBody &B) const;
138 static const unsigned EntrySize = 8;
139
140private:
141 std::vector<const SymbolBody *> Entries;
142 const GotSection<ELFT> &GotSec;
143};
144
145template <class ELFT> struct DynamicReloc {
146 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
147 const InputSection<ELFT> &C;
148 const Elf_Rel &RI;
149};
150
151template <class ELFT>
152class SymbolTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
153public:
154 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
155 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
156 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
157 typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
158 SymbolTableSection(SymbolTable &Table,
159 StringTableSection<ELFT::Is64Bits> &StrTabSec)
160 : OutputSectionBase<ELFT::Is64Bits>(
161 StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
162 StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM
163 : llvm::ELF::SHT_SYMTAB,
164 StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
165 Table(Table), StrTabSec(StrTabSec) {
166 typedef OutputSectionBase<ELFT::Is64Bits> Base;
167 typename Base::HeaderT &Header = this->Header;
168
169 Header.sh_entsize = sizeof(Elf_Sym);
170 Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
171 }
172
173 void finalize() override {
174 this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
175 this->Header.sh_link = StrTabSec.getSectionIndex();
176 this->Header.sh_info = NumLocals + 1;
177 }
178
179 void writeTo(uint8_t *Buf) override;
180
181 const SymbolTable &getSymTable() const { return Table; }
182
183 void addSymbol(StringRef Name, bool isLocal = false) {
184 StrTabSec.add(Name);
185 ++NumVisible;
186 if (isLocal)
187 ++NumLocals;
188 }
189
190 StringTableSection<ELFT::Is64Bits> &getStrTabSec() { return StrTabSec; }
191 unsigned getNumSymbols() const { return NumVisible + 1; }
192 void setBssSec(const OutputSection<ELFT> *V) { BssSec = V; }
193
194private:
195 SymbolTable &Table;
196 StringTableSection<ELFT::Is64Bits> &StrTabSec;
197 unsigned NumVisible = 0;
198 unsigned NumLocals = 0;
199 const OutputSection<ELFT> *BssSec = nullptr;
200};
201
202template <class ELFT>
203class RelocationSection final : public OutputSectionBase<ELFT::Is64Bits> {
204 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
205 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
206
207public:
208 RelocationSection(SymbolTableSection<ELFT> &DynSymSec,
209 const GotSection<ELFT> &GotSec, bool IsRela)
210 : OutputSectionBase<ELFT::Is64Bits>(IsRela ? ".rela.dyn" : ".rel.dyn",
211 IsRela ? llvm::ELF::SHT_RELA
212 : llvm::ELF::SHT_REL,
213 llvm::ELF::SHF_ALLOC),
214 DynSymSec(DynSymSec), GotSec(GotSec), IsRela(IsRela) {
215 this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
216 this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
217 }
218
219 void addReloc(const DynamicReloc<ELFT> &Reloc) { Relocs.push_back(Reloc); }
220 void finalize() override;
221 void writeTo(uint8_t *Buf) override;
222 bool hasRelocs() const { return !Relocs.empty(); }
223 bool isRela() const { return IsRela; }
224
225private:
226 std::vector<DynamicReloc<ELFT>> Relocs;
227 SymbolTableSection<ELFT> &DynSymSec;
228 const GotSection<ELFT> &GotSec;
229 const bool IsRela;
230};
231
232template <class ELFT>
233class OutputSection final : public OutputSectionBase<ELFT::Is64Bits> {
234public:
235 typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
236 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
237 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
238 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
239 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
240 OutputSection(const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec,
241 StringRef Name, uint32_t sh_type, uintX_t sh_flags)
242 : OutputSectionBase<ELFT::Is64Bits>(Name, sh_type, sh_flags),
243 PltSec(PltSec), GotSec(GotSec) {}
244
245 void addChunk(InputSection<ELFT> *C);
246 void writeTo(uint8_t *Buf) override;
247
248 template <bool isRela>
249 void relocate(uint8_t *Buf,
250 llvm::iterator_range<
251 const llvm::object::Elf_Rel_Impl<ELFT, isRela> *> Rels,
252 const ObjectFile<ELFT> &File, uintX_t BaseAddr);
253
254 void relocateOne(uint8_t *Buf, const Elf_Rela &Rel, uint32_t Type,
255 uintX_t BaseAddr, uintX_t SymVA);
256 void relocateOne(uint8_t *Buf, const Elf_Rel &Rel, uint32_t Type,
257 uintX_t BaseAddr, uintX_t SymVA);
258
259private:
260 std::vector<InputSection<ELFT> *> Chunks;
261 const PltSection<ELFT> &PltSec;
262 const GotSection<ELFT> &GotSec;
263};
264
265template <bool Is64Bits>
266class InterpSection final : public OutputSectionBase<Is64Bits> {
267public:
268 InterpSection();
269
270 void writeTo(uint8_t *Buf);
271};
272
273template <bool Is64Bits>
274class StringTableSection final : public OutputSectionBase<Is64Bits> {
275public:
276 typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
277 StringTableSection(bool Dynamic)
278 : OutputSectionBase<Is64Bits>(
279 Dynamic ? ".dynstr" : ".strtab", llvm::ELF::SHT_STRTAB,
280 Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
281 Dynamic(Dynamic) {
282 this->Header.sh_addralign = 1;
283 }
284
285 void add(StringRef S) { StrTabBuilder.add(S); }
286 size_t getFileOff(StringRef S) const { return StrTabBuilder.getOffset(S); }
287 StringRef data() const { return StrTabBuilder.data(); }
288 void writeTo(uint8_t *Buf) override;
289
290 void finalize() override {
291 StrTabBuilder.finalize(llvm::StringTableBuilder::ELF);
292 this->Header.sh_size = StrTabBuilder.data().size();
293 }
294
295 bool isDynamic() const { return Dynamic; }
296
297private:
298 const bool Dynamic;
299 llvm::StringTableBuilder StrTabBuilder;
300};
301
302template <class ELFT>
303class HashTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
304 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
305
306public:
307 HashTableSection(SymbolTableSection<ELFT> &DynSymSec)
308 : OutputSectionBase<ELFT::Is64Bits>(".hash", llvm::ELF::SHT_HASH,
309 llvm::ELF::SHF_ALLOC),
310 DynSymSec(DynSymSec) {
311 this->Header.sh_entsize = sizeof(Elf_Word);
312 this->Header.sh_addralign = sizeof(Elf_Word);
313 }
314
315 void addSymbol(SymbolBody *S);
316
317 void finalize() override {
318 this->Header.sh_link = DynSymSec.getSectionIndex();
319
320 assert(DynSymSec.getNumSymbols() == Hashes.size() + 1);
321 unsigned NumEntries = 2; // nbucket and nchain.
322 NumEntries += DynSymSec.getNumSymbols(); // The chain entries.
323
324 // Create as many buckets as there are symbols.
325 // FIXME: This is simplistic. We can try to optimize it, but implementing
326 // support for SHT_GNU_HASH is probably even more profitable.
327 NumEntries += DynSymSec.getNumSymbols();
328 this->Header.sh_size = NumEntries * sizeof(Elf_Word);
329 }
330
331 void writeTo(uint8_t *Buf) override {
332 unsigned NumSymbols = DynSymSec.getNumSymbols();
333 auto *P = reinterpret_cast<Elf_Word *>(Buf);
334 *P++ = NumSymbols; // nbucket
335 *P++ = NumSymbols; // nchain
336
337 Elf_Word *Buckets = P;
338 Elf_Word *Chains = P + NumSymbols;
339
340 for (unsigned I = 1; I < NumSymbols; ++I) {
341 uint32_t Hash = Hashes[I - 1] % NumSymbols;
342 Chains[I] = Buckets[Hash];
343 Buckets[Hash] = I;
344 }
345 }
346
347 SymbolTableSection<ELFT> &getDynSymSec() { return DynSymSec; }
348
349private:
350 uint32_t hash(StringRef Name) {
351 uint32_t H = 0;
352 for (char C : Name) {
353 H = (H << 4) + C;
354 uint32_t G = H & 0xf0000000;
355 if (G)
356 H ^= G >> 24;
357 H &= ~G;
358 }
359 return H;
360 }
361 SymbolTableSection<ELFT> &DynSymSec;
362 std::vector<uint32_t> Hashes;
363};
364
365template <class ELFT>
366class DynamicSection final : public OutputSectionBase<ELFT::Is64Bits> {
367 typedef OutputSectionBase<ELFT::Is64Bits> Base;
368 typedef typename Base::HeaderT HeaderT;
369
370public:
371 DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec,
372 RelocationSection<ELFT> &RelaDynSec)
373 : OutputSectionBase<ELFT::Is64Bits>(".dynamic", llvm::ELF::SHT_DYNAMIC,
374 llvm::ELF::SHF_ALLOC |
375 llvm::ELF::SHF_WRITE),
376 HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),
377 DynStrSec(DynSymSec.getStrTabSec()), RelaDynSec(RelaDynSec),
378 SymTab(SymTab) {
379 typename Base::HeaderT &Header = this->Header;
380 Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
381 Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
382 }
383
384 void finalize() override;
385 void writeTo(uint8_t *Buf) override;
386
387private:
388 HashTableSection<ELFT> &HashSec;
389 SymbolTableSection<ELFT> &DynSymSec;
390 StringTableSection<ELFT::Is64Bits> &DynStrSec;
391 RelocationSection<ELFT> &RelaDynSec;
392 SymbolTable &SymTab;
393};
394}
395}
396#endif