1 //===- OutputSections.h -----------------------------------------*- C++ -*-===//
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-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLD_ELF_OUTPUT_SECTIONS_H
10 #define LLD_ELF_OUTPUT_SECTIONS_H
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"
24 struct CompressedData
{
25 std::unique_ptr
<SmallVector
<uint8_t, 0>[]> shards
;
27 uint32_t numShards
= 0;
28 uint32_t checksum
= 0;
29 uint64_t uncompressedSize
;
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.
36 class OutputSection final
: public SectionBase
{
38 OutputSection(StringRef name
, uint32_t type
, uint64_t flags
);
40 static bool classof(const SectionBase
*s
) {
41 return s
->kind() == SectionBase::Output
;
44 uint64_t getLMA() const { return ptLoad
? addr
+ ptLoad
->lmaOffset
: addr
; }
45 template <typename ELFT
> void writeHeaderTo(typename
ELFT::Shdr
*sHdr
);
47 uint32_t sectionIndex
= UINT32_MAX
;
50 uint32_t getPhdrFlags() const;
52 // Pointer to the PT_LOAD segment, which this section resides in. This field
53 // is used to correctly compute file offset of a section. When two sections
54 // share the same load segment, difference between their file offsets should
55 // be equal to difference between their virtual addresses. To compute some
56 // section offset we use the following formula: Off = Off_first + VA -
57 // VA_first, where Off_first and VA_first is file offset and VA of first
58 // section in PT_LOAD.
59 PhdrEntry
*ptLoad
= nullptr;
61 // Pointer to a relocation section for this section. Usually nullptr because
62 // we consume relocations, but if --emit-relocs is specified (which is rare),
63 // it may have a non-null value.
64 OutputSection
*relocationSection
= nullptr;
66 // Initially this field is the number of InputSections that have been added to
67 // the OutputSection so far. Later on, after a call to assignAddresses, it
68 // corresponds to the Elf_Shdr member.
71 // The following fields correspond to Elf_Shdr members.
76 void recordSection(InputSectionBase
*isec
);
77 void commitSection(InputSection
*isec
);
78 void finalizeInputSections(LinkerScript
*script
= nullptr);
80 // The following members are normally only used in linker scripts.
81 MemoryRegion
*memRegion
= nullptr;
82 MemoryRegion
*lmaRegion
= nullptr;
87 SmallVector
<SectionCommand
*, 0> commands
;
88 SmallVector
<StringRef
, 0> phdrs
;
89 std::optional
<std::array
<uint8_t, 4>> filler
;
90 ConstraintKind constraint
= ConstraintKind::NoConstraint
;
92 std::string memoryRegionName
;
93 std::string lmaRegionName
;
94 bool nonAlloc
= false;
95 bool typeIsSet
= false;
96 bool expressionsUseSymbols
= false;
97 bool usedInExpression
= false;
98 bool inOverlay
= false;
100 // Tracks whether the section has ever had an input section added to it, even
101 // if the section was later removed (e.g. because it is a synthetic section
102 // that wasn't needed). This is needed for orphan placement.
103 bool hasInputSections
= false;
105 // The output section description is specified between DATA_SEGMENT_ALIGN and
110 template <class ELFT
>
111 void writeTo(uint8_t *buf
, llvm::parallel::TaskGroup
&tg
);
112 // Check that the addends for dynamic relocations were written correctly.
113 void checkDynRelAddends(const uint8_t *bufStart
);
114 template <class ELFT
> void maybeCompress();
116 void sort(llvm::function_ref
<int(InputSectionBase
*s
)> order
);
118 void sortCtorsDtors();
120 // Used for implementation of --compress-debug-sections and
121 // --compress-sections.
122 CompressedData compressed
;
125 SmallVector
<InputSection
*, 0> storage
;
127 std::array
<uint8_t, 4> getFiller();
130 struct OutputDesc final
: SectionCommand
{
132 OutputDesc(StringRef name
, uint32_t type
, uint64_t flags
)
133 : SectionCommand(OutputSectionKind
), osec(name
, type
, flags
) {}
135 static bool classof(const SectionCommand
*c
) {
136 return c
->kind
== OutputSectionKind
;
140 int getPriority(StringRef s
);
142 InputSection
*getFirstInputSection(const OutputSection
*os
);
143 llvm::ArrayRef
<InputSection
*>
144 getInputSections(const OutputSection
&os
,
145 SmallVector
<InputSection
*, 0> &storage
);
147 // All output sections that are handled by the linker specially are
148 // globally accessible. Writer initializes them, so don't use them
149 // until Writer is initialized.
151 static uint8_t *bufferStart
;
152 static PhdrEntry
*tlsPhdr
;
153 static OutputSection
*elfHeader
;
154 static OutputSection
*programHeaders
;
155 static OutputSection
*preinitArray
;
156 static OutputSection
*initArray
;
157 static OutputSection
*finiArray
;
160 uint64_t getHeaderSize();
162 LLVM_LIBRARY_VISIBILITY
extern llvm::SmallVector
<OutputSection
*, 0>
164 } // namespace lld::elf