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 classof(const SectionBase * s)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 writeHeaderTo(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 crelHeader = 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; OutputDescfinal140 OutputDesc(Ctx &ctx, StringRef name, uint32_t type, uint64_t flags) 141 : SectionCommand(OutputSectionKind), osec(ctx, name, type, flags) {} 142 classoffinal143 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 SectionClassfinal155 SectionClass(StringRef name) 156 : SectionBase(Class, nullptr, name, 0, 0, 0, 0, 0, 0) {} classoffinal157 static bool classof(const SectionBase *s) { return s->kind() == Class; } 158 }; 159 160 struct SectionClassDesc : SectionCommand { 161 SectionClass sc; 162 SectionClassDescSectionClassDesc163 SectionClassDesc(StringRef name) : SectionCommand(ClassKind), sc(name) {} 164 classofSectionClassDesc165 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 getHeaderSize(Ctx &); 176 } // namespace lld::elf 177 178 #endif 179