| 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 | |