blob: 679926f155438a6513e9ebaf643e3967a35be78b [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 Italianob558b792015-09-25 04:22:13 +000046inline bool shouldKeepInSymtab(StringRef SymName) {
Davide Italiano85121bb2015-09-25 03:56:11 +000047 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:
Rafael Espindola35c6af32015-09-25 17:19:10 +0000108 GotSection();
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000109 void finalize() override {
110 this->Header.sh_size = Entries.size() * this->getAddrSize();
111 }
112 void writeTo(uint8_t *Buf) override {}
113 void addEntry(SymbolBody *Sym);
114 bool empty() const { return Entries.empty(); }
115 uintX_t getEntryAddr(const SymbolBody &B) const;
116
117private:
118 std::vector<const SymbolBody *> Entries;
119};
120
121template <class ELFT>
122class PltSection final : public OutputSectionBase<ELFT::Is64Bits> {
123 typedef OutputSectionBase<ELFT::Is64Bits> Base;
124 typedef typename Base::uintX_t uintX_t;
125
126public:
Rafael Espindola35c6af32015-09-25 17:19:10 +0000127 PltSection(const GotSection<ELFT> &GotSec);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000128 void finalize() override {
129 this->Header.sh_size = Entries.size() * EntrySize;
130 }
131 void writeTo(uint8_t *Buf) override;
132 void addEntry(SymbolBody *Sym);
133 bool empty() const { return Entries.empty(); }
134 uintX_t getEntryAddr(const SymbolBody &B) const;
135 static const unsigned EntrySize = 8;
136
137private:
138 std::vector<const SymbolBody *> Entries;
139 const GotSection<ELFT> &GotSec;
140};
141
142template <class ELFT> struct DynamicReloc {
143 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
144 const InputSection<ELFT> &C;
145 const Elf_Rel &RI;
146};
147
148template <class ELFT>
149class SymbolTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
150public:
151 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
152 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
153 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
154 typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
155 SymbolTableSection(SymbolTable &Table,
Rafael Espindolac2d21192015-09-23 18:25:05 +0000156 StringTableSection<ELFT::Is64Bits> &StrTabSec,
Rafael Espindola35c6af32015-09-25 17:19:10 +0000157 const OutputSection<ELFT> &BssSec);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000158
159 void finalize() override {
160 this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
161 this->Header.sh_link = StrTabSec.getSectionIndex();
162 this->Header.sh_info = NumLocals + 1;
163 }
164
165 void writeTo(uint8_t *Buf) override;
166
167 const SymbolTable &getSymTable() const { return Table; }
168
169 void addSymbol(StringRef Name, bool isLocal = false) {
170 StrTabSec.add(Name);
171 ++NumVisible;
172 if (isLocal)
173 ++NumLocals;
174 }
175
Davide Italianoe44456b2015-09-23 01:50:53 +0000176 StringTableSection<ELFT::Is64Bits> &getStrTabSec() const { return StrTabSec; }
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000177 unsigned getNumSymbols() const { return NumVisible + 1; }
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000178
179private:
180 SymbolTable &Table;
181 StringTableSection<ELFT::Is64Bits> &StrTabSec;
182 unsigned NumVisible = 0;
183 unsigned NumLocals = 0;
Rafael Espindolac2d21192015-09-23 18:25:05 +0000184 const OutputSection<ELFT> &BssSec;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000185};
186
187template <class ELFT>
188class RelocationSection final : public OutputSectionBase<ELFT::Is64Bits> {
189 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
190 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
191
192public:
193 RelocationSection(SymbolTableSection<ELFT> &DynSymSec,
Rafael Espindola35c6af32015-09-25 17:19:10 +0000194 const GotSection<ELFT> &GotSec, bool IsRela);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000195 void addReloc(const DynamicReloc<ELFT> &Reloc) { Relocs.push_back(Reloc); }
196 void finalize() override;
197 void writeTo(uint8_t *Buf) override;
198 bool hasRelocs() const { return !Relocs.empty(); }
199 bool isRela() const { return IsRela; }
200
201private:
202 std::vector<DynamicReloc<ELFT>> Relocs;
203 SymbolTableSection<ELFT> &DynSymSec;
204 const GotSection<ELFT> &GotSec;
205 const bool IsRela;
206};
207
208template <class ELFT>
209class OutputSection final : public OutputSectionBase<ELFT::Is64Bits> {
210public:
211 typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
212 typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
213 typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
214 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
215 typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
216 OutputSection(const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec,
Rafael Espindolac2d21192015-09-23 18:25:05 +0000217 const OutputSection<ELFT> &BssSec, StringRef Name,
Rafael Espindola35c6af32015-09-25 17:19:10 +0000218 uint32_t sh_type, uintX_t sh_flags);
Rafael Espindola71675852015-09-22 00:16:19 +0000219 void addSection(InputSection<ELFT> *C);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000220 void writeTo(uint8_t *Buf) override;
221
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000222private:
Rafael Espindola71675852015-09-22 00:16:19 +0000223 std::vector<InputSection<ELFT> *> Sections;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000224 const PltSection<ELFT> &PltSec;
225 const GotSection<ELFT> &GotSec;
Rafael Espindolac2d21192015-09-23 18:25:05 +0000226 const OutputSection<ELFT> &BssSec;
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000227};
228
229template <bool Is64Bits>
230class InterpSection final : public OutputSectionBase<Is64Bits> {
231public:
232 InterpSection();
233
234 void writeTo(uint8_t *Buf);
235};
236
237template <bool Is64Bits>
238class StringTableSection final : public OutputSectionBase<Is64Bits> {
239public:
240 typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
Rafael Espindola35c6af32015-09-25 17:19:10 +0000241 StringTableSection(bool Dynamic);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000242 void add(StringRef S) { StrTabBuilder.add(S); }
243 size_t getFileOff(StringRef S) const { return StrTabBuilder.getOffset(S); }
244 StringRef data() const { return StrTabBuilder.data(); }
245 void writeTo(uint8_t *Buf) override;
246
247 void finalize() override {
248 StrTabBuilder.finalize(llvm::StringTableBuilder::ELF);
249 this->Header.sh_size = StrTabBuilder.data().size();
250 }
251
252 bool isDynamic() const { return Dynamic; }
253
254private:
255 const bool Dynamic;
256 llvm::StringTableBuilder StrTabBuilder;
257};
258
259template <class ELFT>
260class HashTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
261 typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
262
263public:
Rafael Espindola35c6af32015-09-25 17:19:10 +0000264 HashTableSection(SymbolTableSection<ELFT> &DynSymSec);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000265 void addSymbol(SymbolBody *S);
266
267 void finalize() override {
268 this->Header.sh_link = DynSymSec.getSectionIndex();
269
270 assert(DynSymSec.getNumSymbols() == Hashes.size() + 1);
271 unsigned NumEntries = 2; // nbucket and nchain.
272 NumEntries += DynSymSec.getNumSymbols(); // The chain entries.
273
274 // Create as many buckets as there are symbols.
275 // FIXME: This is simplistic. We can try to optimize it, but implementing
276 // support for SHT_GNU_HASH is probably even more profitable.
277 NumEntries += DynSymSec.getNumSymbols();
278 this->Header.sh_size = NumEntries * sizeof(Elf_Word);
279 }
280
281 void writeTo(uint8_t *Buf) override {
282 unsigned NumSymbols = DynSymSec.getNumSymbols();
283 auto *P = reinterpret_cast<Elf_Word *>(Buf);
284 *P++ = NumSymbols; // nbucket
285 *P++ = NumSymbols; // nchain
286
287 Elf_Word *Buckets = P;
288 Elf_Word *Chains = P + NumSymbols;
289
290 for (unsigned I = 1; I < NumSymbols; ++I) {
291 uint32_t Hash = Hashes[I - 1] % NumSymbols;
292 Chains[I] = Buckets[Hash];
293 Buckets[Hash] = I;
294 }
295 }
296
297 SymbolTableSection<ELFT> &getDynSymSec() { return DynSymSec; }
298
299private:
300 uint32_t hash(StringRef Name) {
301 uint32_t H = 0;
302 for (char C : Name) {
303 H = (H << 4) + C;
304 uint32_t G = H & 0xf0000000;
305 if (G)
306 H ^= G >> 24;
307 H &= ~G;
308 }
309 return H;
310 }
311 SymbolTableSection<ELFT> &DynSymSec;
312 std::vector<uint32_t> Hashes;
313};
314
315template <class ELFT>
316class DynamicSection final : public OutputSectionBase<ELFT::Is64Bits> {
317 typedef OutputSectionBase<ELFT::Is64Bits> Base;
318 typedef typename Base::HeaderT HeaderT;
319
320public:
321 DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec,
Rafael Espindola35c6af32015-09-25 17:19:10 +0000322 RelocationSection<ELFT> &RelaDynSec);
Rafael Espindola5805c4f2015-09-21 21:38:08 +0000323 void finalize() override;
324 void writeTo(uint8_t *Buf) override;
325
326private:
327 HashTableSection<ELFT> &HashSec;
328 SymbolTableSection<ELFT> &DynSymSec;
329 StringTableSection<ELFT::Is64Bits> &DynStrSec;
330 RelocationSection<ELFT> &RelaDynSec;
331 SymbolTable &SymTab;
332};
333}
334}
335#endif