xref: /freebsd/contrib/llvm-project/lld/ELF/OutputSections.h (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
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