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