xref: /freebsd/contrib/llvm-project/lld/ELF/OutputSections.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
15*bdd1243dSDimitry Andric #include "llvm/Support/Compiler.h"
16*bdd1243dSDimitry Andric #include "llvm/Support/Parallel.h"
1781ad6265SDimitry Andric 
180b57cec5SDimitry Andric #include <array>
190b57cec5SDimitry Andric 
20*bdd1243dSDimitry 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;
2604eeddc0SDimitry Andric   uint32_t numShards = 0;
2704eeddc0SDimitry Andric   uint32_t checksum = 0;
2804eeddc0SDimitry Andric   uint64_t uncompressedSize;
2904eeddc0SDimitry Andric };
3004eeddc0SDimitry Andric 
310b57cec5SDimitry Andric // This represents a section in an output file.
320b57cec5SDimitry Andric // It is composed of multiple InputSections.
330b57cec5SDimitry Andric // The writer creates multiple OutputSections and assign them unique,
340b57cec5SDimitry Andric // non-overlapping file offsets and VAs.
3581ad6265SDimitry Andric class OutputSection final : public SectionBase {
360b57cec5SDimitry Andric public:
370b57cec5SDimitry Andric   OutputSection(StringRef name, uint32_t type, uint64_t flags);
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   static bool classof(const SectionBase *s) {
400b57cec5SDimitry Andric     return s->kind() == SectionBase::Output;
410b57cec5SDimitry Andric   }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; }
440b57cec5SDimitry Andric   template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr);
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   uint32_t sectionIndex = UINT32_MAX;
470b57cec5SDimitry Andric   unsigned sortRank;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   uint32_t getPhdrFlags() const;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   // Pointer to the PT_LOAD segment, which this section resides in. This field
520b57cec5SDimitry Andric   // is used to correctly compute file offset of a section. When two sections
530b57cec5SDimitry Andric   // share the same load segment, difference between their file offsets should
540b57cec5SDimitry Andric   // be equal to difference between their virtual addresses. To compute some
550b57cec5SDimitry Andric   // section offset we use the following formula: Off = Off_first + VA -
560b57cec5SDimitry Andric   // VA_first, where Off_first and VA_first is file offset and VA of first
570b57cec5SDimitry Andric   // section in PT_LOAD.
580b57cec5SDimitry Andric   PhdrEntry *ptLoad = nullptr;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   // Pointer to a relocation section for this section. Usually nullptr because
610b57cec5SDimitry Andric   // we consume relocations, but if --emit-relocs is specified (which is rare),
620b57cec5SDimitry Andric   // it may have a non-null value.
630b57cec5SDimitry Andric   OutputSection *relocationSection = nullptr;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   // Initially this field is the number of InputSections that have been added to
660b57cec5SDimitry Andric   // the OutputSection so far. Later on, after a call to assignAddresses, it
670b57cec5SDimitry Andric   // corresponds to the Elf_Shdr member.
680b57cec5SDimitry Andric   uint64_t size = 0;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   // The following fields correspond to Elf_Shdr members.
710b57cec5SDimitry Andric   uint64_t offset = 0;
720b57cec5SDimitry Andric   uint64_t addr = 0;
730b57cec5SDimitry Andric   uint32_t shName = 0;
740b57cec5SDimitry Andric 
7585868e8aSDimitry Andric   void recordSection(InputSectionBase *isec);
7685868e8aSDimitry Andric   void commitSection(InputSection *isec);
7785868e8aSDimitry Andric   void finalizeInputSections();
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   // The following members are normally only used in linker scripts.
800b57cec5SDimitry Andric   MemoryRegion *memRegion = nullptr;
810b57cec5SDimitry Andric   MemoryRegion *lmaRegion = nullptr;
820b57cec5SDimitry Andric   Expr addrExpr;
830b57cec5SDimitry Andric   Expr alignExpr;
840b57cec5SDimitry Andric   Expr lmaExpr;
850b57cec5SDimitry Andric   Expr subalignExpr;
8604eeddc0SDimitry Andric   SmallVector<SectionCommand *, 0> commands;
8704eeddc0SDimitry Andric   SmallVector<StringRef, 0> phdrs;
88*bdd1243dSDimitry Andric   std::optional<std::array<uint8_t, 4>> filler;
890b57cec5SDimitry Andric   ConstraintKind constraint = ConstraintKind::NoConstraint;
900b57cec5SDimitry Andric   std::string location;
910b57cec5SDimitry Andric   std::string memoryRegionName;
920b57cec5SDimitry Andric   std::string lmaRegionName;
930b57cec5SDimitry Andric   bool nonAlloc = false;
9481ad6265SDimitry Andric   bool typeIsSet = false;
950b57cec5SDimitry Andric   bool expressionsUseSymbols = false;
960b57cec5SDimitry Andric   bool usedInExpression = false;
970b57cec5SDimitry Andric   bool inOverlay = false;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   // Tracks whether the section has ever had an input section added to it, even
1000b57cec5SDimitry Andric   // if the section was later removed (e.g. because it is a synthetic section
1010b57cec5SDimitry Andric   // that wasn't needed). This is needed for orphan placement.
1020b57cec5SDimitry Andric   bool hasInputSections = false;
1030b57cec5SDimitry Andric 
10481ad6265SDimitry Andric   // The output section description is specified between DATA_SEGMENT_ALIGN and
10581ad6265SDimitry Andric   // DATA_RELRO_END.
10681ad6265SDimitry Andric   bool relro = false;
10781ad6265SDimitry Andric 
1080b57cec5SDimitry Andric   void finalize();
109*bdd1243dSDimitry Andric   template <class ELFT>
110*bdd1243dSDimitry Andric   void writeTo(uint8_t *buf, llvm::parallel::TaskGroup &tg);
111fe6060f1SDimitry Andric   // Check that the addends for dynamic relocations were written correctly.
112fe6060f1SDimitry Andric   void checkDynRelAddends(const uint8_t *bufStart);
1130b57cec5SDimitry Andric   template <class ELFT> void maybeCompress();
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   void sort(llvm::function_ref<int(InputSectionBase *s)> order);
1160b57cec5SDimitry Andric   void sortInitFini();
1170b57cec5SDimitry Andric   void sortCtorsDtors();
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric private:
120*bdd1243dSDimitry Andric   SmallVector<InputSection *, 0> storage;
121*bdd1243dSDimitry Andric 
1220b57cec5SDimitry Andric   // Used for implementation of --compress-debug-sections option.
12304eeddc0SDimitry Andric   CompressedData compressed;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   std::array<uint8_t, 4> getFiller();
1260b57cec5SDimitry Andric };
1270b57cec5SDimitry Andric 
12881ad6265SDimitry Andric struct OutputDesc final : SectionCommand {
12981ad6265SDimitry Andric   OutputSection osec;
13081ad6265SDimitry Andric   OutputDesc(StringRef name, uint32_t type, uint64_t flags)
13181ad6265SDimitry Andric       : SectionCommand(OutputSectionKind), osec(name, type, flags) {}
13281ad6265SDimitry Andric 
13381ad6265SDimitry Andric   static bool classof(const SectionCommand *c) {
13481ad6265SDimitry Andric     return c->kind == OutputSectionKind;
13581ad6265SDimitry Andric   }
13681ad6265SDimitry Andric };
13781ad6265SDimitry Andric 
1380b57cec5SDimitry Andric int getPriority(StringRef s);
1390b57cec5SDimitry Andric 
1405ffd83dbSDimitry Andric InputSection *getFirstInputSection(const OutputSection *os);
141753f127fSDimitry Andric llvm::ArrayRef<InputSection *>
142753f127fSDimitry Andric getInputSections(const OutputSection &os,
143753f127fSDimitry Andric                  SmallVector<InputSection *, 0> &storage);
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric // All output sections that are handled by the linker specially are
1460b57cec5SDimitry Andric // globally accessible. Writer initializes them, so don't use them
1470b57cec5SDimitry Andric // until Writer is initialized.
1480b57cec5SDimitry Andric struct Out {
1490b57cec5SDimitry Andric   static uint8_t *bufferStart;
1500b57cec5SDimitry Andric   static PhdrEntry *tlsPhdr;
1510b57cec5SDimitry Andric   static OutputSection *elfHeader;
1520b57cec5SDimitry Andric   static OutputSection *programHeaders;
1530b57cec5SDimitry Andric   static OutputSection *preinitArray;
1540b57cec5SDimitry Andric   static OutputSection *initArray;
1550b57cec5SDimitry Andric   static OutputSection *finiArray;
1560b57cec5SDimitry Andric };
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric uint64_t getHeaderSize();
1590b57cec5SDimitry Andric 
160*bdd1243dSDimitry Andric LLVM_LIBRARY_VISIBILITY extern llvm::SmallVector<OutputSection *, 0>
161*bdd1243dSDimitry Andric     outputSections;
162*bdd1243dSDimitry Andric } // namespace lld::elf
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric #endif
165