blob: c40ee8830b782aad9b88117102c2344e4c07e07b [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
Rafael Espindola5805c4f2015-09-21 21:38:08 +000032template <class ELFT>
33typename llvm::object::ELFFile<ELFT>::uintX_t
34getSymVA(const DefinedRegular<ELFT> *DR);
35
36template <class ELFT>
37typename llvm::object::ELFFile<ELFT>::uintX_t
38getLocalSymVA(const typename llvm::object::ELFFile<ELFT>::Elf_Sym *Sym,
39 const ObjectFile<ELFT> &File);
40
41bool includeInSymtab(const SymbolBody &B);
Rafael Espindola05a3dd22015-09-22 23:38:23 +000042bool includeInDynamicSymtab(const SymbolBody &B);
Rafael Espindola5805c4f2015-09-21 21:38:08 +000043
Rafael Espindola71675852015-09-22 00:16:19 +000044// This represents a section in an output file.
45// Different sub classes represent different types of sections. Some contain
46// input sections, others are created by the linker.
47// The writer creates multiple OutputSections and assign them unique,
Rafael Espindola5805c4f2015-09-21 21:38:08 +000048// non-overlapping file offsets and VAs.
49template <bool Is64Bits> class OutputSectionBase {
50public:
51 typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
52 typedef typename std::conditional<Is64Bits, llvm::ELF::Elf64_Shdr,
53 llvm::ELF::Elf32_Shdr>::type HeaderT;
54
55 OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
56 void setVA(uintX_t VA) { Header.sh_addr = VA; }
57 uintX_t getVA() const { return Header.sh_addr; }
58 void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
59 template <llvm::object::endianness E>
60 void writeHeaderTo(typename llvm::object::ELFFile<
61 llvm::object::ELFType<E, Is64Bits>>::Elf_Shdr *SHdr);
62 StringRef getName() { return Name; }
63 void setNameOffset(uintX_t Offset) { Header.sh_name = Offset; }
64
65 unsigned getSectionIndex() const { return SectionIndex; }
66 void setSectionIndex(unsigned I) { SectionIndex = I; }
67
68 // Returns the size of the section in the output file.
69 uintX_t getSize() { return Header.sh_size; }
70 void setSize(uintX_t Val) { Header.sh_size = Val; }
71 uintX_t getFlags() { return Header.sh_flags; }
72 uintX_t getFileOff() { return Header.sh_offset; }
73 uintX_t getAlign() {
74 // The ELF spec states that a value of 0 means the section has no alignment
75 // constraits.
76 return std::max<uintX_t>(Header.sh_addralign, 1);
77 }
78 uint32_t getType() { return Header.sh_type; }
79
80 static unsigned getAddrSize() { return Is64Bits ? 8 : 4; }
81
82 virtual void finalize() {}
83 virtual void writeTo(uint8_t *Buf) = 0;
84
85protected:
86 StringRef Name;
87 HeaderT Header;
88 unsigned SectionIndex;
89 ~OutputSectionBase() = default;
90};
91
92template <class ELFT>
93class GotSection final : public OutputSectionBase<ELFT::Is64Bits> {
94 typedef OutputSectionBase<ELFT::Is64Bits> Base;
95 typedef typename Base::uintX_t uintX_t;
96
97public:
98 GotSection()
99 : OutputSectionBase<ELFT::Is64Bits>(".got", llvm::ELF::SHT_PROGBITS,
100 llvm::ELF::SHF_ALLOC |
101 llvm::ELF::SHF_WRITE) {
102 this->Header.sh_addralign = this->getAddrSize();
103 }
104 void finalize() override {
105 this->Header.sh_size = Entries.size() * this->getAddrSize();
106 }
107 void writeTo(uint8_t *Buf) override {}
108 void addEntry(SymbolBody *Sym);
109 bool empty() const { return Entries.empty(); }
110 uintX_t getEntryAddr(const SymbolBody &B) const;
111
112private:
113 std::vector<const SymbolBody *> Entries;
114};
115
116template <class ELFT>
117class PltSection final : public OutputSectionBase<ELFT::Is64Bits> {
118 typedef OutputSectionBase<ELFT::Is64Bits> Base;
119 typedef typename Base::uintX_t uintX_t;
120
121public:
122 PltSection(const GotSection<ELFT> &GotSec)
123 : OutputSectionBase<ELFT::Is64Bits>(".plt", llvm::ELF::SHT_PROGBITS,
124 llvm::ELF::SHF_ALLOC |
125 llvm::ELF::SHF_EXECINSTR),
126 GotSec(GotSec) {
127 this->Header.sh_addralign = 16;
128 }
129 void finalize() override {
130 this->Header.sh_size = Entries.size() * EntrySize;
131 }
132 void writeTo(uint8_t *Buf) override;
133 void addEntry(SymbolBody *Sym);
134 bool empty() const { return Entries.empty(); }
135 uintX_t getEntryAddr(const SymbolBody &B) const;
136 static const unsigned EntrySize = 8;
137
138private:
139 std::vector<const SymbolBody *> Entries;
140 const GotSection<ELFT> &GotSec;
141};
142
143template <class ELFT> struct DynamicReloc {
144 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
145 const InputSection<ELFT> &C;
146 const Elf_Rel &RI;
147};
148
149template <class ELFT>
150class SymbolTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
151public:
152 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
153 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
154 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
155 typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
156 SymbolTableSection(SymbolTable &Table,
Rafael Espindolac2d21192015-09-23 18:25:05 +0000157 StringTableSection<ELFT::Is64Bits> &StrTabSec,
158 const OutputSection<ELFT> &BssSec)
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000159 : OutputSectionBase<ELFT::Is64Bits>(
160 StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
161 StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM
162 : llvm::ELF::SHT_SYMTAB,
163 StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
Rafael Espindolac2d21192015-09-23 18:25:05 +0000164 Table(Table), StrTabSec(StrTabSec), BssSec(BssSec) {
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000165 typedef OutputSectionBase<ELFT::Is64Bits> Base;
166 typename Base::HeaderT &Header = this->Header;
167
168 Header.sh_entsize = sizeof(Elf_Sym);
169 Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
170 }
171
172 void finalize() override {
173 this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
174 this->Header.sh_link = StrTabSec.getSectionIndex();
175 this->Header.sh_info = NumLocals + 1;
176 }
177
178 void writeTo(uint8_t *Buf) override;
179
180 const SymbolTable &getSymTable() const { return Table; }
181
182 void addSymbol(StringRef Name, bool isLocal = false) {
183 StrTabSec.add(Name);
184 ++NumVisible;
185 if (isLocal)
186 ++NumLocals;
187 }
188
Davide Italianod75d3b92015-09-24 15:08:23 +0000189 bool shouldKeepInSymtab(StringRef Name);
190
Davide Italianoe44456b2015-09-23 01:50:53 +0000191 StringTableSection<ELFT::Is64Bits> &getStrTabSec() const { return StrTabSec; }
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000192 unsigned getNumSymbols() const { return NumVisible + 1; }
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000193
194private:
195 SymbolTable &Table;
196 StringTableSection<ELFT::Is64Bits> &StrTabSec;
197 unsigned NumVisible = 0;
198 unsigned NumLocals = 0;
Rafael Espindolac2d21192015-09-23 18:25:05 +0000199 const OutputSection<ELFT> &BssSec;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000200};
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,
Rafael Espindolac2d21192015-09-23 18:25:05 +0000241 const OutputSection<ELFT> &BssSec, StringRef Name,
242 uint32_t sh_type, uintX_t sh_flags)
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000243 : OutputSectionBase<ELFT::Is64Bits>(Name, sh_type, sh_flags),
Rafael Espindolac2d21192015-09-23 18:25:05 +0000244 PltSec(PltSec), GotSec(GotSec), BssSec(BssSec) {}
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000245
Rafael Espindola71675852015-09-22 00:16:19 +0000246 void addSection(InputSection<ELFT> *C);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000247 void writeTo(uint8_t *Buf) override;
248
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000249private:
Rafael Espindola71675852015-09-22 00:16:19 +0000250 std::vector<InputSection<ELFT> *> Sections;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000251 const PltSection<ELFT> &PltSec;
252 const GotSection<ELFT> &GotSec;
Rafael Espindolac2d21192015-09-23 18:25:05 +0000253 const OutputSection<ELFT> &BssSec;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000254};
255
256template <bool Is64Bits>
257class InterpSection final : public OutputSectionBase<Is64Bits> {
258public:
259 InterpSection();
260
261 void writeTo(uint8_t *Buf);
262};
263
264template <bool Is64Bits>
265class StringTableSection final : public OutputSectionBase<Is64Bits> {
266public:
267 typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
268 StringTableSection(bool Dynamic)
269 : OutputSectionBase<Is64Bits>(
270 Dynamic ? ".dynstr" : ".strtab", llvm::ELF::SHT_STRTAB,
271 Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
272 Dynamic(Dynamic) {
273 this->Header.sh_addralign = 1;
274 }
275
276 void add(StringRef S) { StrTabBuilder.add(S); }
277 size_t getFileOff(StringRef S) const { return StrTabBuilder.getOffset(S); }
278 StringRef data() const { return StrTabBuilder.data(); }
279 void writeTo(uint8_t *Buf) override;
280
281 void finalize() override {
282 StrTabBuilder.finalize(llvm::StringTableBuilder::ELF);
283 this->Header.sh_size = StrTabBuilder.data().size();
284 }
285
286 bool isDynamic() const { return Dynamic; }
287
288private:
289 const bool Dynamic;
290 llvm::StringTableBuilder StrTabBuilder;
291};
292
293template <class ELFT>
294class HashTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
295 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
296
297public:
298 HashTableSection(SymbolTableSection<ELFT> &DynSymSec)
299 : OutputSectionBase<ELFT::Is64Bits>(".hash", llvm::ELF::SHT_HASH,
300 llvm::ELF::SHF_ALLOC),
301 DynSymSec(DynSymSec) {
302 this->Header.sh_entsize = sizeof(Elf_Word);
303 this->Header.sh_addralign = sizeof(Elf_Word);
304 }
305
306 void addSymbol(SymbolBody *S);
307
308 void finalize() override {
309 this->Header.sh_link = DynSymSec.getSectionIndex();
310
311 assert(DynSymSec.getNumSymbols() == Hashes.size() + 1);
312 unsigned NumEntries = 2; // nbucket and nchain.
313 NumEntries += DynSymSec.getNumSymbols(); // The chain entries.
314
315 // Create as many buckets as there are symbols.
316 // FIXME: This is simplistic. We can try to optimize it, but implementing
317 // support for SHT_GNU_HASH is probably even more profitable.
318 NumEntries += DynSymSec.getNumSymbols();
319 this->Header.sh_size = NumEntries * sizeof(Elf_Word);
320 }
321
322 void writeTo(uint8_t *Buf) override {
323 unsigned NumSymbols = DynSymSec.getNumSymbols();
324 auto *P = reinterpret_cast<Elf_Word *>(Buf);
325 *P++ = NumSymbols; // nbucket
326 *P++ = NumSymbols; // nchain
327
328 Elf_Word *Buckets = P;
329 Elf_Word *Chains = P + NumSymbols;
330
331 for (unsigned I = 1; I < NumSymbols; ++I) {
332 uint32_t Hash = Hashes[I - 1] % NumSymbols;
333 Chains[I] = Buckets[Hash];
334 Buckets[Hash] = I;
335 }
336 }
337
338 SymbolTableSection<ELFT> &getDynSymSec() { return DynSymSec; }
339
340private:
341 uint32_t hash(StringRef Name) {
342 uint32_t H = 0;
343 for (char C : Name) {
344 H = (H << 4) + C;
345 uint32_t G = H & 0xf0000000;
346 if (G)
347 H ^= G >> 24;
348 H &= ~G;
349 }
350 return H;
351 }
352 SymbolTableSection<ELFT> &DynSymSec;
353 std::vector<uint32_t> Hashes;
354};
355
356template <class ELFT>
357class DynamicSection final : public OutputSectionBase<ELFT::Is64Bits> {
358 typedef OutputSectionBase<ELFT::Is64Bits> Base;
359 typedef typename Base::HeaderT HeaderT;
360
361public:
362 DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec,
363 RelocationSection<ELFT> &RelaDynSec)
364 : OutputSectionBase<ELFT::Is64Bits>(".dynamic", llvm::ELF::SHT_DYNAMIC,
365 llvm::ELF::SHF_ALLOC |
366 llvm::ELF::SHF_WRITE),
367 HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),
368 DynStrSec(DynSymSec.getStrTabSec()), RelaDynSec(RelaDynSec),
369 SymTab(SymTab) {
370 typename Base::HeaderT &Header = this->Header;
371 Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
372 Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
373 }
374
375 void finalize() override;
376 void writeTo(uint8_t *Buf) override;
377
378private:
379 HashTableSection<ELFT> &HashSec;
380 SymbolTableSection<ELFT> &DynSymSec;
381 StringTableSection<ELFT::Is64Bits> &DynStrSec;
382 RelocationSection<ELFT> &RelaDynSec;
383 SymbolTable &SymTab;
384};
385}
386}
387#endif