10b57cec5SDimitry Andric //===- OutputSections.h -----------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLD_ELF_OUTPUT_SECTIONS_H 100b57cec5SDimitry Andric #define LLD_ELF_OUTPUT_SECTIONS_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "InputSection.h" 130b57cec5SDimitry Andric #include "LinkerScript.h" 140b57cec5SDimitry Andric #include "lld/Common/LLVM.h" 15bdd1243dSDimitry Andric #include "llvm/Support/Compiler.h" 16bdd1243dSDimitry Andric #include "llvm/Support/Parallel.h" 1781ad6265SDimitry Andric 180b57cec5SDimitry Andric #include <array> 190b57cec5SDimitry Andric 20bdd1243dSDimitry Andric namespace lld::elf { 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric struct PhdrEntry; 230b57cec5SDimitry Andric 2404eeddc0SDimitry Andric struct CompressedData { 2504eeddc0SDimitry Andric std::unique_ptr<SmallVector<uint8_t, 0>[]> shards; 260fca6ea1SDimitry Andric uint32_t type = 0; 2704eeddc0SDimitry Andric uint32_t numShards = 0; 2804eeddc0SDimitry Andric uint32_t checksum = 0; 2904eeddc0SDimitry Andric uint64_t uncompressedSize; 3004eeddc0SDimitry Andric }; 3104eeddc0SDimitry Andric 320b57cec5SDimitry Andric // This represents a section in an output file. 330b57cec5SDimitry Andric // It is composed of multiple InputSections. 340b57cec5SDimitry Andric // The writer creates multiple OutputSections and assign them unique, 350b57cec5SDimitry Andric // non-overlapping file offsets and VAs. 3681ad6265SDimitry Andric class OutputSection final : public SectionBase { 370b57cec5SDimitry Andric public: 380b57cec5SDimitry Andric OutputSection(StringRef name, uint32_t type, uint64_t flags); 390b57cec5SDimitry Andric classof(const SectionBase * s)400b57cec5SDimitry Andric static bool classof(const SectionBase *s) { 410b57cec5SDimitry Andric return s->kind() == SectionBase::Output; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric getLMA()440b57cec5SDimitry Andric uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; } 450b57cec5SDimitry Andric template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric uint32_t sectionIndex = UINT32_MAX; 480b57cec5SDimitry Andric unsigned sortRank; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric uint32_t getPhdrFlags() const; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric // Pointer to the PT_LOAD segment, which this section resides in. This field 530b57cec5SDimitry Andric // is used to correctly compute file offset of a section. When two sections 540b57cec5SDimitry Andric // share the same load segment, difference between their file offsets should 550b57cec5SDimitry Andric // be equal to difference between their virtual addresses. To compute some 560b57cec5SDimitry Andric // section offset we use the following formula: Off = Off_first + VA - 570b57cec5SDimitry Andric // VA_first, where Off_first and VA_first is file offset and VA of first 580b57cec5SDimitry Andric // section in PT_LOAD. 590b57cec5SDimitry Andric PhdrEntry *ptLoad = nullptr; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // Pointer to a relocation section for this section. Usually nullptr because 620b57cec5SDimitry Andric // we consume relocations, but if --emit-relocs is specified (which is rare), 630b57cec5SDimitry Andric // it may have a non-null value. 640b57cec5SDimitry Andric OutputSection *relocationSection = nullptr; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric // Initially this field is the number of InputSections that have been added to 670b57cec5SDimitry Andric // the OutputSection so far. Later on, after a call to assignAddresses, it 680b57cec5SDimitry Andric // corresponds to the Elf_Shdr member. 690b57cec5SDimitry Andric uint64_t size = 0; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric // The following fields correspond to Elf_Shdr members. 720b57cec5SDimitry Andric uint64_t offset = 0; 730b57cec5SDimitry Andric uint64_t addr = 0; 740b57cec5SDimitry Andric uint32_t shName = 0; 750b57cec5SDimitry Andric 7685868e8aSDimitry Andric void recordSection(InputSectionBase *isec); 7785868e8aSDimitry Andric void commitSection(InputSection *isec); 780fca6ea1SDimitry Andric void finalizeInputSections(LinkerScript *script = nullptr); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // The following members are normally only used in linker scripts. 810b57cec5SDimitry Andric MemoryRegion *memRegion = nullptr; 820b57cec5SDimitry Andric MemoryRegion *lmaRegion = nullptr; 830b57cec5SDimitry Andric Expr addrExpr; 840b57cec5SDimitry Andric Expr alignExpr; 850b57cec5SDimitry Andric Expr lmaExpr; 860b57cec5SDimitry Andric Expr subalignExpr; 87*52418fc2SDimitry Andric 88*52418fc2SDimitry Andric // Used by non-alloc SHT_CREL to hold the header and content byte stream. 89*52418fc2SDimitry Andric uint64_t crelHeader = 0; 90*52418fc2SDimitry Andric SmallVector<char, 0> crelBody; 91*52418fc2SDimitry Andric 9204eeddc0SDimitry Andric SmallVector<SectionCommand *, 0> commands; 9304eeddc0SDimitry Andric SmallVector<StringRef, 0> phdrs; 94bdd1243dSDimitry Andric std::optional<std::array<uint8_t, 4>> filler; 950b57cec5SDimitry Andric ConstraintKind constraint = ConstraintKind::NoConstraint; 960b57cec5SDimitry Andric std::string location; 970b57cec5SDimitry Andric std::string memoryRegionName; 980b57cec5SDimitry Andric std::string lmaRegionName; 990b57cec5SDimitry Andric bool nonAlloc = false; 10081ad6265SDimitry Andric bool typeIsSet = false; 1010b57cec5SDimitry Andric bool expressionsUseSymbols = false; 1020b57cec5SDimitry Andric bool usedInExpression = false; 1030b57cec5SDimitry Andric bool inOverlay = false; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // Tracks whether the section has ever had an input section added to it, even 1060b57cec5SDimitry Andric // if the section was later removed (e.g. because it is a synthetic section 1070b57cec5SDimitry Andric // that wasn't needed). This is needed for orphan placement. 1080b57cec5SDimitry Andric bool hasInputSections = false; 1090b57cec5SDimitry Andric 11081ad6265SDimitry Andric // The output section description is specified between DATA_SEGMENT_ALIGN and 11181ad6265SDimitry Andric // DATA_RELRO_END. 11281ad6265SDimitry Andric bool relro = false; 11381ad6265SDimitry Andric 114*52418fc2SDimitry Andric template <bool is64> void finalizeNonAllocCrel(); 1150b57cec5SDimitry Andric void finalize(); 116bdd1243dSDimitry Andric template <class ELFT> 117bdd1243dSDimitry Andric void writeTo(uint8_t *buf, llvm::parallel::TaskGroup &tg); 118fe6060f1SDimitry Andric // Check that the addends for dynamic relocations were written correctly. 119fe6060f1SDimitry Andric void checkDynRelAddends(const uint8_t *bufStart); 1200b57cec5SDimitry Andric template <class ELFT> void maybeCompress(); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric void sort(llvm::function_ref<int(InputSectionBase *s)> order); 1230b57cec5SDimitry Andric void sortInitFini(); 1240b57cec5SDimitry Andric void sortCtorsDtors(); 1250b57cec5SDimitry Andric 1260fca6ea1SDimitry Andric // Used for implementation of --compress-debug-sections and 1270fca6ea1SDimitry Andric // --compress-sections. 1280fca6ea1SDimitry Andric CompressedData compressed; 1290fca6ea1SDimitry Andric 1300b57cec5SDimitry Andric private: 131bdd1243dSDimitry Andric SmallVector<InputSection *, 0> storage; 132bdd1243dSDimitry Andric 1330b57cec5SDimitry Andric std::array<uint8_t, 4> getFiller(); 1340b57cec5SDimitry Andric }; 1350b57cec5SDimitry Andric 13681ad6265SDimitry Andric struct OutputDesc final : SectionCommand { 13781ad6265SDimitry Andric OutputSection osec; OutputDescfinal13881ad6265SDimitry Andric OutputDesc(StringRef name, uint32_t type, uint64_t flags) 13981ad6265SDimitry Andric : SectionCommand(OutputSectionKind), osec(name, type, flags) {} 14081ad6265SDimitry Andric classoffinal14181ad6265SDimitry Andric static bool classof(const SectionCommand *c) { 14281ad6265SDimitry Andric return c->kind == OutputSectionKind; 14381ad6265SDimitry Andric } 14481ad6265SDimitry Andric }; 14581ad6265SDimitry Andric 1460b57cec5SDimitry Andric int getPriority(StringRef s); 1470b57cec5SDimitry Andric 1485ffd83dbSDimitry Andric InputSection *getFirstInputSection(const OutputSection *os); 149753f127fSDimitry Andric llvm::ArrayRef<InputSection *> 150753f127fSDimitry Andric getInputSections(const OutputSection &os, 151753f127fSDimitry Andric SmallVector<InputSection *, 0> &storage); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric // All output sections that are handled by the linker specially are 1540b57cec5SDimitry Andric // globally accessible. Writer initializes them, so don't use them 1550b57cec5SDimitry Andric // until Writer is initialized. 1560b57cec5SDimitry Andric struct Out { 1570b57cec5SDimitry Andric static uint8_t *bufferStart; 1580b57cec5SDimitry Andric static PhdrEntry *tlsPhdr; 1590b57cec5SDimitry Andric static OutputSection *elfHeader; 1600b57cec5SDimitry Andric static OutputSection *programHeaders; 1610b57cec5SDimitry Andric static OutputSection *preinitArray; 1620b57cec5SDimitry Andric static OutputSection *initArray; 1630b57cec5SDimitry Andric static OutputSection *finiArray; 1640b57cec5SDimitry Andric }; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric uint64_t getHeaderSize(); 1670b57cec5SDimitry Andric 168bdd1243dSDimitry Andric LLVM_LIBRARY_VISIBILITY extern llvm::SmallVector<OutputSection *, 0> 169bdd1243dSDimitry Andric outputSections; 170bdd1243dSDimitry Andric } // namespace lld::elf 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric #endif 173