1 //===- ELFObject.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 LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H
10 #define LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/BinaryFormat/ELF.h"
16 #include "llvm/MC/StringTableBuilder.h"
17 #include "llvm/ObjCopy/CommonConfig.h"
18 #include "llvm/Object/ELFObjectFile.h"
19 #include "llvm/Support/Errc.h"
20 #include "llvm/Support/FileOutputBuffer.h"
21 #include "llvm/Support/MemoryBuffer.h"
30 enum class DebugCompressionType
;
36 class OwnedDataSection
;
37 class StringTableSection
;
38 class SymbolTableSection
;
39 class RelocationSection
;
40 class DynamicRelocationSection
;
41 class GnuDebugLinkSection
;
43 class SectionIndexSection
;
44 class CompressedSection
;
45 class DecompressedSection
;
50 class SectionTableRef
{
51 ArrayRef
<std::unique_ptr
<SectionBase
>> Sections
;
54 using iterator
= pointee_iterator
<const std::unique_ptr
<SectionBase
> *>;
56 explicit SectionTableRef(ArrayRef
<std::unique_ptr
<SectionBase
>> Secs
)
58 SectionTableRef(const SectionTableRef
&) = default;
60 iterator
begin() const { return iterator(Sections
.data()); }
61 iterator
end() const { return iterator(Sections
.data() + Sections
.size()); }
62 size_t size() const { return Sections
.size(); }
64 Expected
<SectionBase
*> getSection(uint32_t Index
, Twine ErrMsg
);
67 Expected
<T
*> getSectionOfType(uint32_t Index
, Twine IndexErrMsg
,
71 enum ElfType
{ ELFT_ELF32LE
, ELFT_ELF64LE
, ELFT_ELF32BE
, ELFT_ELF64BE
};
73 class SectionVisitor
{
75 virtual ~SectionVisitor() = default;
77 virtual Error
visit(const Section
&Sec
) = 0;
78 virtual Error
visit(const OwnedDataSection
&Sec
) = 0;
79 virtual Error
visit(const StringTableSection
&Sec
) = 0;
80 virtual Error
visit(const SymbolTableSection
&Sec
) = 0;
81 virtual Error
visit(const RelocationSection
&Sec
) = 0;
82 virtual Error
visit(const DynamicRelocationSection
&Sec
) = 0;
83 virtual Error
visit(const GnuDebugLinkSection
&Sec
) = 0;
84 virtual Error
visit(const GroupSection
&Sec
) = 0;
85 virtual Error
visit(const SectionIndexSection
&Sec
) = 0;
86 virtual Error
visit(const CompressedSection
&Sec
) = 0;
87 virtual Error
visit(const DecompressedSection
&Sec
) = 0;
90 class MutableSectionVisitor
{
92 virtual ~MutableSectionVisitor() = default;
94 virtual Error
visit(Section
&Sec
) = 0;
95 virtual Error
visit(OwnedDataSection
&Sec
) = 0;
96 virtual Error
visit(StringTableSection
&Sec
) = 0;
97 virtual Error
visit(SymbolTableSection
&Sec
) = 0;
98 virtual Error
visit(RelocationSection
&Sec
) = 0;
99 virtual Error
visit(DynamicRelocationSection
&Sec
) = 0;
100 virtual Error
visit(GnuDebugLinkSection
&Sec
) = 0;
101 virtual Error
visit(GroupSection
&Sec
) = 0;
102 virtual Error
visit(SectionIndexSection
&Sec
) = 0;
103 virtual Error
visit(CompressedSection
&Sec
) = 0;
104 virtual Error
visit(DecompressedSection
&Sec
) = 0;
107 class SectionWriter
: public SectionVisitor
{
109 WritableMemoryBuffer
&Out
;
112 virtual ~SectionWriter() = default;
114 Error
visit(const Section
&Sec
) override
;
115 Error
visit(const OwnedDataSection
&Sec
) override
;
116 Error
visit(const StringTableSection
&Sec
) override
;
117 Error
visit(const DynamicRelocationSection
&Sec
) override
;
118 Error
visit(const SymbolTableSection
&Sec
) override
= 0;
119 Error
visit(const RelocationSection
&Sec
) override
= 0;
120 Error
visit(const GnuDebugLinkSection
&Sec
) override
= 0;
121 Error
visit(const GroupSection
&Sec
) override
= 0;
122 Error
visit(const SectionIndexSection
&Sec
) override
= 0;
123 Error
visit(const CompressedSection
&Sec
) override
= 0;
124 Error
visit(const DecompressedSection
&Sec
) override
= 0;
126 explicit SectionWriter(WritableMemoryBuffer
&Buf
) : Out(Buf
) {}
129 template <class ELFT
> class ELFSectionWriter
: public SectionWriter
{
131 using Elf_Word
= typename
ELFT::Word
;
132 using Elf_Rel
= typename
ELFT::Rel
;
133 using Elf_Rela
= typename
ELFT::Rela
;
134 using Elf_Sym
= typename
ELFT::Sym
;
137 virtual ~ELFSectionWriter() {}
138 Error
visit(const SymbolTableSection
&Sec
) override
;
139 Error
visit(const RelocationSection
&Sec
) override
;
140 Error
visit(const GnuDebugLinkSection
&Sec
) override
;
141 Error
visit(const GroupSection
&Sec
) override
;
142 Error
visit(const SectionIndexSection
&Sec
) override
;
143 Error
visit(const CompressedSection
&Sec
) override
;
144 Error
visit(const DecompressedSection
&Sec
) override
;
146 explicit ELFSectionWriter(WritableMemoryBuffer
&Buf
) : SectionWriter(Buf
) {}
149 template <class ELFT
> class ELFSectionSizer
: public MutableSectionVisitor
{
151 using Elf_Rel
= typename
ELFT::Rel
;
152 using Elf_Rela
= typename
ELFT::Rela
;
153 using Elf_Sym
= typename
ELFT::Sym
;
154 using Elf_Word
= typename
ELFT::Word
;
155 using Elf_Xword
= typename
ELFT::Xword
;
158 Error
visit(Section
&Sec
) override
;
159 Error
visit(OwnedDataSection
&Sec
) override
;
160 Error
visit(StringTableSection
&Sec
) override
;
161 Error
visit(DynamicRelocationSection
&Sec
) override
;
162 Error
visit(SymbolTableSection
&Sec
) override
;
163 Error
visit(RelocationSection
&Sec
) override
;
164 Error
visit(GnuDebugLinkSection
&Sec
) override
;
165 Error
visit(GroupSection
&Sec
) override
;
166 Error
visit(SectionIndexSection
&Sec
) override
;
167 Error
visit(CompressedSection
&Sec
) override
;
168 Error
visit(DecompressedSection
&Sec
) override
;
171 #define MAKE_SEC_WRITER_FRIEND \
172 friend class SectionWriter; \
173 friend class IHexSectionWriterBase; \
174 friend class IHexSectionWriter; \
175 template <class ELFT> friend class ELFSectionWriter; \
176 template <class ELFT> friend class ELFSectionSizer;
178 class BinarySectionWriter
: public SectionWriter
{
180 virtual ~BinarySectionWriter() {}
182 Error
visit(const SymbolTableSection
&Sec
) override
;
183 Error
visit(const RelocationSection
&Sec
) override
;
184 Error
visit(const GnuDebugLinkSection
&Sec
) override
;
185 Error
visit(const GroupSection
&Sec
) override
;
186 Error
visit(const SectionIndexSection
&Sec
) override
;
187 Error
visit(const CompressedSection
&Sec
) override
;
188 Error
visit(const DecompressedSection
&Sec
) override
;
190 explicit BinarySectionWriter(WritableMemoryBuffer
&Buf
)
191 : SectionWriter(Buf
) {}
194 using IHexLineData
= SmallVector
<char, 64>;
197 // Memory address of the record.
199 // Record type (see below).
201 // Record data in hexadecimal form.
204 // Helper method to get file length of the record
205 // including newline character
206 static size_t getLength(size_t DataSize
) {
207 // :LLAAAATT[DD...DD]CC'
208 return DataSize
* 2 + 11;
211 // Gets length of line in a file (getLength + CRLF).
212 static size_t getLineLength(size_t DataSize
) {
213 return getLength(DataSize
) + 2;
216 // Given type, address and data returns line which can
217 // be written to output file.
218 static IHexLineData
getLine(uint8_t Type
, uint16_t Addr
,
219 ArrayRef
<uint8_t> Data
);
221 // Parses the line and returns record if possible.
222 // Line should be trimmed from whitespace characters.
223 static Expected
<IHexRecord
> parse(StringRef Line
);
225 // Calculates checksum of stringified record representation
226 // S must NOT contain leading ':' and trailing whitespace
228 static uint8_t getChecksum(StringRef S
);
231 // Contains data and a 16-bit starting address for the data.
232 // The byte count specifies number of data bytes in the record.
234 // Must occur exactly once per file in the last line of the file.
235 // The data field is empty (thus byte count is 00) and the address
236 // field is typically 0000.
238 // The data field contains a 16-bit segment base address (thus byte
239 // count is always 02) compatible with 80x86 real mode addressing.
240 // The address field (typically 0000) is ignored. The segment address
241 // from the most recent 02 record is multiplied by 16 and added to each
242 // subsequent data record address to form the physical starting address
243 // for the data. This allows addressing up to one megabyte of address
246 // or 80x86 processors, specifies the initial content of the CS:IP
247 // registers. The address field is 0000, the byte count is always 04,
248 // the first two data bytes are the CS value, the latter two are the
251 // Allows for 32 bit addressing (up to 4GiB). The record's address field
252 // is ignored (typically 0000) and its byte count is always 02. The two
253 // data bytes (big endian) specify the upper 16 bits of the 32 bit
254 // absolute address for all subsequent type 00 records
256 // The address field is 0000 (not used) and the byte count is always 04.
257 // The four data bytes represent a 32-bit address value. In the case of
258 // 80386 and higher CPUs, this address is loaded into the EIP register.
260 // We have no other valid types
265 // Base class for IHexSectionWriter. This class implements writing algorithm,
266 // but doesn't actually write records. It is used for output buffer size
267 // calculation in IHexWriter::finalize.
268 class IHexSectionWriterBase
: public BinarySectionWriter
{
269 // 20-bit segment address
270 uint32_t SegmentAddr
= 0;
271 // Extended linear address
272 uint32_t BaseAddr
= 0;
274 // Write segment address corresponding to 'Addr'
275 uint64_t writeSegmentAddr(uint64_t Addr
);
276 // Write extended linear (base) address corresponding to 'Addr'
277 uint64_t writeBaseAddr(uint64_t Addr
);
280 // Offset in the output buffer
283 void writeSection(const SectionBase
*Sec
, ArrayRef
<uint8_t> Data
);
284 virtual void writeData(uint8_t Type
, uint16_t Addr
, ArrayRef
<uint8_t> Data
);
287 explicit IHexSectionWriterBase(WritableMemoryBuffer
&Buf
)
288 : BinarySectionWriter(Buf
) {}
290 uint64_t getBufferOffset() const { return Offset
; }
291 Error
visit(const Section
&Sec
) final
;
292 Error
visit(const OwnedDataSection
&Sec
) final
;
293 Error
visit(const StringTableSection
&Sec
) override
;
294 Error
visit(const DynamicRelocationSection
&Sec
) final
;
295 using BinarySectionWriter::visit
;
298 // Real IHEX section writer
299 class IHexSectionWriter
: public IHexSectionWriterBase
{
301 IHexSectionWriter(WritableMemoryBuffer
&Buf
) : IHexSectionWriterBase(Buf
) {}
303 void writeData(uint8_t Type
, uint16_t Addr
, ArrayRef
<uint8_t> Data
) override
;
304 Error
visit(const StringTableSection
&Sec
) override
;
310 std::unique_ptr
<WritableMemoryBuffer
> Buf
;
315 virtual Error
finalize() = 0;
316 virtual Error
write() = 0;
318 Writer(Object
&O
, raw_ostream
&Out
) : Obj(O
), Out(Out
) {}
321 template <class ELFT
> class ELFWriter
: public Writer
{
323 using Elf_Addr
= typename
ELFT::Addr
;
324 using Elf_Shdr
= typename
ELFT::Shdr
;
325 using Elf_Phdr
= typename
ELFT::Phdr
;
326 using Elf_Ehdr
= typename
ELFT::Ehdr
;
328 void initEhdrSegment();
331 void writePhdr(const Segment
&Seg
);
332 void writeShdr(const SectionBase
&Sec
);
336 Error
writeSectionData();
337 void writeSegmentData();
339 void assignOffsets();
341 std::unique_ptr
<ELFSectionWriter
<ELFT
>> SecWriter
;
343 size_t totalSize() const;
346 virtual ~ELFWriter() {}
347 bool WriteSectionHeaders
;
349 // For --only-keep-debug, select an alternative section/segment layout
353 Error
finalize() override
;
354 Error
write() override
;
355 ELFWriter(Object
&Obj
, raw_ostream
&Out
, bool WSH
, bool OnlyKeepDebug
);
358 class BinaryWriter
: public Writer
{
360 std::unique_ptr
<BinarySectionWriter
> SecWriter
;
362 uint64_t TotalSize
= 0;
366 Error
finalize() override
;
367 Error
write() override
;
368 BinaryWriter(Object
&Obj
, raw_ostream
&Out
) : Writer(Obj
, Out
) {}
371 class IHexWriter
: public Writer
{
372 struct SectionCompare
{
373 bool operator()(const SectionBase
*Lhs
, const SectionBase
*Rhs
) const;
376 std::set
<const SectionBase
*, SectionCompare
> Sections
;
377 size_t TotalSize
= 0;
379 Error
checkSection(const SectionBase
&Sec
);
380 uint64_t writeEntryPointRecord(uint8_t *Buf
);
381 uint64_t writeEndOfFileRecord(uint8_t *Buf
);
385 Error
finalize() override
;
386 Error
write() override
;
387 IHexWriter(Object
&Obj
, raw_ostream
&Out
) : Writer(Obj
, Out
) {}
393 Segment
*ParentSegment
= nullptr;
394 uint64_t HeaderOffset
= 0;
397 uint32_t OriginalIndex
= 0;
398 uint64_t OriginalFlags
= 0;
399 uint64_t OriginalType
= ELF::SHT_NULL
;
400 uint64_t OriginalOffset
= std::numeric_limits
<uint64_t>::max();
404 uint32_t EntrySize
= 0;
407 uint64_t Link
= ELF::SHN_UNDEF
;
408 uint64_t NameIndex
= 0;
411 uint64_t Type
= ELF::SHT_NULL
;
412 ArrayRef
<uint8_t> OriginalData
;
413 bool HasSymbol
= false;
415 SectionBase() = default;
416 SectionBase(const SectionBase
&) = default;
418 virtual ~SectionBase() = default;
420 virtual Error
initialize(SectionTableRef SecTable
);
421 virtual void finalize();
422 // Remove references to these sections. The list of sections must be sorted.
424 removeSectionReferences(bool AllowBrokenLinks
,
425 function_ref
<bool(const SectionBase
*)> ToRemove
);
426 virtual Error
removeSymbols(function_ref
<bool(const Symbol
&)> ToRemove
);
427 virtual Error
accept(SectionVisitor
&Visitor
) const = 0;
428 virtual Error
accept(MutableSectionVisitor
&Visitor
) = 0;
429 virtual void markSymbols();
431 replaceSectionReferences(const DenseMap
<SectionBase
*, SectionBase
*> &);
432 virtual bool hasContents() const { return false; }
433 // Notify the section that it is subject to removal.
434 virtual void onRemove();
436 virtual void restoreSymTabLink(SymbolTableSection
&) {}
441 struct SectionCompare
{
442 bool operator()(const SectionBase
*Lhs
, const SectionBase
*Rhs
) const {
443 // Some sections might have the same address if one of them is empty. To
444 // fix this we can use the lexicographic ordering on ->Addr and the
446 if (Lhs
->OriginalOffset
== Rhs
->OriginalOffset
)
447 return Lhs
->OriginalIndex
< Rhs
->OriginalIndex
;
448 return Lhs
->OriginalOffset
< Rhs
->OriginalOffset
;
458 uint64_t FileSize
= 0;
459 uint64_t MemSize
= 0;
463 uint64_t OriginalOffset
= 0;
464 Segment
*ParentSegment
= nullptr;
465 ArrayRef
<uint8_t> Contents
;
466 std::set
<const SectionBase
*, SectionCompare
> Sections
;
468 explicit Segment(ArrayRef
<uint8_t> Data
) : Contents(Data
) {}
471 const SectionBase
*firstSection() const {
472 if (!Sections
.empty())
473 return *Sections
.begin();
477 void removeSection(const SectionBase
*Sec
) { Sections
.erase(Sec
); }
478 void addSection(const SectionBase
*Sec
) { Sections
.insert(Sec
); }
480 ArrayRef
<uint8_t> getContents() const { return Contents
; }
483 class Section
: public SectionBase
{
484 MAKE_SEC_WRITER_FRIEND
486 ArrayRef
<uint8_t> Contents
;
487 SectionBase
*LinkSection
= nullptr;
488 bool HasSymTabLink
= false;
491 explicit Section(ArrayRef
<uint8_t> Data
) : Contents(Data
) {}
493 Error
accept(SectionVisitor
&Visitor
) const override
;
494 Error
accept(MutableSectionVisitor
&Visitor
) override
;
495 Error
removeSectionReferences(
496 bool AllowBrokenLinks
,
497 function_ref
<bool(const SectionBase
*)> ToRemove
) override
;
498 Error
initialize(SectionTableRef SecTable
) override
;
499 void finalize() override
;
500 bool hasContents() const override
{
501 return Type
!= ELF::SHT_NOBITS
&& Type
!= ELF::SHT_NULL
;
503 void restoreSymTabLink(SymbolTableSection
&SymTab
) override
;
506 class OwnedDataSection
: public SectionBase
{
507 MAKE_SEC_WRITER_FRIEND
509 std::vector
<uint8_t> Data
;
512 OwnedDataSection(StringRef SecName
, ArrayRef
<uint8_t> Data
)
513 : Data(std::begin(Data
), std::end(Data
)) {
514 Name
= SecName
.str();
515 Type
= OriginalType
= ELF::SHT_PROGBITS
;
517 OriginalOffset
= std::numeric_limits
<uint64_t>::max();
520 OwnedDataSection(const Twine
&SecName
, uint64_t SecAddr
, uint64_t SecFlags
,
522 Name
= SecName
.str();
523 Type
= OriginalType
= ELF::SHT_PROGBITS
;
525 Flags
= OriginalFlags
= SecFlags
;
526 OriginalOffset
= SecOff
;
529 OwnedDataSection(SectionBase
&S
, ArrayRef
<uint8_t> Data
)
530 : SectionBase(S
), Data(std::begin(Data
), std::end(Data
)) {
534 void appendHexData(StringRef HexData
);
535 Error
accept(SectionVisitor
&Sec
) const override
;
536 Error
accept(MutableSectionVisitor
&Visitor
) override
;
537 bool hasContents() const override
{ return true; }
540 class CompressedSection
: public SectionBase
{
541 MAKE_SEC_WRITER_FRIEND
544 DebugCompressionType CompressionType
;
545 uint64_t DecompressedSize
;
546 uint64_t DecompressedAlign
;
547 SmallVector
<uint8_t, 128> CompressedData
;
550 CompressedSection(const SectionBase
&Sec
,
551 DebugCompressionType CompressionType
, bool Is64Bits
);
552 CompressedSection(ArrayRef
<uint8_t> CompressedData
, uint32_t ChType
,
553 uint64_t DecompressedSize
, uint64_t DecompressedAlign
);
555 uint64_t getDecompressedSize() const { return DecompressedSize
; }
556 uint64_t getDecompressedAlign() const { return DecompressedAlign
; }
557 uint64_t getChType() const { return ChType
; }
559 Error
accept(SectionVisitor
&Visitor
) const override
;
560 Error
accept(MutableSectionVisitor
&Visitor
) override
;
562 static bool classof(const SectionBase
*S
) {
563 return S
->OriginalFlags
& ELF::SHF_COMPRESSED
;
567 class DecompressedSection
: public SectionBase
{
568 MAKE_SEC_WRITER_FRIEND
572 explicit DecompressedSection(const CompressedSection
&Sec
)
573 : SectionBase(Sec
), ChType(Sec
.getChType()) {
574 Size
= Sec
.getDecompressedSize();
575 Align
= Sec
.getDecompressedAlign();
576 Flags
= OriginalFlags
= (Flags
& ~ELF::SHF_COMPRESSED
);
579 Error
accept(SectionVisitor
&Visitor
) const override
;
580 Error
accept(MutableSectionVisitor
&Visitor
) override
;
583 // There are two types of string tables that can exist, dynamic and not dynamic.
584 // In the dynamic case the string table is allocated. Changing a dynamic string
585 // table would mean altering virtual addresses and thus the memory image. So
586 // dynamic string tables should not have an interface to modify them or
587 // reconstruct them. This type lets us reconstruct a string table. To avoid
588 // this class being used for dynamic string tables (which has happened) the
589 // classof method checks that the particular instance is not allocated. This
590 // then agrees with the makeSection method used to construct most sections.
591 class StringTableSection
: public SectionBase
{
592 MAKE_SEC_WRITER_FRIEND
594 StringTableBuilder StrTabBuilder
;
597 StringTableSection() : StrTabBuilder(StringTableBuilder::ELF
) {
598 Type
= OriginalType
= ELF::SHT_STRTAB
;
601 void addString(StringRef Name
);
602 uint32_t findIndex(StringRef Name
) const;
603 void prepareForLayout();
604 Error
accept(SectionVisitor
&Visitor
) const override
;
605 Error
accept(MutableSectionVisitor
&Visitor
) override
;
607 static bool classof(const SectionBase
*S
) {
608 if (S
->OriginalFlags
& ELF::SHF_ALLOC
)
610 return S
->OriginalType
== ELF::SHT_STRTAB
;
614 // Symbols have a st_shndx field that normally stores an index but occasionally
615 // stores a different special value. This enum keeps track of what the st_shndx
616 // field means. Most of the values are just copies of the special SHN_* values.
617 // SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
618 enum SymbolShndxType
{
619 SYMBOL_SIMPLE_INDEX
= 0,
620 SYMBOL_ABS
= ELF::SHN_ABS
,
621 SYMBOL_COMMON
= ELF::SHN_COMMON
,
622 SYMBOL_LOPROC
= ELF::SHN_LOPROC
,
623 SYMBOL_AMDGPU_LDS
= ELF::SHN_AMDGPU_LDS
,
624 SYMBOL_HEXAGON_SCOMMON
= ELF::SHN_HEXAGON_SCOMMON
,
625 SYMBOL_HEXAGON_SCOMMON_2
= ELF::SHN_HEXAGON_SCOMMON_2
,
626 SYMBOL_HEXAGON_SCOMMON_4
= ELF::SHN_HEXAGON_SCOMMON_4
,
627 SYMBOL_HEXAGON_SCOMMON_8
= ELF::SHN_HEXAGON_SCOMMON_8
,
628 SYMBOL_MIPS_ACOMMON
= ELF::SHN_MIPS_ACOMMON
,
629 SYMBOL_MIPS_TEXT
= ELF::SHN_MIPS_TEXT
,
630 SYMBOL_MIPS_DATA
= ELF::SHN_MIPS_DATA
,
631 SYMBOL_MIPS_SCOMMON
= ELF::SHN_MIPS_SCOMMON
,
632 SYMBOL_MIPS_SUNDEFINED
= ELF::SHN_MIPS_SUNDEFINED
,
633 SYMBOL_HIPROC
= ELF::SHN_HIPROC
,
634 SYMBOL_LOOS
= ELF::SHN_LOOS
,
635 SYMBOL_HIOS
= ELF::SHN_HIOS
,
636 SYMBOL_XINDEX
= ELF::SHN_XINDEX
,
641 SectionBase
*DefinedIn
= nullptr;
642 SymbolShndxType ShndxType
;
650 bool Referenced
= false;
652 uint16_t getShndx() const;
653 bool isCommon() const;
656 class SectionIndexSection
: public SectionBase
{
657 MAKE_SEC_WRITER_FRIEND
660 std::vector
<uint32_t> Indexes
;
661 SymbolTableSection
*Symbols
= nullptr;
664 virtual ~SectionIndexSection() {}
665 void addIndex(uint32_t Index
) {
667 Indexes
.push_back(Index
);
670 void reserve(size_t NumSymbols
) {
671 Indexes
.reserve(NumSymbols
);
672 Size
= NumSymbols
* 4;
674 void setSymTab(SymbolTableSection
*SymTab
) { Symbols
= SymTab
; }
675 Error
initialize(SectionTableRef SecTable
) override
;
676 void finalize() override
;
677 Error
accept(SectionVisitor
&Visitor
) const override
;
678 Error
accept(MutableSectionVisitor
&Visitor
) override
;
680 SectionIndexSection() {
681 Name
= ".symtab_shndx";
684 Type
= OriginalType
= ELF::SHT_SYMTAB_SHNDX
;
688 class SymbolTableSection
: public SectionBase
{
689 MAKE_SEC_WRITER_FRIEND
691 void setStrTab(StringTableSection
*StrTab
) { SymbolNames
= StrTab
; }
692 void assignIndices();
695 std::vector
<std::unique_ptr
<Symbol
>> Symbols
;
696 StringTableSection
*SymbolNames
= nullptr;
697 SectionIndexSection
*SectionIndexTable
= nullptr;
698 bool IndicesChanged
= false;
700 using SymPtr
= std::unique_ptr
<Symbol
>;
703 SymbolTableSection() { Type
= OriginalType
= ELF::SHT_SYMTAB
; }
705 void addSymbol(Twine Name
, uint8_t Bind
, uint8_t Type
, SectionBase
*DefinedIn
,
706 uint64_t Value
, uint8_t Visibility
, uint16_t Shndx
,
707 uint64_t SymbolSize
);
708 void prepareForLayout();
709 // An 'empty' symbol table still contains a null symbol.
710 bool empty() const { return Symbols
.size() == 1; }
711 bool indicesChanged() const { return IndicesChanged
; }
712 void setShndxTable(SectionIndexSection
*ShndxTable
) {
713 SectionIndexTable
= ShndxTable
;
715 const SectionIndexSection
*getShndxTable() const { return SectionIndexTable
; }
716 void fillShndxTable();
717 const SectionBase
*getStrTab() const { return SymbolNames
; }
718 Expected
<const Symbol
*> getSymbolByIndex(uint32_t Index
) const;
719 Expected
<Symbol
*> getSymbolByIndex(uint32_t Index
);
720 void updateSymbols(function_ref
<void(Symbol
&)> Callable
);
722 Error
removeSectionReferences(
723 bool AllowBrokenLinks
,
724 function_ref
<bool(const SectionBase
*)> ToRemove
) override
;
725 Error
initialize(SectionTableRef SecTable
) override
;
726 void finalize() override
;
727 Error
accept(SectionVisitor
&Visitor
) const override
;
728 Error
accept(MutableSectionVisitor
&Visitor
) override
;
729 Error
removeSymbols(function_ref
<bool(const Symbol
&)> ToRemove
) override
;
730 void replaceSectionReferences(
731 const DenseMap
<SectionBase
*, SectionBase
*> &FromTo
) override
;
733 static bool classof(const SectionBase
*S
) {
734 return S
->OriginalType
== ELF::SHT_SYMTAB
;
739 Symbol
*RelocSymbol
= nullptr;
745 // All relocation sections denote relocations to apply to another section.
746 // However, some relocation sections use a dynamic symbol table and others use
747 // a regular symbol table. Because the types of the two symbol tables differ in
748 // our system (because they should behave differently) we can't uniformly
749 // represent all relocations with the same base class if we expose an interface
750 // that mentions the symbol table type. So we split the two base types into two
751 // different classes, one which handles the section the relocation is applied to
752 // and another which handles the symbol table type. The symbol table type is
753 // taken as a type parameter to the class (see RelocSectionWithSymtabBase).
754 class RelocationSectionBase
: public SectionBase
{
756 SectionBase
*SecToApplyRel
= nullptr;
759 const SectionBase
*getSection() const { return SecToApplyRel
; }
760 void setSection(SectionBase
*Sec
) { SecToApplyRel
= Sec
; }
762 StringRef
getNamePrefix() const;
764 static bool classof(const SectionBase
*S
) {
765 return S
->OriginalType
== ELF::SHT_REL
|| S
->OriginalType
== ELF::SHT_RELA
;
769 // Takes the symbol table type to use as a parameter so that we can deduplicate
770 // that code between the two symbol table types.
771 template <class SymTabType
>
772 class RelocSectionWithSymtabBase
: public RelocationSectionBase
{
773 void setSymTab(SymTabType
*SymTab
) { Symbols
= SymTab
; }
776 RelocSectionWithSymtabBase() = default;
778 SymTabType
*Symbols
= nullptr;
781 Error
initialize(SectionTableRef SecTable
) override
;
782 void finalize() override
;
785 class RelocationSection
786 : public RelocSectionWithSymtabBase
<SymbolTableSection
> {
787 MAKE_SEC_WRITER_FRIEND
789 std::vector
<Relocation
> Relocations
;
793 RelocationSection(const Object
&O
) : Obj(O
) {}
794 void addRelocation(Relocation Rel
) { Relocations
.push_back(Rel
); }
795 Error
accept(SectionVisitor
&Visitor
) const override
;
796 Error
accept(MutableSectionVisitor
&Visitor
) override
;
797 Error
removeSectionReferences(
798 bool AllowBrokenLinks
,
799 function_ref
<bool(const SectionBase
*)> ToRemove
) override
;
800 Error
removeSymbols(function_ref
<bool(const Symbol
&)> ToRemove
) override
;
801 void markSymbols() override
;
802 void replaceSectionReferences(
803 const DenseMap
<SectionBase
*, SectionBase
*> &FromTo
) override
;
804 const Object
&getObject() const { return Obj
; }
806 static bool classof(const SectionBase
*S
) {
807 if (S
->OriginalFlags
& ELF::SHF_ALLOC
)
809 return S
->OriginalType
== ELF::SHT_REL
|| S
->OriginalType
== ELF::SHT_RELA
;
813 // TODO: The way stripping and groups interact is complicated
814 // and still needs to be worked on.
816 class GroupSection
: public SectionBase
{
817 MAKE_SEC_WRITER_FRIEND
818 const SymbolTableSection
*SymTab
= nullptr;
819 Symbol
*Sym
= nullptr;
820 ELF::Elf32_Word FlagWord
;
821 SmallVector
<SectionBase
*, 3> GroupMembers
;
824 // TODO: Contents is present in several classes of the hierarchy.
825 // This needs to be refactored to avoid duplication.
826 ArrayRef
<uint8_t> Contents
;
828 explicit GroupSection(ArrayRef
<uint8_t> Data
) : Contents(Data
) {}
830 void setSymTab(const SymbolTableSection
*SymTabSec
) { SymTab
= SymTabSec
; }
831 void setSymbol(Symbol
*S
) { Sym
= S
; }
832 void setFlagWord(ELF::Elf32_Word W
) { FlagWord
= W
; }
833 void addMember(SectionBase
*Sec
) { GroupMembers
.push_back(Sec
); }
835 Error
accept(SectionVisitor
&) const override
;
836 Error
accept(MutableSectionVisitor
&Visitor
) override
;
837 void finalize() override
;
838 Error
removeSectionReferences(
839 bool AllowBrokenLinks
,
840 function_ref
<bool(const SectionBase
*)> ToRemove
) override
;
841 Error
removeSymbols(function_ref
<bool(const Symbol
&)> ToRemove
) override
;
842 void markSymbols() override
;
843 void replaceSectionReferences(
844 const DenseMap
<SectionBase
*, SectionBase
*> &FromTo
) override
;
845 void onRemove() override
;
847 static bool classof(const SectionBase
*S
) {
848 return S
->OriginalType
== ELF::SHT_GROUP
;
852 class DynamicSymbolTableSection
: public Section
{
854 explicit DynamicSymbolTableSection(ArrayRef
<uint8_t> Data
) : Section(Data
) {}
856 static bool classof(const SectionBase
*S
) {
857 return S
->OriginalType
== ELF::SHT_DYNSYM
;
861 class DynamicSection
: public Section
{
863 explicit DynamicSection(ArrayRef
<uint8_t> Data
) : Section(Data
) {}
865 static bool classof(const SectionBase
*S
) {
866 return S
->OriginalType
== ELF::SHT_DYNAMIC
;
870 class DynamicRelocationSection
871 : public RelocSectionWithSymtabBase
<DynamicSymbolTableSection
> {
872 MAKE_SEC_WRITER_FRIEND
875 ArrayRef
<uint8_t> Contents
;
878 explicit DynamicRelocationSection(ArrayRef
<uint8_t> Data
) : Contents(Data
) {}
880 Error
accept(SectionVisitor
&) const override
;
881 Error
accept(MutableSectionVisitor
&Visitor
) override
;
882 Error
removeSectionReferences(
883 bool AllowBrokenLinks
,
884 function_ref
<bool(const SectionBase
*)> ToRemove
) override
;
886 static bool classof(const SectionBase
*S
) {
887 if (!(S
->OriginalFlags
& ELF::SHF_ALLOC
))
889 return S
->OriginalType
== ELF::SHT_REL
|| S
->OriginalType
== ELF::SHT_RELA
;
893 class GnuDebugLinkSection
: public SectionBase
{
894 MAKE_SEC_WRITER_FRIEND
900 void init(StringRef File
);
903 // If we add this section from an external source we can use this ctor.
904 explicit GnuDebugLinkSection(StringRef File
, uint32_t PrecomputedCRC
);
905 Error
accept(SectionVisitor
&Visitor
) const override
;
906 Error
accept(MutableSectionVisitor
&Visitor
) override
;
912 virtual Expected
<std::unique_ptr
<Object
>> create(bool EnsureSymtab
) const = 0;
915 using object::Binary
;
916 using object::ELFFile
;
917 using object::ELFObjectFile
;
918 using object::OwningBinary
;
920 class BasicELFBuilder
{
922 std::unique_ptr
<Object
> Obj
;
924 void initFileHeader();
925 void initHeaderSegment();
926 StringTableSection
*addStrTab();
927 SymbolTableSection
*addSymTab(StringTableSection
*StrTab
);
928 Error
initSections();
931 BasicELFBuilder() : Obj(std::make_unique
<Object
>()) {}
934 class BinaryELFBuilder
: public BasicELFBuilder
{
935 MemoryBuffer
*MemBuf
;
936 uint8_t NewSymbolVisibility
;
937 void addData(SymbolTableSection
*SymTab
);
940 BinaryELFBuilder(MemoryBuffer
*MB
, uint8_t NewSymbolVisibility
)
941 : MemBuf(MB
), NewSymbolVisibility(NewSymbolVisibility
) {}
943 Expected
<std::unique_ptr
<Object
>> build();
946 class IHexELFBuilder
: public BasicELFBuilder
{
947 const std::vector
<IHexRecord
> &Records
;
949 void addDataSections();
952 IHexELFBuilder(const std::vector
<IHexRecord
> &Records
) : Records(Records
) {}
954 Expected
<std::unique_ptr
<Object
>> build();
957 template <class ELFT
> class ELFBuilder
{
959 using Elf_Addr
= typename
ELFT::Addr
;
960 using Elf_Shdr
= typename
ELFT::Shdr
;
961 using Elf_Word
= typename
ELFT::Word
;
963 const ELFFile
<ELFT
> &ElfFile
;
965 size_t EhdrOffset
= 0;
966 std::optional
<StringRef
> ExtractPartition
;
968 void setParentSegment(Segment
&Child
);
969 Error
readProgramHeaders(const ELFFile
<ELFT
> &HeadersFile
);
970 Error
initGroupSection(GroupSection
*GroupSec
);
971 Error
initSymbolTable(SymbolTableSection
*SymTab
);
972 Error
readSectionHeaders();
973 Error
readSections(bool EnsureSymtab
);
974 Error
findEhdrOffset();
975 Expected
<SectionBase
&> makeSection(const Elf_Shdr
&Shdr
);
978 ELFBuilder(const ELFObjectFile
<ELFT
> &ElfObj
, Object
&Obj
,
979 std::optional
<StringRef
> ExtractPartition
);
981 Error
build(bool EnsureSymtab
);
984 class BinaryReader
: public Reader
{
985 MemoryBuffer
*MemBuf
;
986 uint8_t NewSymbolVisibility
;
989 BinaryReader(MemoryBuffer
*MB
, const uint8_t NewSymbolVisibility
)
990 : MemBuf(MB
), NewSymbolVisibility(NewSymbolVisibility
) {}
991 Expected
<std::unique_ptr
<Object
>> create(bool EnsureSymtab
) const override
;
994 class IHexReader
: public Reader
{
995 MemoryBuffer
*MemBuf
;
997 Expected
<std::vector
<IHexRecord
>> parse() const;
998 Error
parseError(size_t LineNo
, Error E
) const {
1000 ? createFileError(MemBuf
->getBufferIdentifier(), std::move(E
))
1001 : createFileError(MemBuf
->getBufferIdentifier(), LineNo
,
1004 template <typename
... Ts
>
1005 Error
parseError(size_t LineNo
, char const *Fmt
, const Ts
&...Vals
) const {
1006 Error E
= createStringError(errc::invalid_argument
, Fmt
, Vals
...);
1007 return parseError(LineNo
, std::move(E
));
1011 IHexReader(MemoryBuffer
*MB
) : MemBuf(MB
) {}
1013 Expected
<std::unique_ptr
<Object
>> create(bool EnsureSymtab
) const override
;
1016 class ELFReader
: public Reader
{
1018 std::optional
<StringRef
> ExtractPartition
;
1021 Expected
<std::unique_ptr
<Object
>> create(bool EnsureSymtab
) const override
;
1022 explicit ELFReader(Binary
*B
, std::optional
<StringRef
> ExtractPartition
)
1023 : Bin(B
), ExtractPartition(ExtractPartition
) {}
1028 using SecPtr
= std::unique_ptr
<SectionBase
>;
1029 using SegPtr
= std::unique_ptr
<Segment
>;
1031 std::vector
<SecPtr
> Sections
;
1032 std::vector
<SegPtr
> Segments
;
1033 std::vector
<SecPtr
> RemovedSections
;
1034 DenseMap
<SectionBase
*, std::vector
<uint8_t>> UpdatedSections
;
1036 static bool sectionIsAlloc(const SectionBase
&Sec
) {
1037 return Sec
.Flags
& ELF::SHF_ALLOC
;
1042 using ConstRange
= iterator_range
<pointee_iterator
<
1043 typename
std::vector
<std::unique_ptr
<T
>>::const_iterator
>>;
1045 // It is often the case that the ELF header and the program header table are
1046 // not present in any segment. This could be a problem during file layout,
1047 // because other segments may get assigned an offset where either of the
1048 // two should reside, which will effectively corrupt the resulting binary.
1049 // Other than that we use these segments to track program header offsets
1050 // when they may not follow the ELF header.
1051 Segment ElfHdrSegment
;
1052 Segment ProgramHdrSegment
;
1064 bool HadShdrs
= true;
1065 bool MustBeRelocatable
= false;
1066 StringTableSection
*SectionNames
= nullptr;
1067 SymbolTableSection
*SymbolTable
= nullptr;
1068 SectionIndexSection
*SectionIndexTable
= nullptr;
1070 bool IsMips64EL
= false;
1072 SectionTableRef
sections() const { return SectionTableRef(Sections
); }
1074 filter_iterator
<pointee_iterator
<std::vector
<SecPtr
>::const_iterator
>,
1075 decltype(§ionIsAlloc
)>>
1076 allocSections() const {
1077 return make_filter_range(make_pointee_range(Sections
), sectionIsAlloc
);
1080 const auto &getUpdatedSections() const { return UpdatedSections
; }
1081 Error
updateSection(StringRef Name
, ArrayRef
<uint8_t> Data
);
1083 SectionBase
*findSection(StringRef Name
) {
1085 find_if(Sections
, [&](const SecPtr
&Sec
) { return Sec
->Name
== Name
; });
1086 return SecIt
== Sections
.end() ? nullptr : SecIt
->get();
1088 SectionTableRef
removedSections() { return SectionTableRef(RemovedSections
); }
1090 ConstRange
<Segment
> segments() const { return make_pointee_range(Segments
); }
1092 Error
removeSections(bool AllowBrokenLinks
,
1093 std::function
<bool(const SectionBase
&)> ToRemove
);
1094 Error
replaceSections(const DenseMap
<SectionBase
*, SectionBase
*> &FromTo
);
1095 Error
removeSymbols(function_ref
<bool(const Symbol
&)> ToRemove
);
1096 template <class T
, class... Ts
> T
&addSection(Ts
&&...Args
) {
1097 auto Sec
= std::make_unique
<T
>(std::forward
<Ts
>(Args
)...);
1098 auto Ptr
= Sec
.get();
1099 MustBeRelocatable
|= isa
<RelocationSection
>(*Ptr
);
1100 Sections
.emplace_back(std::move(Sec
));
1101 Ptr
->Index
= Sections
.size();
1104 Error
addNewSymbolTable();
1105 Segment
&addSegment(ArrayRef
<uint8_t> Data
) {
1106 Segments
.emplace_back(std::make_unique
<Segment
>(Data
));
1107 return *Segments
.back();
1109 bool isRelocatable() const {
1110 return (Type
!= ELF::ET_DYN
&& Type
!= ELF::ET_EXEC
) || MustBeRelocatable
;
1114 } // end namespace elf
1115 } // end namespace objcopy
1116 } // end namespace llvm
1118 #endif // LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H