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