blob: 9ecf363bf54ad7f6eb96c2075134123a84d3ef21 [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,
157 StringTableSection<ELFT::Is64Bits> &StrTabSec)
158 : OutputSectionBase<ELFT::Is64Bits>(
159 StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
160 StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM
161 : llvm::ELF::SHT_SYMTAB,
162 StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
163 Table(Table), StrTabSec(StrTabSec) {
164 typedef OutputSectionBase<ELFT::Is64Bits> Base;
165 typename Base::HeaderT &Header = this->Header;
166
167 Header.sh_entsize = sizeof(Elf_Sym);
168 Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
169 }
170
171 void finalize() override {
172 this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
173 this->Header.sh_link = StrTabSec.getSectionIndex();
174 this->Header.sh_info = NumLocals + 1;
175 }
176
177 void writeTo(uint8_t *Buf) override;
178
179 const SymbolTable &getSymTable() const { return Table; }
180
181 void addSymbol(StringRef Name, bool isLocal = false) {
182 StrTabSec.add(Name);
183 ++NumVisible;
184 if (isLocal)
185 ++NumLocals;
186 }
187
188 StringTableSection<ELFT::Is64Bits> &getStrTabSec() { return StrTabSec; }
189 unsigned getNumSymbols() const { return NumVisible + 1; }
190 void setBssSec(const OutputSection<ELFT> *V) { BssSec = V; }
191
192private:
193 SymbolTable &Table;
194 StringTableSection<ELFT::Is64Bits> &StrTabSec;
195 unsigned NumVisible = 0;
196 unsigned NumLocals = 0;
197 const OutputSection<ELFT> *BssSec = nullptr;
198};
199
200template <class ELFT>
201class RelocationSection final : public OutputSectionBase<ELFT::Is64Bits> {
202 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
203 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
204
205public:
206 RelocationSection(SymbolTableSection<ELFT> &DynSymSec,
207 const GotSection<ELFT> &GotSec, bool IsRela)
208 : OutputSectionBase<ELFT::Is64Bits>(IsRela ? ".rela.dyn" : ".rel.dyn",
209 IsRela ? llvm::ELF::SHT_RELA
210 : llvm::ELF::SHT_REL,
211 llvm::ELF::SHF_ALLOC),
212 DynSymSec(DynSymSec), GotSec(GotSec), IsRela(IsRela) {
213 this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
214 this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
215 }
216
217 void addReloc(const DynamicReloc<ELFT> &Reloc) { Relocs.push_back(Reloc); }
218 void finalize() override;
219 void writeTo(uint8_t *Buf) override;
220 bool hasRelocs() const { return !Relocs.empty(); }
221 bool isRela() const { return IsRela; }
222
223private:
224 std::vector<DynamicReloc<ELFT>> Relocs;
225 SymbolTableSection<ELFT> &DynSymSec;
226 const GotSection<ELFT> &GotSec;
227 const bool IsRela;
228};
229
230template <class ELFT>
231class OutputSection final : public OutputSectionBase<ELFT::Is64Bits> {
232public:
233 typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
234 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
235 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
236 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
237 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
238 OutputSection(const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec,
239 StringRef Name, uint32_t sh_type, uintX_t sh_flags)
240 : OutputSectionBase<ELFT::Is64Bits>(Name, sh_type, sh_flags),
241 PltSec(PltSec), GotSec(GotSec) {}
242
Rafael Espindola71675852015-09-22 00:16:19 +0000243 void addSection(InputSection<ELFT> *C);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000244 void writeTo(uint8_t *Buf) override;
245
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000246private:
Rafael Espindola71675852015-09-22 00:16:19 +0000247 std::vector<InputSection<ELFT> *> Sections;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000248 const PltSection<ELFT> &PltSec;
249 const GotSection<ELFT> &GotSec;
250};
251
252template <bool Is64Bits>
253class InterpSection final : public OutputSectionBase<Is64Bits> {
254public:
255 InterpSection();
256
257 void writeTo(uint8_t *Buf);
258};
259
260template <bool Is64Bits>
261class StringTableSection final : public OutputSectionBase<Is64Bits> {
262public:
263 typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
264 StringTableSection(bool Dynamic)
265 : OutputSectionBase<Is64Bits>(
266 Dynamic ? ".dynstr" : ".strtab", llvm::ELF::SHT_STRTAB,
267 Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
268 Dynamic(Dynamic) {
269 this->Header.sh_addralign = 1;
270 }
271
272 void add(StringRef S) { StrTabBuilder.add(S); }
273 size_t getFileOff(StringRef S) const { return StrTabBuilder.getOffset(S); }
274 StringRef data() const { return StrTabBuilder.data(); }
275 void writeTo(uint8_t *Buf) override;
276
277 void finalize() override {
278 StrTabBuilder.finalize(llvm::StringTableBuilder::ELF);
279 this->Header.sh_size = StrTabBuilder.data().size();
280 }
281
282 bool isDynamic() const { return Dynamic; }
283
284private:
285 const bool Dynamic;
286 llvm::StringTableBuilder StrTabBuilder;
287};
288
289template <class ELFT>
290class HashTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
291 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
292
293public:
294 HashTableSection(SymbolTableSection<ELFT> &DynSymSec)
295 : OutputSectionBase<ELFT::Is64Bits>(".hash", llvm::ELF::SHT_HASH,
296 llvm::ELF::SHF_ALLOC),
297 DynSymSec(DynSymSec) {
298 this->Header.sh_entsize = sizeof(Elf_Word);
299 this->Header.sh_addralign = sizeof(Elf_Word);
300 }
301
302 void addSymbol(SymbolBody *S);
303
304 void finalize() override {
305 this->Header.sh_link = DynSymSec.getSectionIndex();
306
307 assert(DynSymSec.getNumSymbols() == Hashes.size() + 1);
308 unsigned NumEntries = 2; // nbucket and nchain.
309 NumEntries += DynSymSec.getNumSymbols(); // The chain entries.
310
311 // Create as many buckets as there are symbols.
312 // FIXME: This is simplistic. We can try to optimize it, but implementing
313 // support for SHT_GNU_HASH is probably even more profitable.
314 NumEntries += DynSymSec.getNumSymbols();
315 this->Header.sh_size = NumEntries * sizeof(Elf_Word);
316 }
317
318 void writeTo(uint8_t *Buf) override {
319 unsigned NumSymbols = DynSymSec.getNumSymbols();
320 auto *P = reinterpret_cast<Elf_Word *>(Buf);
321 *P++ = NumSymbols; // nbucket
322 *P++ = NumSymbols; // nchain
323
324 Elf_Word *Buckets = P;
325 Elf_Word *Chains = P + NumSymbols;
326
327 for (unsigned I = 1; I < NumSymbols; ++I) {
328 uint32_t Hash = Hashes[I - 1] % NumSymbols;
329 Chains[I] = Buckets[Hash];
330 Buckets[Hash] = I;
331 }
332 }
333
334 SymbolTableSection<ELFT> &getDynSymSec() { return DynSymSec; }
335
336private:
337 uint32_t hash(StringRef Name) {
338 uint32_t H = 0;
339 for (char C : Name) {
340 H = (H << 4) + C;
341 uint32_t G = H & 0xf0000000;
342 if (G)
343 H ^= G >> 24;
344 H &= ~G;
345 }
346 return H;
347 }
348 SymbolTableSection<ELFT> &DynSymSec;
349 std::vector<uint32_t> Hashes;
350};
351
352template <class ELFT>
353class DynamicSection final : public OutputSectionBase<ELFT::Is64Bits> {
354 typedef OutputSectionBase<ELFT::Is64Bits> Base;
355 typedef typename Base::HeaderT HeaderT;
356
357public:
358 DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec,
359 RelocationSection<ELFT> &RelaDynSec)
360 : OutputSectionBase<ELFT::Is64Bits>(".dynamic", llvm::ELF::SHT_DYNAMIC,
361 llvm::ELF::SHF_ALLOC |
362 llvm::ELF::SHF_WRITE),
363 HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),
364 DynStrSec(DynSymSec.getStrTabSec()), RelaDynSec(RelaDynSec),
365 SymTab(SymTab) {
366 typename Base::HeaderT &Header = this->Header;
367 Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
368 Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
369 }
370
371 void finalize() override;
372 void writeTo(uint8_t *Buf) override;
373
374private:
375 HashTableSection<ELFT> &HashSec;
376 SymbolTableSection<ELFT> &DynSymSec;
377 StringTableSection<ELFT::Is64Bits> &DynStrSec;
378 RelocationSection<ELFT> &RelaDynSec;
379 SymbolTable &SymTab;
380};
381}
382}
383#endif