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(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 { return ptLoad ? addr + ptLoad->lmaOffset : addr; } |
45 | template <typename ELFT> void (typename ELFT::Shdr *sHdr); |
46 | |
47 | uint32_t sectionIndex = UINT32_MAX; |
48 | unsigned sortRank; |
49 | |
50 | uint32_t getPhdrFlags() const; |
51 | |
52 | // Pointer to the PT_LOAD segment, which this section resides in. This field |
53 | // is used to correctly compute file offset of a section. When two sections |
54 | // share the same load segment, difference between their file offsets should |
55 | // be equal to difference between their virtual addresses. To compute some |
56 | // section offset we use the following formula: Off = Off_first + VA - |
57 | // VA_first, where Off_first and VA_first is file offset and VA of first |
58 | // section in PT_LOAD. |
59 | PhdrEntry *ptLoad = nullptr; |
60 | |
61 | // Pointer to a relocation section for this section. Usually nullptr because |
62 | // we consume relocations, but if --emit-relocs is specified (which is rare), |
63 | // it may have a non-null value. |
64 | OutputSection *relocationSection = nullptr; |
65 | |
66 | // Initially this field is the number of InputSections that have been added to |
67 | // the OutputSection so far. Later on, after a call to assignAddresses, it |
68 | // corresponds to the Elf_Shdr member. |
69 | uint64_t size = 0; |
70 | |
71 | // The following fields correspond to Elf_Shdr members. |
72 | uint64_t offset = 0; |
73 | uint64_t addr = 0; |
74 | uint32_t shName = 0; |
75 | |
76 | void recordSection(InputSectionBase *isec); |
77 | void commitSection(InputSection *isec); |
78 | void finalizeInputSections(LinkerScript *script = nullptr); |
79 | |
80 | // The following members are normally only used in linker scripts. |
81 | MemoryRegion *memRegion = nullptr; |
82 | MemoryRegion *lmaRegion = nullptr; |
83 | Expr addrExpr; |
84 | Expr alignExpr; |
85 | Expr lmaExpr; |
86 | Expr subalignExpr; |
87 | |
88 | // Used by non-alloc SHT_CREL to hold the header and content byte stream. |
89 | uint64_t = 0; |
90 | SmallVector<char, 0> crelBody; |
91 | |
92 | SmallVector<SectionCommand *, 0> commands; |
93 | SmallVector<StringRef, 0> phdrs; |
94 | std::optional<std::array<uint8_t, 4>> filler; |
95 | ConstraintKind constraint = ConstraintKind::NoConstraint; |
96 | std::string location; |
97 | std::string memoryRegionName; |
98 | std::string lmaRegionName; |
99 | bool nonAlloc = false; |
100 | bool typeIsSet = false; |
101 | bool expressionsUseSymbols = false; |
102 | bool usedInExpression = false; |
103 | bool inOverlay = false; |
104 | |
105 | // Tracks whether the section has ever had an input section added to it, even |
106 | // if the section was later removed (e.g. because it is a synthetic section |
107 | // that wasn't needed). This is needed for orphan placement. |
108 | bool hasInputSections = false; |
109 | |
110 | // The output section description is specified between DATA_SEGMENT_ALIGN and |
111 | // DATA_RELRO_END. |
112 | bool relro = false; |
113 | |
114 | template <bool is64> void finalizeNonAllocCrel(); |
115 | void finalize(); |
116 | template <class ELFT> |
117 | void writeTo(uint8_t *buf, llvm::parallel::TaskGroup &tg); |
118 | // Check that the addends for dynamic relocations were written correctly. |
119 | void checkDynRelAddends(const uint8_t *bufStart); |
120 | template <class ELFT> void maybeCompress(); |
121 | |
122 | void sort(llvm::function_ref<int(InputSectionBase *s)> order); |
123 | void sortInitFini(); |
124 | void sortCtorsDtors(); |
125 | |
126 | // Used for implementation of --compress-debug-sections and |
127 | // --compress-sections. |
128 | CompressedData compressed; |
129 | |
130 | private: |
131 | SmallVector<InputSection *, 0> storage; |
132 | |
133 | std::array<uint8_t, 4> getFiller(); |
134 | }; |
135 | |
136 | struct OutputDesc final : SectionCommand { |
137 | OutputSection osec; |
138 | OutputDesc(StringRef name, uint32_t type, uint64_t flags) |
139 | : SectionCommand(OutputSectionKind), osec(name, type, flags) {} |
140 | |
141 | static bool classof(const SectionCommand *c) { |
142 | return c->kind == OutputSectionKind; |
143 | } |
144 | }; |
145 | |
146 | int getPriority(StringRef s); |
147 | |
148 | InputSection *getFirstInputSection(const OutputSection *os); |
149 | llvm::ArrayRef<InputSection *> |
150 | getInputSections(const OutputSection &os, |
151 | SmallVector<InputSection *, 0> &storage); |
152 | |
153 | // All output sections that are handled by the linker specially are |
154 | // globally accessible. Writer initializes them, so don't use them |
155 | // until Writer is initialized. |
156 | struct Out { |
157 | static uint8_t *bufferStart; |
158 | static PhdrEntry *tlsPhdr; |
159 | static OutputSection *; |
160 | static OutputSection *; |
161 | static OutputSection *preinitArray; |
162 | static OutputSection *initArray; |
163 | static OutputSection *finiArray; |
164 | }; |
165 | |
166 | uint64_t (); |
167 | |
168 | LLVM_LIBRARY_VISIBILITY extern llvm::SmallVector<OutputSection *, 0> |
169 | outputSections; |
170 | } // namespace lld::elf |
171 | |
172 | #endif |
173 | |