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(); |
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 | SmallVector<SectionCommand *, 0> commands; |
88 | SmallVector<StringRef, 0> phdrs; |
89 | std::optional<std::array<uint8_t, 4>> filler; |
90 | ConstraintKind constraint = ConstraintKind::NoConstraint; |
91 | std::string location; |
92 | std::string memoryRegionName; |
93 | std::string lmaRegionName; |
94 | bool nonAlloc = false; |
95 | bool typeIsSet = false; |
96 | bool expressionsUseSymbols = false; |
97 | bool usedInExpression = false; |
98 | bool inOverlay = false; |
99 | |
100 | // Tracks whether the section has ever had an input section added to it, even |
101 | // if the section was later removed (e.g. because it is a synthetic section |
102 | // that wasn't needed). This is needed for orphan placement. |
103 | bool hasInputSections = false; |
104 | |
105 | // The output section description is specified between DATA_SEGMENT_ALIGN and |
106 | // DATA_RELRO_END. |
107 | bool relro = false; |
108 | |
109 | void finalize(); |
110 | template <class ELFT> |
111 | void writeTo(uint8_t *buf, llvm::parallel::TaskGroup &tg); |
112 | // Check that the addends for dynamic relocations were written correctly. |
113 | void checkDynRelAddends(const uint8_t *bufStart); |
114 | template <class ELFT> void maybeCompress(); |
115 | |
116 | void sort(llvm::function_ref<int(InputSectionBase *s)> order); |
117 | void sortInitFini(); |
118 | void sortCtorsDtors(); |
119 | |
120 | // Used for implementation of --compress-debug-sections and |
121 | // --compress-sections. |
122 | CompressedData compressed; |
123 | |
124 | private: |
125 | SmallVector<InputSection *, 0> storage; |
126 | |
127 | std::array<uint8_t, 4> getFiller(); |
128 | }; |
129 | |
130 | struct OutputDesc final : SectionCommand { |
131 | OutputSection osec; |
132 | OutputDesc(StringRef name, uint32_t type, uint64_t flags) |
133 | : SectionCommand(OutputSectionKind), osec(name, type, flags) {} |
134 | |
135 | static bool classof(const SectionCommand *c) { |
136 | return c->kind == OutputSectionKind; |
137 | } |
138 | }; |
139 | |
140 | int getPriority(StringRef s); |
141 | |
142 | InputSection *getFirstInputSection(const OutputSection *os); |
143 | llvm::ArrayRef<InputSection *> |
144 | getInputSections(const OutputSection &os, |
145 | SmallVector<InputSection *, 0> &storage); |
146 | |
147 | // All output sections that are handled by the linker specially are |
148 | // globally accessible. Writer initializes them, so don't use them |
149 | // until Writer is initialized. |
150 | struct Out { |
151 | static uint8_t *bufferStart; |
152 | static PhdrEntry *tlsPhdr; |
153 | static OutputSection *; |
154 | static OutputSection *; |
155 | static OutputSection *preinitArray; |
156 | static OutputSection *initArray; |
157 | static OutputSection *finiArray; |
158 | }; |
159 | |
160 | uint64_t (); |
161 | |
162 | LLVM_LIBRARY_VISIBILITY extern llvm::SmallVector<OutputSection *, 0> |
163 | outputSections; |
164 | } // namespace lld::elf |
165 | |
166 | #endif |
167 | |