blob: d23d3797f5f19a2f851827ac174c265382a9dd53 [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
Rafael Espindola71675852015-09-22 00:16:19 +000046// This represents a section in an output file.
47// Different sub classes represent different types of sections. Some contain
48// input sections, others are created by the linker.
49// The writer creates multiple OutputSections and assign them unique,
Rafael Espindola5805c4f2015-09-21 21:38:08 +000050// 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
Rafael Espindola71675852015-09-22 00:16:19 +0000245 void addSection(InputSection<ELFT> *C);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000246 void writeTo(uint8_t *Buf) override;
247
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000248private:
Rafael Espindola71675852015-09-22 00:16:19 +0000249 std::vector<InputSection<ELFT> *> Sections;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000250 const PltSection<ELFT> &PltSec;
251 const GotSection<ELFT> &GotSec;
252};
253
254template <bool Is64Bits>
255class InterpSection final : public OutputSectionBase<Is64Bits> {
256public:
257 InterpSection();
258
259 void writeTo(uint8_t *Buf);
260};
261
262template <bool Is64Bits>
263class StringTableSection final : public OutputSectionBase<Is64Bits> {
264public:
265 typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
266 StringTableSection(bool Dynamic)
267 : OutputSectionBase<Is64Bits>(
268 Dynamic ? ".dynstr" : ".strtab", llvm::ELF::SHT_STRTAB,
269 Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
270 Dynamic(Dynamic) {
271 this->Header.sh_addralign = 1;
272 }
273
274 void add(StringRef S) { StrTabBuilder.add(S); }
275 size_t getFileOff(StringRef S) const { return StrTabBuilder.getOffset(S); }
276 StringRef data() const { return StrTabBuilder.data(); }
277 void writeTo(uint8_t *Buf) override;
278
279 void finalize() override {
280 StrTabBuilder.finalize(llvm::StringTableBuilder::ELF);
281 this->Header.sh_size = StrTabBuilder.data().size();
282 }
283
284 bool isDynamic() const { return Dynamic; }
285
286private:
287 const bool Dynamic;
288 llvm::StringTableBuilder StrTabBuilder;
289};
290
291template <class ELFT>
292class HashTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
293 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
294
295public:
296 HashTableSection(SymbolTableSection<ELFT> &DynSymSec)
297 : OutputSectionBase<ELFT::Is64Bits>(".hash", llvm::ELF::SHT_HASH,
298 llvm::ELF::SHF_ALLOC),
299 DynSymSec(DynSymSec) {
300 this->Header.sh_entsize = sizeof(Elf_Word);
301 this->Header.sh_addralign = sizeof(Elf_Word);
302 }
303
304 void addSymbol(SymbolBody *S);
305
306 void finalize() override {
307 this->Header.sh_link = DynSymSec.getSectionIndex();
308
309 assert(DynSymSec.getNumSymbols() == Hashes.size() + 1);
310 unsigned NumEntries = 2; // nbucket and nchain.
311 NumEntries += DynSymSec.getNumSymbols(); // The chain entries.
312
313 // Create as many buckets as there are symbols.
314 // FIXME: This is simplistic. We can try to optimize it, but implementing
315 // support for SHT_GNU_HASH is probably even more profitable.
316 NumEntries += DynSymSec.getNumSymbols();
317 this->Header.sh_size = NumEntries * sizeof(Elf_Word);
318 }
319
320 void writeTo(uint8_t *Buf) override {
321 unsigned NumSymbols = DynSymSec.getNumSymbols();
322 auto *P = reinterpret_cast<Elf_Word *>(Buf);
323 *P++ = NumSymbols; // nbucket
324 *P++ = NumSymbols; // nchain
325
326 Elf_Word *Buckets = P;
327 Elf_Word *Chains = P + NumSymbols;
328
329 for (unsigned I = 1; I < NumSymbols; ++I) {
330 uint32_t Hash = Hashes[I - 1] % NumSymbols;
331 Chains[I] = Buckets[Hash];
332 Buckets[Hash] = I;
333 }
334 }
335
336 SymbolTableSection<ELFT> &getDynSymSec() { return DynSymSec; }
337
338private:
339 uint32_t hash(StringRef Name) {
340 uint32_t H = 0;
341 for (char C : Name) {
342 H = (H << 4) + C;
343 uint32_t G = H & 0xf0000000;
344 if (G)
345 H ^= G >> 24;
346 H &= ~G;
347 }
348 return H;
349 }
350 SymbolTableSection<ELFT> &DynSymSec;
351 std::vector<uint32_t> Hashes;
352};
353
354template <class ELFT>
355class DynamicSection final : public OutputSectionBase<ELFT::Is64Bits> {
356 typedef OutputSectionBase<ELFT::Is64Bits> Base;
357 typedef typename Base::HeaderT HeaderT;
358
359public:
360 DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec,
361 RelocationSection<ELFT> &RelaDynSec)
362 : OutputSectionBase<ELFT::Is64Bits>(".dynamic", llvm::ELF::SHT_DYNAMIC,
363 llvm::ELF::SHF_ALLOC |
364 llvm::ELF::SHF_WRITE),
365 HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),
366 DynStrSec(DynSymSec.getStrTabSec()), RelaDynSec(RelaDynSec),
367 SymTab(SymTab) {
368 typename Base::HeaderT &Header = this->Header;
369 Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
370 Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
371 }
372
373 void finalize() override;
374 void writeTo(uint8_t *Buf) override;
375
376private:
377 HashTableSection<ELFT> &HashSec;
378 SymbolTableSection<ELFT> &DynSymSec;
379 StringTableSection<ELFT::Is64Bits> &DynStrSec;
380 RelocationSection<ELFT> &RelaDynSec;
381 SymbolTable &SymTab;
382};
383}
384}
385#endif