blob: 6ece9adf4d2e0ba6b7fc7326b7f39bf6fd338d82 [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
Davide Italianoe44456b2015-09-23 01:50:53 +0000188 StringTableSection<ELFT::Is64Bits> &getStrTabSec() const { return StrTabSec; }
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000189 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;
Michael J. Spencer2812aa82015-09-23 16:57:31 +0000245 void setBssSec(const OutputSection<ELFT> *BS) { BssSec = BS; }
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000246
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000247private:
Rafael Espindola71675852015-09-22 00:16:19 +0000248 std::vector<InputSection<ELFT> *> Sections;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000249 const PltSection<ELFT> &PltSec;
250 const GotSection<ELFT> &GotSec;
Michael J. Spencer2812aa82015-09-23 16:57:31 +0000251 const OutputSection<ELFT> *BssSec = nullptr;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000252};
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