1 | //===- OutputSections.h -----------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLD_ELF_OUTPUT_SECTIONS_H |
10 | #define LLD_ELF_OUTPUT_SECTIONS_H |
11 | |
12 | #include "InputSection.h" |
13 | #include "LinkerScript.h" |
14 | #include "lld/Common/LLVM.h" |
15 | #include "llvm/Support/Compiler.h" |
16 | #include "llvm/Support/Parallel.h" |
17 | |
18 | #include <array> |
19 | |
20 | namespace lld::elf { |
21 | |
22 | struct PhdrEntry; |
23 | |
24 | struct CompressedData { |
25 | std::unique_ptr<SmallVector<uint8_t, 0>[]> shards; |
26 | uint32_t type = 0; |
27 | uint32_t numShards = 0; |
28 | uint32_t checksum = 0; |
29 | uint64_t uncompressedSize; |
30 | }; |
31 | |
32 | // This represents a section in an output file. |
33 | // It is composed of multiple InputSections. |
34 | // The writer creates multiple OutputSections and assign them unique, |
35 | // non-overlapping file offsets and VAs. |
36 | class OutputSection final : public SectionBase { |
37 | public: |
38 | OutputSection(Ctx &, StringRef name, uint32_t type, uint64_t flags); |
39 | |
40 | static bool classof(const SectionBase *s) { |
41 | return s->kind() == SectionBase::Output; |
42 | } |
43 | |
44 | uint64_t getLMA() const; |
45 | template <typename ELFT> void (typename ELFT::Shdr *sHdr); |
46 | |
47 | Ctx &ctx; |
48 | uint32_t sectionIndex = UINT32_MAX; |
49 | unsigned sortRank; |
50 | |
51 | uint32_t getPhdrFlags() const; |
52 | |
53 | // Pointer to the PT_LOAD segment, which this section resides in. This field |
54 | // is used to correctly compute file offset of a section. When two sections |
55 | // share the same load segment, difference between their file offsets should |
56 | // be equal to difference between their virtual addresses. To compute some |
57 | // section offset we use the following formula: Off = Off_first + VA - |
58 | // VA_first, where Off_first and VA_first is file offset and VA of first |
59 | // section in PT_LOAD. |
60 | PhdrEntry *ptLoad = nullptr; |
61 | |
62 | // Pointer to a relocation section for this section. Usually nullptr because |
63 | // we consume relocations, but if --emit-relocs is specified (which is rare), |
64 | // it may have a non-null value. |
65 | OutputSection *relocationSection = nullptr; |
66 | |
67 | // Initially this field is the number of InputSections that have been added to |
68 | // the OutputSection so far. Later on, after a call to assignAddresses, it |
69 | // corresponds to the Elf_Shdr member. |
70 | uint64_t size = 0; |
71 | |
72 | // The following fields correspond to Elf_Shdr members. |
73 | uint64_t offset = 0; |
74 | uint64_t addr = 0; |
75 | uint32_t shName = 0; |
76 | |
77 | void recordSection(InputSectionBase *isec); |
78 | void commitSection(InputSection *isec); |
79 | void finalizeInputSections(); |
80 | |
81 | // The following members are normally only used in linker scripts. |
82 | MemoryRegion *memRegion = nullptr; |
83 | MemoryRegion *lmaRegion = nullptr; |
84 | Expr addrExpr; |
85 | Expr alignExpr; |
86 | Expr lmaExpr; |
87 | Expr subalignExpr; |
88 | |
89 | // Used by non-alloc SHT_CREL to hold the header and content byte stream. |
90 | uint64_t = 0; |
91 | SmallVector<char, 0> crelBody; |
92 | |
93 | SmallVector<SectionCommand *, 0> commands; |
94 | SmallVector<StringRef, 0> phdrs; |
95 | std::optional<std::array<uint8_t, 4>> filler; |
96 | ConstraintKind constraint = ConstraintKind::NoConstraint; |
97 | std::string location; |
98 | std::string memoryRegionName; |
99 | std::string lmaRegionName; |
100 | bool nonAlloc = false; |
101 | bool typeIsSet = false; |
102 | bool expressionsUseSymbols = false; |
103 | bool usedInExpression = false; |
104 | bool inOverlay = false; |
105 | bool firstInOverlay = false; |
106 | |
107 | // Tracks whether the section has ever had an input section added to it, even |
108 | // if the section was later removed (e.g. because it is a synthetic section |
109 | // that wasn't needed). This is needed for orphan placement. |
110 | bool hasInputSections = false; |
111 | |
112 | // The output section description is specified between DATA_SEGMENT_ALIGN and |
113 | // DATA_RELRO_END. |
114 | bool relro = false; |
115 | |
116 | template <bool is64> void finalizeNonAllocCrel(Ctx &); |
117 | void finalize(Ctx &); |
118 | template <class ELFT> |
119 | void writeTo(Ctx &, uint8_t *buf, llvm::parallel::TaskGroup &tg); |
120 | // Check that the addends for dynamic relocations were written correctly. |
121 | void checkDynRelAddends(Ctx &); |
122 | template <class ELFT> void maybeCompress(Ctx &); |
123 | |
124 | void sort(llvm::function_ref<int(InputSectionBase *s)> order); |
125 | void sortInitFini(); |
126 | void sortCtorsDtors(); |
127 | |
128 | std::array<uint8_t, 4> getFiller(Ctx &); |
129 | |
130 | // Used for implementation of --compress-debug-sections and |
131 | // --compress-sections. |
132 | CompressedData compressed; |
133 | |
134 | private: |
135 | SmallVector<InputSection *, 0> storage; |
136 | }; |
137 | |
138 | struct OutputDesc final : SectionCommand { |
139 | OutputSection osec; |
140 | OutputDesc(Ctx &ctx, StringRef name, uint32_t type, uint64_t flags) |
141 | : SectionCommand(OutputSectionKind), osec(ctx, name, type, flags) {} |
142 | |
143 | static bool classof(const SectionCommand *c) { |
144 | return c->kind == OutputSectionKind; |
145 | } |
146 | }; |
147 | |
148 | // This represents a CLASS(class_name) { ... } that can be referenced by output |
149 | // section descriptions. If referenced more than once, the sections can be |
150 | // spilled to the next reference like --enable-non-contiguous-regions. |
151 | struct SectionClass final : public SectionBase { |
152 | SmallVector<InputSectionDescription *, 0> commands; |
153 | bool assigned = false; |
154 | |
155 | SectionClass(StringRef name) |
156 | : SectionBase(Class, nullptr, name, 0, 0, 0, 0, 0, 0) {} |
157 | static bool classof(const SectionBase *s) { return s->kind() == Class; } |
158 | }; |
159 | |
160 | struct SectionClassDesc : SectionCommand { |
161 | SectionClass sc; |
162 | |
163 | SectionClassDesc(StringRef name) : SectionCommand(ClassKind), sc(name) {} |
164 | |
165 | static bool classof(const SectionCommand *c) { return c->kind == ClassKind; } |
166 | }; |
167 | |
168 | int getPriority(StringRef s); |
169 | |
170 | InputSection *getFirstInputSection(const OutputSection *os); |
171 | llvm::ArrayRef<InputSection *> |
172 | getInputSections(const OutputSection &os, |
173 | SmallVector<InputSection *, 0> &storage); |
174 | |
175 | uint64_t (Ctx &); |
176 | } // namespace lld::elf |
177 | |
178 | #endif |
179 | |