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 "Config.h" 130b57cec5SDimitry Andric #include "InputSection.h" 140b57cec5SDimitry Andric #include "LinkerScript.h" 150b57cec5SDimitry Andric #include "Relocations.h" 160b57cec5SDimitry Andric #include "lld/Common/LLVM.h" 170b57cec5SDimitry Andric #include "llvm/MC/StringTableBuilder.h" 180b57cec5SDimitry Andric #include "llvm/Object/ELF.h" 190b57cec5SDimitry Andric #include <array> 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace lld { 220b57cec5SDimitry Andric namespace elf { 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric struct PhdrEntry; 250b57cec5SDimitry Andric class InputSection; 260b57cec5SDimitry Andric class InputSectionBase; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric // This represents a section in an output file. 290b57cec5SDimitry Andric // It is composed of multiple InputSections. 300b57cec5SDimitry Andric // The writer creates multiple OutputSections and assign them unique, 310b57cec5SDimitry Andric // non-overlapping file offsets and VAs. 320b57cec5SDimitry Andric class OutputSection final : public BaseCommand, public SectionBase { 330b57cec5SDimitry Andric public: 340b57cec5SDimitry Andric OutputSection(StringRef name, uint32_t type, uint64_t flags); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric static bool classof(const SectionBase *s) { 370b57cec5SDimitry Andric return s->kind() == SectionBase::Output; 380b57cec5SDimitry Andric } 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric static bool classof(const BaseCommand *c); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; } 430b57cec5SDimitry Andric template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric uint32_t sectionIndex = UINT32_MAX; 460b57cec5SDimitry Andric unsigned sortRank; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric uint32_t getPhdrFlags() const; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // Pointer to the PT_LOAD segment, which this section resides in. This field 510b57cec5SDimitry Andric // is used to correctly compute file offset of a section. When two sections 520b57cec5SDimitry Andric // share the same load segment, difference between their file offsets should 530b57cec5SDimitry Andric // be equal to difference between their virtual addresses. To compute some 540b57cec5SDimitry Andric // section offset we use the following formula: Off = Off_first + VA - 550b57cec5SDimitry Andric // VA_first, where Off_first and VA_first is file offset and VA of first 560b57cec5SDimitry Andric // section in PT_LOAD. 570b57cec5SDimitry Andric PhdrEntry *ptLoad = nullptr; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Pointer to a relocation section for this section. Usually nullptr because 600b57cec5SDimitry Andric // we consume relocations, but if --emit-relocs is specified (which is rare), 610b57cec5SDimitry Andric // it may have a non-null value. 620b57cec5SDimitry Andric OutputSection *relocationSection = nullptr; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric // Initially this field is the number of InputSections that have been added to 650b57cec5SDimitry Andric // the OutputSection so far. Later on, after a call to assignAddresses, it 660b57cec5SDimitry Andric // corresponds to the Elf_Shdr member. 670b57cec5SDimitry Andric uint64_t size = 0; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric // The following fields correspond to Elf_Shdr members. 700b57cec5SDimitry Andric uint64_t offset = 0; 710b57cec5SDimitry Andric uint64_t addr = 0; 720b57cec5SDimitry Andric uint32_t shName = 0; 730b57cec5SDimitry Andric 7485868e8aSDimitry Andric void recordSection(InputSectionBase *isec); 7585868e8aSDimitry Andric void commitSection(InputSection *isec); 7685868e8aSDimitry Andric void finalizeInputSections(); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // The following members are normally only used in linker scripts. 790b57cec5SDimitry Andric MemoryRegion *memRegion = nullptr; 800b57cec5SDimitry Andric MemoryRegion *lmaRegion = nullptr; 810b57cec5SDimitry Andric Expr addrExpr; 820b57cec5SDimitry Andric Expr alignExpr; 830b57cec5SDimitry Andric Expr lmaExpr; 840b57cec5SDimitry Andric Expr subalignExpr; 850b57cec5SDimitry Andric std::vector<BaseCommand *> sectionCommands; 860b57cec5SDimitry Andric std::vector<StringRef> phdrs; 870b57cec5SDimitry Andric llvm::Optional<std::array<uint8_t, 4>> filler; 880b57cec5SDimitry Andric ConstraintKind constraint = ConstraintKind::NoConstraint; 890b57cec5SDimitry Andric std::string location; 900b57cec5SDimitry Andric std::string memoryRegionName; 910b57cec5SDimitry Andric std::string lmaRegionName; 920b57cec5SDimitry Andric bool nonAlloc = false; 930b57cec5SDimitry Andric bool noload = false; 940b57cec5SDimitry Andric bool expressionsUseSymbols = false; 950b57cec5SDimitry Andric bool usedInExpression = false; 960b57cec5SDimitry Andric bool inOverlay = false; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric // Tracks whether the section has ever had an input section added to it, even 990b57cec5SDimitry Andric // if the section was later removed (e.g. because it is a synthetic section 1000b57cec5SDimitry Andric // that wasn't needed). This is needed for orphan placement. 1010b57cec5SDimitry Andric bool hasInputSections = false; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric void finalize(); 1040b57cec5SDimitry Andric template <class ELFT> void writeTo(uint8_t *buf); 1050b57cec5SDimitry Andric template <class ELFT> void maybeCompress(); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric void sort(llvm::function_ref<int(InputSectionBase *s)> order); 1080b57cec5SDimitry Andric void sortInitFini(); 1090b57cec5SDimitry Andric void sortCtorsDtors(); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric private: 1120b57cec5SDimitry Andric // Used for implementation of --compress-debug-sections option. 1130b57cec5SDimitry Andric std::vector<uint8_t> zDebugHeader; 1140b57cec5SDimitry Andric llvm::SmallVector<char, 1> compressedData; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric std::array<uint8_t, 4> getFiller(); 1170b57cec5SDimitry Andric }; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric int getPriority(StringRef s); 1200b57cec5SDimitry Andric 121*5ffd83dbSDimitry Andric InputSection *getFirstInputSection(const OutputSection *os); 122*5ffd83dbSDimitry Andric std::vector<InputSection *> getInputSections(const OutputSection *os); 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // All output sections that are handled by the linker specially are 1250b57cec5SDimitry Andric // globally accessible. Writer initializes them, so don't use them 1260b57cec5SDimitry Andric // until Writer is initialized. 1270b57cec5SDimitry Andric struct Out { 1280b57cec5SDimitry Andric static uint8_t *bufferStart; 1290b57cec5SDimitry Andric static uint8_t first; 1300b57cec5SDimitry Andric static PhdrEntry *tlsPhdr; 1310b57cec5SDimitry Andric static OutputSection *elfHeader; 1320b57cec5SDimitry Andric static OutputSection *programHeaders; 1330b57cec5SDimitry Andric static OutputSection *preinitArray; 1340b57cec5SDimitry Andric static OutputSection *initArray; 1350b57cec5SDimitry Andric static OutputSection *finiArray; 1360b57cec5SDimitry Andric }; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric } // namespace elf 1390b57cec5SDimitry Andric } // namespace lld 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric namespace lld { 1420b57cec5SDimitry Andric namespace elf { 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric uint64_t getHeaderSize(); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric extern std::vector<OutputSection *> outputSections; 1470b57cec5SDimitry Andric } // namespace elf 1480b57cec5SDimitry Andric } // namespace lld 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric #endif 151