179 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLD_ELF_OUTPUT_SECTIONS_H10#define LLD_ELF_OUTPUT_SECTIONS_H11 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 20namespace lld::elf {21 22struct PhdrEntry;23 24struct CompressedData {25 std::unique_ptr<SmallVector<uint8_t, 0>[]> shards;26 uint32_t type = 0;27 uint32_t numShards = 0;28 uint32_t checksum = 0;29 uint64_t uncompressedSize;30};31 32// This represents a section in an output file.33// It is composed of multiple InputSections.34// The writer creates multiple OutputSections and assign them unique,35// non-overlapping file offsets and VAs.36class OutputSection final : public SectionBase {37public:38 OutputSection(Ctx &, StringRef name, uint32_t type, uint64_t flags);39 40 static bool classof(const SectionBase *s) {41 return s->kind() == SectionBase::Output;42 }43 44 uint64_t getLMA() const;45 template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr);46 47 Ctx &ctx;48 uint32_t sectionIndex = UINT32_MAX;49 unsigned sortRank;50 51 uint32_t getPhdrFlags() const;52 53 // Pointer to the PT_LOAD segment, which this section resides in. This field54 // is used to correctly compute file offset of a section. When two sections55 // share the same load segment, difference between their file offsets should56 // be equal to difference between their virtual addresses. To compute some57 // section offset we use the following formula: Off = Off_first + VA -58 // VA_first, where Off_first and VA_first is file offset and VA of first59 // section in PT_LOAD.60 PhdrEntry *ptLoad = nullptr;61 62 // Pointer to a relocation section for this section. Usually nullptr because63 // we consume relocations, but if --emit-relocs is specified (which is rare),64 // it may have a non-null value.65 OutputSection *relocationSection = nullptr;66 67 // Initially this field is the number of InputSections that have been added to68 // the OutputSection so far. Later on, after a call to assignAddresses, it69 // corresponds to the Elf_Shdr member.70 uint64_t size = 0;71 72 // The following fields correspond to Elf_Shdr members.73 uint64_t offset = 0;74 uint64_t addr = 0;75 uint32_t shName = 0;76 77 void recordSection(InputSectionBase *isec);78 void commitSection(InputSection *isec);79 void finalizeInputSections();80 81 // The following members are normally only used in linker scripts.82 MemoryRegion *memRegion = nullptr;83 MemoryRegion *lmaRegion = nullptr;84 Expr addrExpr;85 Expr alignExpr;86 Expr lmaExpr;87 Expr subalignExpr;88 89 // Used by non-alloc SHT_CREL to hold the header and content byte stream.90 uint64_t crelHeader = 0;91 SmallVector<char, 0> crelBody;92 93 SmallVector<SectionCommand *, 0> commands;94 SmallVector<StringRef, 0> phdrs;95 std::optional<std::array<uint8_t, 4>> filler;96 ConstraintKind constraint = ConstraintKind::NoConstraint;97 std::string location;98 std::string memoryRegionName;99 std::string lmaRegionName;100 bool nonAlloc = false;101 bool typeIsSet = false;102 bool expressionsUseSymbols = false;103 bool usedInExpression = false;104 bool inOverlay = false;105 bool firstInOverlay = false;106 107 // Tracks whether the section has ever had an input section added to it, even108 // if the section was later removed (e.g. because it is a synthetic section109 // that wasn't needed). This is needed for orphan placement.110 bool hasInputSections = false;111 112 // The output section description is specified between DATA_SEGMENT_ALIGN and113 // DATA_RELRO_END.114 bool relro = false;115 116 template <bool is64> void finalizeNonAllocCrel(Ctx &);117 void finalize(Ctx &);118 template <class ELFT>119 void writeTo(Ctx &, uint8_t *buf, llvm::parallel::TaskGroup &tg);120 // Check that the addends for dynamic relocations were written correctly.121 void checkDynRelAddends(Ctx &);122 template <class ELFT> void maybeCompress(Ctx &);123 124 void sort(llvm::function_ref<int(InputSectionBase *s)> order);125 void sortInitFini();126 void sortCtorsDtors();127 128 std::array<uint8_t, 4> getFiller(Ctx &);129 130 // Used for implementation of --compress-debug-sections and131 // --compress-sections.132 CompressedData compressed;133 134private:135 SmallVector<InputSection *, 0> storage;136};137 138struct OutputDesc final : SectionCommand {139 OutputSection osec;140 OutputDesc(Ctx &ctx, StringRef name, uint32_t type, uint64_t flags)141 : SectionCommand(OutputSectionKind), osec(ctx, name, type, flags) {}142 143 static bool classof(const SectionCommand *c) {144 return c->kind == OutputSectionKind;145 }146};147 148// This represents a CLASS(class_name) { ... } that can be referenced by output149// section descriptions. If referenced more than once, the sections can be150// spilled to the next reference like --enable-non-contiguous-regions.151struct SectionClass final : public SectionBase {152 SmallVector<InputSectionDescription *, 0> commands;153 bool assigned = false;154 155 SectionClass(StringRef name)156 : SectionBase(Class, nullptr, name, 0, 0, 0, 0, 0, 0) {}157 static bool classof(const SectionBase *s) { return s->kind() == Class; }158};159 160struct SectionClassDesc : SectionCommand {161 SectionClass sc;162 163 SectionClassDesc(StringRef name) : SectionCommand(ClassKind), sc(name) {}164 165 static bool classof(const SectionCommand *c) { return c->kind == ClassKind; }166};167 168int getPriority(StringRef s);169 170InputSection *getFirstInputSection(const OutputSection *os);171llvm::ArrayRef<InputSection *>172getInputSections(const OutputSection &os,173 SmallVector<InputSection *, 0> &storage);174 175uint64_t getHeaderSize(Ctx &);176} // namespace lld::elf177 178#endif179