xref: /llvm-project/llvm/lib/ObjCopy/ELF/ELFObject.h (revision 10772807ab72ce2b68d76816f8753219b2acbac3)
125d7b4fbSAlexey Lapshin //===- ELFObject.h ----------------------------------------------*- C++ -*-===//
225d7b4fbSAlexey Lapshin //
325d7b4fbSAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
425d7b4fbSAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information.
525d7b4fbSAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
625d7b4fbSAlexey Lapshin //
725d7b4fbSAlexey Lapshin //===----------------------------------------------------------------------===//
825d7b4fbSAlexey Lapshin 
925d7b4fbSAlexey Lapshin #ifndef LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H
1025d7b4fbSAlexey Lapshin #define LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H
1125d7b4fbSAlexey Lapshin 
1225d7b4fbSAlexey Lapshin #include "llvm/ADT/ArrayRef.h"
1325d7b4fbSAlexey Lapshin #include "llvm/ADT/StringRef.h"
1425d7b4fbSAlexey Lapshin #include "llvm/ADT/Twine.h"
1525d7b4fbSAlexey Lapshin #include "llvm/BinaryFormat/ELF.h"
1625d7b4fbSAlexey Lapshin #include "llvm/MC/StringTableBuilder.h"
1725d7b4fbSAlexey Lapshin #include "llvm/ObjCopy/CommonConfig.h"
1825d7b4fbSAlexey Lapshin #include "llvm/Object/ELFObjectFile.h"
1925d7b4fbSAlexey Lapshin #include "llvm/Support/Errc.h"
2025d7b4fbSAlexey Lapshin #include "llvm/Support/FileOutputBuffer.h"
2125d7b4fbSAlexey Lapshin #include "llvm/Support/MemoryBuffer.h"
2225d7b4fbSAlexey Lapshin #include <cstddef>
2325d7b4fbSAlexey Lapshin #include <cstdint>
2425d7b4fbSAlexey Lapshin #include <functional>
2525d7b4fbSAlexey Lapshin #include <memory>
2625d7b4fbSAlexey Lapshin #include <set>
2725d7b4fbSAlexey Lapshin #include <vector>
2825d7b4fbSAlexey Lapshin 
2925d7b4fbSAlexey Lapshin namespace llvm {
3025d7b4fbSAlexey Lapshin enum class DebugCompressionType;
3125d7b4fbSAlexey Lapshin namespace objcopy {
3225d7b4fbSAlexey Lapshin namespace elf {
3325d7b4fbSAlexey Lapshin 
3425d7b4fbSAlexey Lapshin class SectionBase;
3525d7b4fbSAlexey Lapshin class Section;
3625d7b4fbSAlexey Lapshin class OwnedDataSection;
3725d7b4fbSAlexey Lapshin class StringTableSection;
3825d7b4fbSAlexey Lapshin class SymbolTableSection;
3925d7b4fbSAlexey Lapshin class RelocationSection;
4025d7b4fbSAlexey Lapshin class DynamicRelocationSection;
4125d7b4fbSAlexey Lapshin class GnuDebugLinkSection;
4225d7b4fbSAlexey Lapshin class GroupSection;
4325d7b4fbSAlexey Lapshin class SectionIndexSection;
4425d7b4fbSAlexey Lapshin class CompressedSection;
4525d7b4fbSAlexey Lapshin class DecompressedSection;
4625d7b4fbSAlexey Lapshin class Segment;
4725d7b4fbSAlexey Lapshin class Object;
4825d7b4fbSAlexey Lapshin struct Symbol;
4925d7b4fbSAlexey Lapshin 
5025d7b4fbSAlexey Lapshin class SectionTableRef {
5125d7b4fbSAlexey Lapshin   ArrayRef<std::unique_ptr<SectionBase>> Sections;
5225d7b4fbSAlexey Lapshin 
5325d7b4fbSAlexey Lapshin public:
5425d7b4fbSAlexey Lapshin   using iterator = pointee_iterator<const std::unique_ptr<SectionBase> *>;
5525d7b4fbSAlexey Lapshin 
5625d7b4fbSAlexey Lapshin   explicit SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs)
5725d7b4fbSAlexey Lapshin       : Sections(Secs) {}
5825d7b4fbSAlexey Lapshin   SectionTableRef(const SectionTableRef &) = default;
5925d7b4fbSAlexey Lapshin 
6025d7b4fbSAlexey Lapshin   iterator begin() const { return iterator(Sections.data()); }
6125d7b4fbSAlexey Lapshin   iterator end() const { return iterator(Sections.data() + Sections.size()); }
6225d7b4fbSAlexey Lapshin   size_t size() const { return Sections.size(); }
6325d7b4fbSAlexey Lapshin 
6425d7b4fbSAlexey Lapshin   Expected<SectionBase *> getSection(uint32_t Index, Twine ErrMsg);
6525d7b4fbSAlexey Lapshin 
6625d7b4fbSAlexey Lapshin   template <class T>
6725d7b4fbSAlexey Lapshin   Expected<T *> getSectionOfType(uint32_t Index, Twine IndexErrMsg,
6825d7b4fbSAlexey Lapshin                                  Twine TypeErrMsg);
6925d7b4fbSAlexey Lapshin };
7025d7b4fbSAlexey Lapshin 
7125d7b4fbSAlexey Lapshin enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };
7225d7b4fbSAlexey Lapshin 
7325d7b4fbSAlexey Lapshin class SectionVisitor {
7425d7b4fbSAlexey Lapshin public:
7525d7b4fbSAlexey Lapshin   virtual ~SectionVisitor() = default;
7625d7b4fbSAlexey Lapshin 
7725d7b4fbSAlexey Lapshin   virtual Error visit(const Section &Sec) = 0;
7825d7b4fbSAlexey Lapshin   virtual Error visit(const OwnedDataSection &Sec) = 0;
7925d7b4fbSAlexey Lapshin   virtual Error visit(const StringTableSection &Sec) = 0;
8025d7b4fbSAlexey Lapshin   virtual Error visit(const SymbolTableSection &Sec) = 0;
8125d7b4fbSAlexey Lapshin   virtual Error visit(const RelocationSection &Sec) = 0;
8225d7b4fbSAlexey Lapshin   virtual Error visit(const DynamicRelocationSection &Sec) = 0;
8325d7b4fbSAlexey Lapshin   virtual Error visit(const GnuDebugLinkSection &Sec) = 0;
8425d7b4fbSAlexey Lapshin   virtual Error visit(const GroupSection &Sec) = 0;
8525d7b4fbSAlexey Lapshin   virtual Error visit(const SectionIndexSection &Sec) = 0;
8625d7b4fbSAlexey Lapshin   virtual Error visit(const CompressedSection &Sec) = 0;
8725d7b4fbSAlexey Lapshin   virtual Error visit(const DecompressedSection &Sec) = 0;
8825d7b4fbSAlexey Lapshin };
8925d7b4fbSAlexey Lapshin 
9025d7b4fbSAlexey Lapshin class MutableSectionVisitor {
9125d7b4fbSAlexey Lapshin public:
9225d7b4fbSAlexey Lapshin   virtual ~MutableSectionVisitor() = default;
9325d7b4fbSAlexey Lapshin 
9425d7b4fbSAlexey Lapshin   virtual Error visit(Section &Sec) = 0;
9525d7b4fbSAlexey Lapshin   virtual Error visit(OwnedDataSection &Sec) = 0;
9625d7b4fbSAlexey Lapshin   virtual Error visit(StringTableSection &Sec) = 0;
9725d7b4fbSAlexey Lapshin   virtual Error visit(SymbolTableSection &Sec) = 0;
9825d7b4fbSAlexey Lapshin   virtual Error visit(RelocationSection &Sec) = 0;
9925d7b4fbSAlexey Lapshin   virtual Error visit(DynamicRelocationSection &Sec) = 0;
10025d7b4fbSAlexey Lapshin   virtual Error visit(GnuDebugLinkSection &Sec) = 0;
10125d7b4fbSAlexey Lapshin   virtual Error visit(GroupSection &Sec) = 0;
10225d7b4fbSAlexey Lapshin   virtual Error visit(SectionIndexSection &Sec) = 0;
10325d7b4fbSAlexey Lapshin   virtual Error visit(CompressedSection &Sec) = 0;
10425d7b4fbSAlexey Lapshin   virtual Error visit(DecompressedSection &Sec) = 0;
10525d7b4fbSAlexey Lapshin };
10625d7b4fbSAlexey Lapshin 
10725d7b4fbSAlexey Lapshin class SectionWriter : public SectionVisitor {
10825d7b4fbSAlexey Lapshin protected:
10925d7b4fbSAlexey Lapshin   WritableMemoryBuffer &Out;
11025d7b4fbSAlexey Lapshin 
11125d7b4fbSAlexey Lapshin public:
11225d7b4fbSAlexey Lapshin   virtual ~SectionWriter() = default;
11325d7b4fbSAlexey Lapshin 
11425d7b4fbSAlexey Lapshin   Error visit(const Section &Sec) override;
11525d7b4fbSAlexey Lapshin   Error visit(const OwnedDataSection &Sec) override;
11625d7b4fbSAlexey Lapshin   Error visit(const StringTableSection &Sec) override;
11725d7b4fbSAlexey Lapshin   Error visit(const DynamicRelocationSection &Sec) override;
118b5188591SKazu Hirata   Error visit(const SymbolTableSection &Sec) override = 0;
119b5188591SKazu Hirata   Error visit(const RelocationSection &Sec) override = 0;
120b5188591SKazu Hirata   Error visit(const GnuDebugLinkSection &Sec) override = 0;
121b5188591SKazu Hirata   Error visit(const GroupSection &Sec) override = 0;
122b5188591SKazu Hirata   Error visit(const SectionIndexSection &Sec) override = 0;
123b5188591SKazu Hirata   Error visit(const CompressedSection &Sec) override = 0;
124b5188591SKazu Hirata   Error visit(const DecompressedSection &Sec) override = 0;
12525d7b4fbSAlexey Lapshin 
12625d7b4fbSAlexey Lapshin   explicit SectionWriter(WritableMemoryBuffer &Buf) : Out(Buf) {}
12725d7b4fbSAlexey Lapshin };
12825d7b4fbSAlexey Lapshin 
12925d7b4fbSAlexey Lapshin template <class ELFT> class ELFSectionWriter : public SectionWriter {
13025d7b4fbSAlexey Lapshin private:
13125d7b4fbSAlexey Lapshin   using Elf_Word = typename ELFT::Word;
13225d7b4fbSAlexey Lapshin   using Elf_Rel = typename ELFT::Rel;
13325d7b4fbSAlexey Lapshin   using Elf_Rela = typename ELFT::Rela;
13425d7b4fbSAlexey Lapshin   using Elf_Sym = typename ELFT::Sym;
13525d7b4fbSAlexey Lapshin 
13625d7b4fbSAlexey Lapshin public:
13725d7b4fbSAlexey Lapshin   virtual ~ELFSectionWriter() {}
13825d7b4fbSAlexey Lapshin   Error visit(const SymbolTableSection &Sec) override;
13925d7b4fbSAlexey Lapshin   Error visit(const RelocationSection &Sec) override;
14025d7b4fbSAlexey Lapshin   Error visit(const GnuDebugLinkSection &Sec) override;
14125d7b4fbSAlexey Lapshin   Error visit(const GroupSection &Sec) override;
14225d7b4fbSAlexey Lapshin   Error visit(const SectionIndexSection &Sec) override;
14325d7b4fbSAlexey Lapshin   Error visit(const CompressedSection &Sec) override;
14425d7b4fbSAlexey Lapshin   Error visit(const DecompressedSection &Sec) override;
14525d7b4fbSAlexey Lapshin 
14625d7b4fbSAlexey Lapshin   explicit ELFSectionWriter(WritableMemoryBuffer &Buf) : SectionWriter(Buf) {}
14725d7b4fbSAlexey Lapshin };
14825d7b4fbSAlexey Lapshin 
14925d7b4fbSAlexey Lapshin template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {
15025d7b4fbSAlexey Lapshin private:
15125d7b4fbSAlexey Lapshin   using Elf_Rel = typename ELFT::Rel;
15225d7b4fbSAlexey Lapshin   using Elf_Rela = typename ELFT::Rela;
15325d7b4fbSAlexey Lapshin   using Elf_Sym = typename ELFT::Sym;
15425d7b4fbSAlexey Lapshin   using Elf_Word = typename ELFT::Word;
15525d7b4fbSAlexey Lapshin   using Elf_Xword = typename ELFT::Xword;
15625d7b4fbSAlexey Lapshin 
15725d7b4fbSAlexey Lapshin public:
15825d7b4fbSAlexey Lapshin   Error visit(Section &Sec) override;
15925d7b4fbSAlexey Lapshin   Error visit(OwnedDataSection &Sec) override;
16025d7b4fbSAlexey Lapshin   Error visit(StringTableSection &Sec) override;
16125d7b4fbSAlexey Lapshin   Error visit(DynamicRelocationSection &Sec) override;
16225d7b4fbSAlexey Lapshin   Error visit(SymbolTableSection &Sec) override;
16325d7b4fbSAlexey Lapshin   Error visit(RelocationSection &Sec) override;
16425d7b4fbSAlexey Lapshin   Error visit(GnuDebugLinkSection &Sec) override;
16525d7b4fbSAlexey Lapshin   Error visit(GroupSection &Sec) override;
16625d7b4fbSAlexey Lapshin   Error visit(SectionIndexSection &Sec) override;
16725d7b4fbSAlexey Lapshin   Error visit(CompressedSection &Sec) override;
16825d7b4fbSAlexey Lapshin   Error visit(DecompressedSection &Sec) override;
16925d7b4fbSAlexey Lapshin };
17025d7b4fbSAlexey Lapshin 
17125d7b4fbSAlexey Lapshin #define MAKE_SEC_WRITER_FRIEND                                                 \
17225d7b4fbSAlexey Lapshin   friend class SectionWriter;                                                  \
17325d7b4fbSAlexey Lapshin   friend class IHexSectionWriterBase;                                          \
17425d7b4fbSAlexey Lapshin   friend class IHexSectionWriter;                                              \
1757ddc3205Squic-areg   friend class SRECSectionWriter;                                              \
1767ddc3205Squic-areg   friend class SRECSectionWriterBase;                                          \
1777ddc3205Squic-areg   friend class SRECSizeCalculator;                                             \
17825d7b4fbSAlexey Lapshin   template <class ELFT> friend class ELFSectionWriter;                         \
17925d7b4fbSAlexey Lapshin   template <class ELFT> friend class ELFSectionSizer;
18025d7b4fbSAlexey Lapshin 
18125d7b4fbSAlexey Lapshin class BinarySectionWriter : public SectionWriter {
18225d7b4fbSAlexey Lapshin public:
18325d7b4fbSAlexey Lapshin   virtual ~BinarySectionWriter() {}
18425d7b4fbSAlexey Lapshin 
18525d7b4fbSAlexey Lapshin   Error visit(const SymbolTableSection &Sec) override;
18625d7b4fbSAlexey Lapshin   Error visit(const RelocationSection &Sec) override;
18725d7b4fbSAlexey Lapshin   Error visit(const GnuDebugLinkSection &Sec) override;
18825d7b4fbSAlexey Lapshin   Error visit(const GroupSection &Sec) override;
18925d7b4fbSAlexey Lapshin   Error visit(const SectionIndexSection &Sec) override;
19025d7b4fbSAlexey Lapshin   Error visit(const CompressedSection &Sec) override;
19125d7b4fbSAlexey Lapshin   Error visit(const DecompressedSection &Sec) override;
19225d7b4fbSAlexey Lapshin 
19325d7b4fbSAlexey Lapshin   explicit BinarySectionWriter(WritableMemoryBuffer &Buf)
19425d7b4fbSAlexey Lapshin       : SectionWriter(Buf) {}
19525d7b4fbSAlexey Lapshin };
19625d7b4fbSAlexey Lapshin 
19725d7b4fbSAlexey Lapshin using IHexLineData = SmallVector<char, 64>;
19825d7b4fbSAlexey Lapshin 
19925d7b4fbSAlexey Lapshin struct IHexRecord {
20025d7b4fbSAlexey Lapshin   // Memory address of the record.
20125d7b4fbSAlexey Lapshin   uint16_t Addr;
20225d7b4fbSAlexey Lapshin   // Record type (see below).
20325d7b4fbSAlexey Lapshin   uint16_t Type;
20425d7b4fbSAlexey Lapshin   // Record data in hexadecimal form.
20525d7b4fbSAlexey Lapshin   StringRef HexData;
20625d7b4fbSAlexey Lapshin 
20725d7b4fbSAlexey Lapshin   // Helper method to get file length of the record
20825d7b4fbSAlexey Lapshin   // including newline character
20925d7b4fbSAlexey Lapshin   static size_t getLength(size_t DataSize) {
21025d7b4fbSAlexey Lapshin     // :LLAAAATT[DD...DD]CC'
21125d7b4fbSAlexey Lapshin     return DataSize * 2 + 11;
21225d7b4fbSAlexey Lapshin   }
21325d7b4fbSAlexey Lapshin 
21425d7b4fbSAlexey Lapshin   // Gets length of line in a file (getLength + CRLF).
21525d7b4fbSAlexey Lapshin   static size_t getLineLength(size_t DataSize) {
21625d7b4fbSAlexey Lapshin     return getLength(DataSize) + 2;
21725d7b4fbSAlexey Lapshin   }
21825d7b4fbSAlexey Lapshin 
21925d7b4fbSAlexey Lapshin   // Given type, address and data returns line which can
22025d7b4fbSAlexey Lapshin   // be written to output file.
22125d7b4fbSAlexey Lapshin   static IHexLineData getLine(uint8_t Type, uint16_t Addr,
22225d7b4fbSAlexey Lapshin                               ArrayRef<uint8_t> Data);
22325d7b4fbSAlexey Lapshin 
22425d7b4fbSAlexey Lapshin   // Parses the line and returns record if possible.
22525d7b4fbSAlexey Lapshin   // Line should be trimmed from whitespace characters.
22625d7b4fbSAlexey Lapshin   static Expected<IHexRecord> parse(StringRef Line);
22725d7b4fbSAlexey Lapshin 
22825d7b4fbSAlexey Lapshin   // Calculates checksum of stringified record representation
22925d7b4fbSAlexey Lapshin   // S must NOT contain leading ':' and trailing whitespace
23025d7b4fbSAlexey Lapshin   // characters
23125d7b4fbSAlexey Lapshin   static uint8_t getChecksum(StringRef S);
23225d7b4fbSAlexey Lapshin 
23325d7b4fbSAlexey Lapshin   enum Type {
23425d7b4fbSAlexey Lapshin     // Contains data and a 16-bit starting address for the data.
23525d7b4fbSAlexey Lapshin     // The byte count specifies number of data bytes in the record.
23625d7b4fbSAlexey Lapshin     Data = 0,
23725d7b4fbSAlexey Lapshin     // Must occur exactly once per file in the last line of the file.
23825d7b4fbSAlexey Lapshin     // The data field is empty (thus byte count is 00) and the address
23925d7b4fbSAlexey Lapshin     // field is typically 0000.
24025d7b4fbSAlexey Lapshin     EndOfFile = 1,
24125d7b4fbSAlexey Lapshin     // The data field contains a 16-bit segment base address (thus byte
24225d7b4fbSAlexey Lapshin     // count is always 02) compatible with 80x86 real mode addressing.
24325d7b4fbSAlexey Lapshin     // The address field (typically 0000) is ignored. The segment address
24425d7b4fbSAlexey Lapshin     // from the most recent 02 record is multiplied by 16 and added to each
24525d7b4fbSAlexey Lapshin     // subsequent data record address to form the physical starting address
24625d7b4fbSAlexey Lapshin     // for the data. This allows addressing up to one megabyte of address
24725d7b4fbSAlexey Lapshin     // space.
24825d7b4fbSAlexey Lapshin     SegmentAddr = 2,
24925d7b4fbSAlexey Lapshin     // or 80x86 processors, specifies the initial content of the CS:IP
25025d7b4fbSAlexey Lapshin     // registers. The address field is 0000, the byte count is always 04,
25125d7b4fbSAlexey Lapshin     // the first two data bytes are the CS value, the latter two are the
25225d7b4fbSAlexey Lapshin     // IP value.
25325d7b4fbSAlexey Lapshin     StartAddr80x86 = 3,
25425d7b4fbSAlexey Lapshin     // Allows for 32 bit addressing (up to 4GiB). The record's address field
25525d7b4fbSAlexey Lapshin     // is ignored (typically 0000) and its byte count is always 02. The two
25625d7b4fbSAlexey Lapshin     // data bytes (big endian) specify the upper 16 bits of the 32 bit
25725d7b4fbSAlexey Lapshin     // absolute address for all subsequent type 00 records
25825d7b4fbSAlexey Lapshin     ExtendedAddr = 4,
25925d7b4fbSAlexey Lapshin     // The address field is 0000 (not used) and the byte count is always 04.
26025d7b4fbSAlexey Lapshin     // The four data bytes represent a 32-bit address value. In the case of
26125d7b4fbSAlexey Lapshin     // 80386 and higher CPUs, this address is loaded into the EIP register.
26225d7b4fbSAlexey Lapshin     StartAddr = 5,
26325d7b4fbSAlexey Lapshin     // We have no other valid types
26425d7b4fbSAlexey Lapshin     InvalidType = 6
26525d7b4fbSAlexey Lapshin   };
26625d7b4fbSAlexey Lapshin };
26725d7b4fbSAlexey Lapshin 
26825d7b4fbSAlexey Lapshin // Base class for IHexSectionWriter. This class implements writing algorithm,
26925d7b4fbSAlexey Lapshin // but doesn't actually write records. It is used for output buffer size
27025d7b4fbSAlexey Lapshin // calculation in IHexWriter::finalize.
27125d7b4fbSAlexey Lapshin class IHexSectionWriterBase : public BinarySectionWriter {
27225d7b4fbSAlexey Lapshin   // 20-bit segment address
27325d7b4fbSAlexey Lapshin   uint32_t SegmentAddr = 0;
27425d7b4fbSAlexey Lapshin   // Extended linear address
27525d7b4fbSAlexey Lapshin   uint32_t BaseAddr = 0;
27625d7b4fbSAlexey Lapshin 
27725d7b4fbSAlexey Lapshin   // Write segment address corresponding to 'Addr'
27825d7b4fbSAlexey Lapshin   uint64_t writeSegmentAddr(uint64_t Addr);
27925d7b4fbSAlexey Lapshin   // Write extended linear (base) address corresponding to 'Addr'
28025d7b4fbSAlexey Lapshin   uint64_t writeBaseAddr(uint64_t Addr);
28125d7b4fbSAlexey Lapshin 
28225d7b4fbSAlexey Lapshin protected:
28325d7b4fbSAlexey Lapshin   // Offset in the output buffer
28425d7b4fbSAlexey Lapshin   uint64_t Offset = 0;
28525d7b4fbSAlexey Lapshin 
28625d7b4fbSAlexey Lapshin   void writeSection(const SectionBase *Sec, ArrayRef<uint8_t> Data);
28725d7b4fbSAlexey Lapshin   virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);
28825d7b4fbSAlexey Lapshin 
28925d7b4fbSAlexey Lapshin public:
29025d7b4fbSAlexey Lapshin   explicit IHexSectionWriterBase(WritableMemoryBuffer &Buf)
29125d7b4fbSAlexey Lapshin       : BinarySectionWriter(Buf) {}
29225d7b4fbSAlexey Lapshin 
29325d7b4fbSAlexey Lapshin   uint64_t getBufferOffset() const { return Offset; }
29425d7b4fbSAlexey Lapshin   Error visit(const Section &Sec) final;
29525d7b4fbSAlexey Lapshin   Error visit(const OwnedDataSection &Sec) final;
29625d7b4fbSAlexey Lapshin   Error visit(const StringTableSection &Sec) override;
29725d7b4fbSAlexey Lapshin   Error visit(const DynamicRelocationSection &Sec) final;
29825d7b4fbSAlexey Lapshin   using BinarySectionWriter::visit;
29925d7b4fbSAlexey Lapshin };
30025d7b4fbSAlexey Lapshin 
30125d7b4fbSAlexey Lapshin // Real IHEX section writer
30225d7b4fbSAlexey Lapshin class IHexSectionWriter : public IHexSectionWriterBase {
30325d7b4fbSAlexey Lapshin public:
30425d7b4fbSAlexey Lapshin   IHexSectionWriter(WritableMemoryBuffer &Buf) : IHexSectionWriterBase(Buf) {}
30525d7b4fbSAlexey Lapshin 
30625d7b4fbSAlexey Lapshin   void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;
30725d7b4fbSAlexey Lapshin   Error visit(const StringTableSection &Sec) override;
30825d7b4fbSAlexey Lapshin };
30925d7b4fbSAlexey Lapshin 
31025d7b4fbSAlexey Lapshin class Writer {
31125d7b4fbSAlexey Lapshin protected:
31225d7b4fbSAlexey Lapshin   Object &Obj;
31325d7b4fbSAlexey Lapshin   std::unique_ptr<WritableMemoryBuffer> Buf;
31425d7b4fbSAlexey Lapshin   raw_ostream &Out;
31525d7b4fbSAlexey Lapshin 
31625d7b4fbSAlexey Lapshin public:
31725d7b4fbSAlexey Lapshin   virtual ~Writer();
31825d7b4fbSAlexey Lapshin   virtual Error finalize() = 0;
31925d7b4fbSAlexey Lapshin   virtual Error write() = 0;
32025d7b4fbSAlexey Lapshin 
32125d7b4fbSAlexey Lapshin   Writer(Object &O, raw_ostream &Out) : Obj(O), Out(Out) {}
32225d7b4fbSAlexey Lapshin };
32325d7b4fbSAlexey Lapshin 
32425d7b4fbSAlexey Lapshin template <class ELFT> class ELFWriter : public Writer {
32525d7b4fbSAlexey Lapshin private:
32625d7b4fbSAlexey Lapshin   using Elf_Addr = typename ELFT::Addr;
32725d7b4fbSAlexey Lapshin   using Elf_Shdr = typename ELFT::Shdr;
32825d7b4fbSAlexey Lapshin   using Elf_Phdr = typename ELFT::Phdr;
32925d7b4fbSAlexey Lapshin   using Elf_Ehdr = typename ELFT::Ehdr;
33025d7b4fbSAlexey Lapshin 
33125d7b4fbSAlexey Lapshin   void initEhdrSegment();
33225d7b4fbSAlexey Lapshin 
33325d7b4fbSAlexey Lapshin   void writeEhdr();
33425d7b4fbSAlexey Lapshin   void writePhdr(const Segment &Seg);
33525d7b4fbSAlexey Lapshin   void writeShdr(const SectionBase &Sec);
33625d7b4fbSAlexey Lapshin 
33725d7b4fbSAlexey Lapshin   void writePhdrs();
33825d7b4fbSAlexey Lapshin   void writeShdrs();
33925d7b4fbSAlexey Lapshin   Error writeSectionData();
34025d7b4fbSAlexey Lapshin   void writeSegmentData();
34125d7b4fbSAlexey Lapshin 
34225d7b4fbSAlexey Lapshin   void assignOffsets();
34325d7b4fbSAlexey Lapshin 
34425d7b4fbSAlexey Lapshin   std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;
34525d7b4fbSAlexey Lapshin 
34625d7b4fbSAlexey Lapshin   size_t totalSize() const;
34725d7b4fbSAlexey Lapshin 
34825d7b4fbSAlexey Lapshin public:
34925d7b4fbSAlexey Lapshin   virtual ~ELFWriter() {}
35025d7b4fbSAlexey Lapshin   bool WriteSectionHeaders;
35125d7b4fbSAlexey Lapshin 
35225d7b4fbSAlexey Lapshin   // For --only-keep-debug, select an alternative section/segment layout
35325d7b4fbSAlexey Lapshin   // algorithm.
35425d7b4fbSAlexey Lapshin   bool OnlyKeepDebug;
35525d7b4fbSAlexey Lapshin 
35625d7b4fbSAlexey Lapshin   Error finalize() override;
35725d7b4fbSAlexey Lapshin   Error write() override;
35825d7b4fbSAlexey Lapshin   ELFWriter(Object &Obj, raw_ostream &Out, bool WSH, bool OnlyKeepDebug);
35925d7b4fbSAlexey Lapshin };
36025d7b4fbSAlexey Lapshin 
36125d7b4fbSAlexey Lapshin class BinaryWriter : public Writer {
36225d7b4fbSAlexey Lapshin private:
3634070dffdSquic-akaryaki   const uint8_t GapFill;
3644070dffdSquic-akaryaki   const uint64_t PadTo;
36525d7b4fbSAlexey Lapshin   std::unique_ptr<BinarySectionWriter> SecWriter;
36625d7b4fbSAlexey Lapshin 
36725d7b4fbSAlexey Lapshin   uint64_t TotalSize = 0;
36825d7b4fbSAlexey Lapshin 
36925d7b4fbSAlexey Lapshin public:
37025d7b4fbSAlexey Lapshin   ~BinaryWriter() {}
37125d7b4fbSAlexey Lapshin   Error finalize() override;
37225d7b4fbSAlexey Lapshin   Error write() override;
3734070dffdSquic-akaryaki   BinaryWriter(Object &Obj, raw_ostream &Out, const CommonConfig &Config)
3744070dffdSquic-akaryaki       : Writer(Obj, Out), GapFill(Config.GapFill), PadTo(Config.PadTo) {}
37525d7b4fbSAlexey Lapshin };
37625d7b4fbSAlexey Lapshin 
3777ddc3205Squic-areg // A base class for writing ascii hex formats such as srec and ihex.
3787ddc3205Squic-areg class ASCIIHexWriter : public Writer {
3797ddc3205Squic-areg public:
3807ddc3205Squic-areg   ASCIIHexWriter(Object &Obj, raw_ostream &OS, StringRef OutputFile)
3817ddc3205Squic-areg       : Writer(Obj, OS), OutputFileName(OutputFile) {}
3827ddc3205Squic-areg   Error finalize() override;
3837ddc3205Squic-areg 
3847ddc3205Squic-areg protected:
3857ddc3205Squic-areg   StringRef OutputFileName;
3867ddc3205Squic-areg   size_t TotalSize = 0;
3877ddc3205Squic-areg   std::vector<const SectionBase *> Sections;
3887ddc3205Squic-areg 
3897ddc3205Squic-areg   Error checkSection(const SectionBase &S) const;
3907ddc3205Squic-areg   virtual Expected<size_t>
3917ddc3205Squic-areg   getTotalSize(WritableMemoryBuffer &EmptyBuffer) const = 0;
39225d7b4fbSAlexey Lapshin };
39325d7b4fbSAlexey Lapshin 
3947ddc3205Squic-areg class IHexWriter : public ASCIIHexWriter {
3957ddc3205Squic-areg public:
3967ddc3205Squic-areg   Error write() override;
3977ddc3205Squic-areg   IHexWriter(Object &Obj, raw_ostream &Out, StringRef OutputFile)
3987ddc3205Squic-areg       : ASCIIHexWriter(Obj, Out, OutputFile) {}
39925d7b4fbSAlexey Lapshin 
4007ddc3205Squic-areg private:
40125d7b4fbSAlexey Lapshin   uint64_t writeEntryPointRecord(uint8_t *Buf);
40225d7b4fbSAlexey Lapshin   uint64_t writeEndOfFileRecord(uint8_t *Buf);
4037ddc3205Squic-areg   Expected<size_t>
4047ddc3205Squic-areg   getTotalSize(WritableMemoryBuffer &EmptyBuffer) const override;
4057ddc3205Squic-areg };
40625d7b4fbSAlexey Lapshin 
4077ddc3205Squic-areg class SRECWriter : public ASCIIHexWriter {
40825d7b4fbSAlexey Lapshin public:
4097ddc3205Squic-areg   SRECWriter(Object &Obj, raw_ostream &OS, StringRef OutputFile)
4107ddc3205Squic-areg       : ASCIIHexWriter(Obj, OS, OutputFile) {}
41125d7b4fbSAlexey Lapshin   Error write() override;
4127ddc3205Squic-areg 
4137ddc3205Squic-areg private:
4147ddc3205Squic-areg   size_t writeHeader(uint8_t *Buf);
4157ddc3205Squic-areg   size_t writeTerminator(uint8_t *Buf, uint8_t Type);
4167ddc3205Squic-areg   Expected<size_t>
4177ddc3205Squic-areg   getTotalSize(WritableMemoryBuffer &EmptyBuffer) const override;
4187ddc3205Squic-areg };
4197ddc3205Squic-areg 
4207ddc3205Squic-areg using SRecLineData = SmallVector<char, 64>;
4217ddc3205Squic-areg struct SRecord {
4227ddc3205Squic-areg   uint8_t Type;
4237ddc3205Squic-areg   uint32_t Address;
4247ddc3205Squic-areg   ArrayRef<uint8_t> Data;
4257ddc3205Squic-areg   SRecLineData toString() const;
4267ddc3205Squic-areg   uint8_t getCount() const;
4277ddc3205Squic-areg   // Get address size in characters.
4287ddc3205Squic-areg   uint8_t getAddressSize() const;
4297ddc3205Squic-areg   uint8_t getChecksum() const;
4307ddc3205Squic-areg   size_t getSize() const;
4317ddc3205Squic-areg   static SRecord getHeader(StringRef FileName);
4327ddc3205Squic-areg   static uint8_t getType(uint32_t Address);
4337ddc3205Squic-areg 
4347ddc3205Squic-areg   enum Type : uint8_t {
4357ddc3205Squic-areg     // Vendor specific text comment.
4367ddc3205Squic-areg     S0 = 0,
4377ddc3205Squic-areg     // Data that starts at a 16 bit address.
4387ddc3205Squic-areg     S1 = 1,
4397ddc3205Squic-areg     // Data that starts at a 24 bit address.
4407ddc3205Squic-areg     S2 = 2,
4417ddc3205Squic-areg     // Data that starts at a 32 bit address.
4427ddc3205Squic-areg     S3 = 3,
4437ddc3205Squic-areg     // Reserved.
4447ddc3205Squic-areg     S4 = 4,
4457ddc3205Squic-areg     // 16 bit count of S1/S2/S3 records (optional).
4467ddc3205Squic-areg     S5 = 5,
4477ddc3205Squic-areg     // 32 bit count of S1/S2/S3 records (optional).
4487ddc3205Squic-areg     S6 = 6,
4497ddc3205Squic-areg     // Terminates a series of S3 records.
4507ddc3205Squic-areg     S7 = 7,
4517ddc3205Squic-areg     // Terminates a series of S2 records.
4527ddc3205Squic-areg     S8 = 8,
4537ddc3205Squic-areg     // Terminates a series of S1 records.
4547ddc3205Squic-areg     S9 = 9
4557ddc3205Squic-areg   };
4567ddc3205Squic-areg };
4577ddc3205Squic-areg 
4587ddc3205Squic-areg class SRECSectionWriterBase : public BinarySectionWriter {
4597ddc3205Squic-areg public:
4607ddc3205Squic-areg   explicit SRECSectionWriterBase(WritableMemoryBuffer &Buf,
4617ddc3205Squic-areg                                  uint64_t StartOffset)
4627ddc3205Squic-areg       : BinarySectionWriter(Buf), Offset(StartOffset), HeaderSize(StartOffset) {
4637ddc3205Squic-areg   }
4647ddc3205Squic-areg 
4657ddc3205Squic-areg   using BinarySectionWriter::visit;
4667ddc3205Squic-areg 
4677ddc3205Squic-areg   void writeRecords(uint32_t Entry);
4687ddc3205Squic-areg   uint64_t getBufferOffset() const { return Offset; }
4697ddc3205Squic-areg   Error visit(const Section &S) override;
4707ddc3205Squic-areg   Error visit(const OwnedDataSection &S) override;
4717ddc3205Squic-areg   Error visit(const StringTableSection &S) override;
4727ddc3205Squic-areg   Error visit(const DynamicRelocationSection &S) override;
4737ddc3205Squic-areg   uint8_t getType() const { return Type; };
4747ddc3205Squic-areg 
4757ddc3205Squic-areg protected:
4767ddc3205Squic-areg   // Offset in the output buffer.
4777ddc3205Squic-areg   uint64_t Offset;
4787ddc3205Squic-areg   // Sections start after the header.
4797ddc3205Squic-areg   uint64_t HeaderSize;
4807ddc3205Squic-areg   // Type of records to write.
4817ddc3205Squic-areg   uint8_t Type = SRecord::S1;
4827ddc3205Squic-areg   std::vector<SRecord> Records;
4837ddc3205Squic-areg 
4847ddc3205Squic-areg   void writeSection(const SectionBase &S, ArrayRef<uint8_t> Data);
4857ddc3205Squic-areg   virtual void writeRecord(SRecord &Record, uint64_t Off) = 0;
4867ddc3205Squic-areg };
4877ddc3205Squic-areg 
4887ddc3205Squic-areg // An SRECSectionWriterBase that visits sections but does not write anything.
4897ddc3205Squic-areg // This class is only used to calculate the size of the output file.
4907ddc3205Squic-areg class SRECSizeCalculator : public SRECSectionWriterBase {
4917ddc3205Squic-areg public:
4927ddc3205Squic-areg   SRECSizeCalculator(WritableMemoryBuffer &EmptyBuffer, uint64_t Offset)
4937ddc3205Squic-areg       : SRECSectionWriterBase(EmptyBuffer, Offset) {}
4947ddc3205Squic-areg 
4957ddc3205Squic-areg protected:
4967ddc3205Squic-areg   void writeRecord(SRecord &Record, uint64_t Off) override {}
4977ddc3205Squic-areg };
4987ddc3205Squic-areg 
4997ddc3205Squic-areg class SRECSectionWriter : public SRECSectionWriterBase {
5007ddc3205Squic-areg public:
5017ddc3205Squic-areg   SRECSectionWriter(WritableMemoryBuffer &Buf, uint64_t Offset)
5027ddc3205Squic-areg       : SRECSectionWriterBase(Buf, Offset) {}
5037ddc3205Squic-areg   Error visit(const StringTableSection &Sec) override;
5047ddc3205Squic-areg 
5057ddc3205Squic-areg protected:
5067ddc3205Squic-areg   void writeRecord(SRecord &Record, uint64_t Off) override;
50725d7b4fbSAlexey Lapshin };
50825d7b4fbSAlexey Lapshin 
50925d7b4fbSAlexey Lapshin class SectionBase {
51025d7b4fbSAlexey Lapshin public:
51125d7b4fbSAlexey Lapshin   std::string Name;
51225d7b4fbSAlexey Lapshin   Segment *ParentSegment = nullptr;
51325d7b4fbSAlexey Lapshin   uint64_t HeaderOffset = 0;
51425d7b4fbSAlexey Lapshin   uint32_t Index = 0;
51525d7b4fbSAlexey Lapshin 
51625d7b4fbSAlexey Lapshin   uint32_t OriginalIndex = 0;
51725d7b4fbSAlexey Lapshin   uint64_t OriginalFlags = 0;
51825d7b4fbSAlexey Lapshin   uint64_t OriginalType = ELF::SHT_NULL;
51925d7b4fbSAlexey Lapshin   uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();
52025d7b4fbSAlexey Lapshin 
52125d7b4fbSAlexey Lapshin   uint64_t Addr = 0;
52225d7b4fbSAlexey Lapshin   uint64_t Align = 1;
52325d7b4fbSAlexey Lapshin   uint32_t EntrySize = 0;
52425d7b4fbSAlexey Lapshin   uint64_t Flags = 0;
52525d7b4fbSAlexey Lapshin   uint64_t Info = 0;
52625d7b4fbSAlexey Lapshin   uint64_t Link = ELF::SHN_UNDEF;
52725d7b4fbSAlexey Lapshin   uint64_t NameIndex = 0;
52825d7b4fbSAlexey Lapshin   uint64_t Offset = 0;
52925d7b4fbSAlexey Lapshin   uint64_t Size = 0;
53025d7b4fbSAlexey Lapshin   uint64_t Type = ELF::SHT_NULL;
53125d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> OriginalData;
53225d7b4fbSAlexey Lapshin   bool HasSymbol = false;
53325d7b4fbSAlexey Lapshin 
53425d7b4fbSAlexey Lapshin   SectionBase() = default;
53525d7b4fbSAlexey Lapshin   SectionBase(const SectionBase &) = default;
53625d7b4fbSAlexey Lapshin 
53725d7b4fbSAlexey Lapshin   virtual ~SectionBase() = default;
53825d7b4fbSAlexey Lapshin 
53925d7b4fbSAlexey Lapshin   virtual Error initialize(SectionTableRef SecTable);
54025d7b4fbSAlexey Lapshin   virtual void finalize();
54125d7b4fbSAlexey Lapshin   // Remove references to these sections. The list of sections must be sorted.
54225d7b4fbSAlexey Lapshin   virtual Error
54325d7b4fbSAlexey Lapshin   removeSectionReferences(bool AllowBrokenLinks,
54425d7b4fbSAlexey Lapshin                           function_ref<bool(const SectionBase *)> ToRemove);
54525d7b4fbSAlexey Lapshin   virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
54625d7b4fbSAlexey Lapshin   virtual Error accept(SectionVisitor &Visitor) const = 0;
54725d7b4fbSAlexey Lapshin   virtual Error accept(MutableSectionVisitor &Visitor) = 0;
54825d7b4fbSAlexey Lapshin   virtual void markSymbols();
54925d7b4fbSAlexey Lapshin   virtual void
55025d7b4fbSAlexey Lapshin   replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
55125d7b4fbSAlexey Lapshin   virtual bool hasContents() const { return false; }
552*10772807SIgor Kudrin   virtual ArrayRef<uint8_t> getContents() const { return {}; }
55325d7b4fbSAlexey Lapshin   // Notify the section that it is subject to removal.
55425d7b4fbSAlexey Lapshin   virtual void onRemove();
555744e589cSAndrew Ng 
556744e589cSAndrew Ng   virtual void restoreSymTabLink(SymbolTableSection &) {}
55725d7b4fbSAlexey Lapshin };
55825d7b4fbSAlexey Lapshin 
55925d7b4fbSAlexey Lapshin class Segment {
56025d7b4fbSAlexey Lapshin private:
56125d7b4fbSAlexey Lapshin   struct SectionCompare {
56225d7b4fbSAlexey Lapshin     bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {
56325d7b4fbSAlexey Lapshin       // Some sections might have the same address if one of them is empty. To
56425d7b4fbSAlexey Lapshin       // fix this we can use the lexicographic ordering on ->Addr and the
56525d7b4fbSAlexey Lapshin       // original index.
56625d7b4fbSAlexey Lapshin       if (Lhs->OriginalOffset == Rhs->OriginalOffset)
56725d7b4fbSAlexey Lapshin         return Lhs->OriginalIndex < Rhs->OriginalIndex;
56825d7b4fbSAlexey Lapshin       return Lhs->OriginalOffset < Rhs->OriginalOffset;
56925d7b4fbSAlexey Lapshin     }
57025d7b4fbSAlexey Lapshin   };
57125d7b4fbSAlexey Lapshin 
57225d7b4fbSAlexey Lapshin public:
57325d7b4fbSAlexey Lapshin   uint32_t Type = 0;
57425d7b4fbSAlexey Lapshin   uint32_t Flags = 0;
57525d7b4fbSAlexey Lapshin   uint64_t Offset = 0;
57625d7b4fbSAlexey Lapshin   uint64_t VAddr = 0;
57725d7b4fbSAlexey Lapshin   uint64_t PAddr = 0;
57825d7b4fbSAlexey Lapshin   uint64_t FileSize = 0;
57925d7b4fbSAlexey Lapshin   uint64_t MemSize = 0;
58025d7b4fbSAlexey Lapshin   uint64_t Align = 0;
58125d7b4fbSAlexey Lapshin 
58225d7b4fbSAlexey Lapshin   uint32_t Index = 0;
58325d7b4fbSAlexey Lapshin   uint64_t OriginalOffset = 0;
58425d7b4fbSAlexey Lapshin   Segment *ParentSegment = nullptr;
58525d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> Contents;
58625d7b4fbSAlexey Lapshin   std::set<const SectionBase *, SectionCompare> Sections;
58725d7b4fbSAlexey Lapshin 
58825d7b4fbSAlexey Lapshin   explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
58925d7b4fbSAlexey Lapshin   Segment() = default;
59025d7b4fbSAlexey Lapshin 
59125d7b4fbSAlexey Lapshin   const SectionBase *firstSection() const {
59225d7b4fbSAlexey Lapshin     if (!Sections.empty())
59325d7b4fbSAlexey Lapshin       return *Sections.begin();
59425d7b4fbSAlexey Lapshin     return nullptr;
59525d7b4fbSAlexey Lapshin   }
59625d7b4fbSAlexey Lapshin 
59725d7b4fbSAlexey Lapshin   void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }
59825d7b4fbSAlexey Lapshin   void addSection(const SectionBase *Sec) { Sections.insert(Sec); }
59925d7b4fbSAlexey Lapshin 
60025d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> getContents() const { return Contents; }
60125d7b4fbSAlexey Lapshin };
60225d7b4fbSAlexey Lapshin 
60325d7b4fbSAlexey Lapshin class Section : public SectionBase {
60425d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
60525d7b4fbSAlexey Lapshin 
60625d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> Contents;
60725d7b4fbSAlexey Lapshin   SectionBase *LinkSection = nullptr;
608744e589cSAndrew Ng   bool HasSymTabLink = false;
60925d7b4fbSAlexey Lapshin 
61025d7b4fbSAlexey Lapshin public:
61125d7b4fbSAlexey Lapshin   explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
61225d7b4fbSAlexey Lapshin 
61325d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Visitor) const override;
61425d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
61525d7b4fbSAlexey Lapshin   Error removeSectionReferences(
61625d7b4fbSAlexey Lapshin       bool AllowBrokenLinks,
61725d7b4fbSAlexey Lapshin       function_ref<bool(const SectionBase *)> ToRemove) override;
61825d7b4fbSAlexey Lapshin   Error initialize(SectionTableRef SecTable) override;
61925d7b4fbSAlexey Lapshin   void finalize() override;
62025d7b4fbSAlexey Lapshin   bool hasContents() const override {
62125d7b4fbSAlexey Lapshin     return Type != ELF::SHT_NOBITS && Type != ELF::SHT_NULL;
62225d7b4fbSAlexey Lapshin   }
623*10772807SIgor Kudrin   ArrayRef<uint8_t> getContents() const override { return Contents; }
624*10772807SIgor Kudrin 
625744e589cSAndrew Ng   void restoreSymTabLink(SymbolTableSection &SymTab) override;
62625d7b4fbSAlexey Lapshin };
62725d7b4fbSAlexey Lapshin 
62825d7b4fbSAlexey Lapshin class OwnedDataSection : public SectionBase {
62925d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
63025d7b4fbSAlexey Lapshin 
63125d7b4fbSAlexey Lapshin   std::vector<uint8_t> Data;
63225d7b4fbSAlexey Lapshin 
63325d7b4fbSAlexey Lapshin public:
63425d7b4fbSAlexey Lapshin   OwnedDataSection(StringRef SecName, ArrayRef<uint8_t> Data)
63525d7b4fbSAlexey Lapshin       : Data(std::begin(Data), std::end(Data)) {
63625d7b4fbSAlexey Lapshin     Name = SecName.str();
63725d7b4fbSAlexey Lapshin     Type = OriginalType = ELF::SHT_PROGBITS;
63825d7b4fbSAlexey Lapshin     Size = Data.size();
63925d7b4fbSAlexey Lapshin     OriginalOffset = std::numeric_limits<uint64_t>::max();
64025d7b4fbSAlexey Lapshin   }
64125d7b4fbSAlexey Lapshin 
64225d7b4fbSAlexey Lapshin   OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,
64325d7b4fbSAlexey Lapshin                    uint64_t SecOff) {
64425d7b4fbSAlexey Lapshin     Name = SecName.str();
64525d7b4fbSAlexey Lapshin     Type = OriginalType = ELF::SHT_PROGBITS;
64625d7b4fbSAlexey Lapshin     Addr = SecAddr;
64725d7b4fbSAlexey Lapshin     Flags = OriginalFlags = SecFlags;
64825d7b4fbSAlexey Lapshin     OriginalOffset = SecOff;
64925d7b4fbSAlexey Lapshin   }
65025d7b4fbSAlexey Lapshin 
65125d7b4fbSAlexey Lapshin   OwnedDataSection(SectionBase &S, ArrayRef<uint8_t> Data)
65225d7b4fbSAlexey Lapshin       : SectionBase(S), Data(std::begin(Data), std::end(Data)) {
65325d7b4fbSAlexey Lapshin     Size = Data.size();
65425d7b4fbSAlexey Lapshin   }
65525d7b4fbSAlexey Lapshin 
65625d7b4fbSAlexey Lapshin   void appendHexData(StringRef HexData);
65725d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Sec) const override;
65825d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
65925d7b4fbSAlexey Lapshin   bool hasContents() const override { return true; }
660*10772807SIgor Kudrin   ArrayRef<uint8_t> getContents() const override { return Data; }
66125d7b4fbSAlexey Lapshin };
66225d7b4fbSAlexey Lapshin 
66325d7b4fbSAlexey Lapshin class CompressedSection : public SectionBase {
66425d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
66525d7b4fbSAlexey Lapshin 
666b6e1fd76SFangrui Song   uint32_t ChType = 0;
66725d7b4fbSAlexey Lapshin   DebugCompressionType CompressionType;
66825d7b4fbSAlexey Lapshin   uint64_t DecompressedSize;
66925d7b4fbSAlexey Lapshin   uint64_t DecompressedAlign;
670e690137dSFangrui Song   SmallVector<uint8_t, 128> CompressedData;
67125d7b4fbSAlexey Lapshin 
67225d7b4fbSAlexey Lapshin public:
673cce35210SFangrui Song   CompressedSection(const SectionBase &Sec,
674c997fe65SFangrui Song     DebugCompressionType CompressionType, bool Is64Bits);
675b6e1fd76SFangrui Song   CompressedSection(ArrayRef<uint8_t> CompressedData, uint32_t ChType,
676b6e1fd76SFangrui Song                     uint64_t DecompressedSize, uint64_t DecompressedAlign);
67725d7b4fbSAlexey Lapshin 
67825d7b4fbSAlexey Lapshin   uint64_t getDecompressedSize() const { return DecompressedSize; }
67925d7b4fbSAlexey Lapshin   uint64_t getDecompressedAlign() const { return DecompressedAlign; }
680b6e1fd76SFangrui Song   uint64_t getChType() const { return ChType; }
68125d7b4fbSAlexey Lapshin 
68225d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Visitor) const override;
68325d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
68425d7b4fbSAlexey Lapshin 
68525d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
68645ae5531SFangrui Song     return S->OriginalFlags & ELF::SHF_COMPRESSED;
68725d7b4fbSAlexey Lapshin   }
68825d7b4fbSAlexey Lapshin };
68925d7b4fbSAlexey Lapshin 
69025d7b4fbSAlexey Lapshin class DecompressedSection : public SectionBase {
69125d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
69225d7b4fbSAlexey Lapshin 
69325d7b4fbSAlexey Lapshin public:
694b6e1fd76SFangrui Song   uint32_t ChType;
69525d7b4fbSAlexey Lapshin   explicit DecompressedSection(const CompressedSection &Sec)
696b6e1fd76SFangrui Song       : SectionBase(Sec), ChType(Sec.getChType()) {
69725d7b4fbSAlexey Lapshin     Size = Sec.getDecompressedSize();
69825d7b4fbSAlexey Lapshin     Align = Sec.getDecompressedAlign();
69925d7b4fbSAlexey Lapshin     Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED);
70025d7b4fbSAlexey Lapshin   }
70125d7b4fbSAlexey Lapshin 
70225d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Visitor) const override;
70325d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
70425d7b4fbSAlexey Lapshin };
70525d7b4fbSAlexey Lapshin 
70625d7b4fbSAlexey Lapshin // There are two types of string tables that can exist, dynamic and not dynamic.
70725d7b4fbSAlexey Lapshin // In the dynamic case the string table is allocated. Changing a dynamic string
70825d7b4fbSAlexey Lapshin // table would mean altering virtual addresses and thus the memory image. So
70925d7b4fbSAlexey Lapshin // dynamic string tables should not have an interface to modify them or
71025d7b4fbSAlexey Lapshin // reconstruct them. This type lets us reconstruct a string table. To avoid
71125d7b4fbSAlexey Lapshin // this class being used for dynamic string tables (which has happened) the
71225d7b4fbSAlexey Lapshin // classof method checks that the particular instance is not allocated. This
71325d7b4fbSAlexey Lapshin // then agrees with the makeSection method used to construct most sections.
71425d7b4fbSAlexey Lapshin class StringTableSection : public SectionBase {
71525d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
71625d7b4fbSAlexey Lapshin 
71725d7b4fbSAlexey Lapshin   StringTableBuilder StrTabBuilder;
71825d7b4fbSAlexey Lapshin 
71925d7b4fbSAlexey Lapshin public:
72025d7b4fbSAlexey Lapshin   StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {
72125d7b4fbSAlexey Lapshin     Type = OriginalType = ELF::SHT_STRTAB;
72225d7b4fbSAlexey Lapshin   }
72325d7b4fbSAlexey Lapshin 
72425d7b4fbSAlexey Lapshin   void addString(StringRef Name);
72525d7b4fbSAlexey Lapshin   uint32_t findIndex(StringRef Name) const;
72625d7b4fbSAlexey Lapshin   void prepareForLayout();
72725d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Visitor) const override;
72825d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
72925d7b4fbSAlexey Lapshin 
73025d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
73125d7b4fbSAlexey Lapshin     if (S->OriginalFlags & ELF::SHF_ALLOC)
73225d7b4fbSAlexey Lapshin       return false;
73325d7b4fbSAlexey Lapshin     return S->OriginalType == ELF::SHT_STRTAB;
73425d7b4fbSAlexey Lapshin   }
73525d7b4fbSAlexey Lapshin };
73625d7b4fbSAlexey Lapshin 
73725d7b4fbSAlexey Lapshin // Symbols have a st_shndx field that normally stores an index but occasionally
73825d7b4fbSAlexey Lapshin // stores a different special value. This enum keeps track of what the st_shndx
73925d7b4fbSAlexey Lapshin // field means. Most of the values are just copies of the special SHN_* values.
74025d7b4fbSAlexey Lapshin // SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
74125d7b4fbSAlexey Lapshin enum SymbolShndxType {
74225d7b4fbSAlexey Lapshin   SYMBOL_SIMPLE_INDEX = 0,
74325d7b4fbSAlexey Lapshin   SYMBOL_ABS = ELF::SHN_ABS,
74425d7b4fbSAlexey Lapshin   SYMBOL_COMMON = ELF::SHN_COMMON,
74525d7b4fbSAlexey Lapshin   SYMBOL_LOPROC = ELF::SHN_LOPROC,
74625d7b4fbSAlexey Lapshin   SYMBOL_AMDGPU_LDS = ELF::SHN_AMDGPU_LDS,
74725d7b4fbSAlexey Lapshin   SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,
74825d7b4fbSAlexey Lapshin   SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,
74925d7b4fbSAlexey Lapshin   SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,
75025d7b4fbSAlexey Lapshin   SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,
7519da89651SAnubhab Ghosh   SYMBOL_MIPS_ACOMMON = ELF::SHN_MIPS_ACOMMON,
7529da89651SAnubhab Ghosh   SYMBOL_MIPS_TEXT = ELF::SHN_MIPS_TEXT,
7539da89651SAnubhab Ghosh   SYMBOL_MIPS_DATA = ELF::SHN_MIPS_DATA,
7549da89651SAnubhab Ghosh   SYMBOL_MIPS_SCOMMON = ELF::SHN_MIPS_SCOMMON,
7559da89651SAnubhab Ghosh   SYMBOL_MIPS_SUNDEFINED = ELF::SHN_MIPS_SUNDEFINED,
75625d7b4fbSAlexey Lapshin   SYMBOL_HIPROC = ELF::SHN_HIPROC,
75725d7b4fbSAlexey Lapshin   SYMBOL_LOOS = ELF::SHN_LOOS,
75825d7b4fbSAlexey Lapshin   SYMBOL_HIOS = ELF::SHN_HIOS,
75925d7b4fbSAlexey Lapshin   SYMBOL_XINDEX = ELF::SHN_XINDEX,
76025d7b4fbSAlexey Lapshin };
76125d7b4fbSAlexey Lapshin 
76225d7b4fbSAlexey Lapshin struct Symbol {
76325d7b4fbSAlexey Lapshin   uint8_t Binding;
76425d7b4fbSAlexey Lapshin   SectionBase *DefinedIn = nullptr;
76525d7b4fbSAlexey Lapshin   SymbolShndxType ShndxType;
76625d7b4fbSAlexey Lapshin   uint32_t Index;
76725d7b4fbSAlexey Lapshin   std::string Name;
76825d7b4fbSAlexey Lapshin   uint32_t NameIndex;
76925d7b4fbSAlexey Lapshin   uint64_t Size;
77025d7b4fbSAlexey Lapshin   uint8_t Type;
77125d7b4fbSAlexey Lapshin   uint64_t Value;
77225d7b4fbSAlexey Lapshin   uint8_t Visibility;
77325d7b4fbSAlexey Lapshin   bool Referenced = false;
77425d7b4fbSAlexey Lapshin 
77525d7b4fbSAlexey Lapshin   uint16_t getShndx() const;
77625d7b4fbSAlexey Lapshin   bool isCommon() const;
77725d7b4fbSAlexey Lapshin };
77825d7b4fbSAlexey Lapshin 
77925d7b4fbSAlexey Lapshin class SectionIndexSection : public SectionBase {
78025d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
78125d7b4fbSAlexey Lapshin 
78225d7b4fbSAlexey Lapshin private:
78325d7b4fbSAlexey Lapshin   std::vector<uint32_t> Indexes;
78425d7b4fbSAlexey Lapshin   SymbolTableSection *Symbols = nullptr;
78525d7b4fbSAlexey Lapshin 
78625d7b4fbSAlexey Lapshin public:
78725d7b4fbSAlexey Lapshin   virtual ~SectionIndexSection() {}
78825d7b4fbSAlexey Lapshin   void addIndex(uint32_t Index) {
78925d7b4fbSAlexey Lapshin     assert(Size > 0);
79025d7b4fbSAlexey Lapshin     Indexes.push_back(Index);
79125d7b4fbSAlexey Lapshin   }
79225d7b4fbSAlexey Lapshin 
79325d7b4fbSAlexey Lapshin   void reserve(size_t NumSymbols) {
79425d7b4fbSAlexey Lapshin     Indexes.reserve(NumSymbols);
79525d7b4fbSAlexey Lapshin     Size = NumSymbols * 4;
79625d7b4fbSAlexey Lapshin   }
79725d7b4fbSAlexey Lapshin   void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }
79825d7b4fbSAlexey Lapshin   Error initialize(SectionTableRef SecTable) override;
79925d7b4fbSAlexey Lapshin   void finalize() override;
80025d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Visitor) const override;
80125d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
80225d7b4fbSAlexey Lapshin 
80325d7b4fbSAlexey Lapshin   SectionIndexSection() {
80425d7b4fbSAlexey Lapshin     Name = ".symtab_shndx";
80525d7b4fbSAlexey Lapshin     Align = 4;
80625d7b4fbSAlexey Lapshin     EntrySize = 4;
80725d7b4fbSAlexey Lapshin     Type = OriginalType = ELF::SHT_SYMTAB_SHNDX;
80825d7b4fbSAlexey Lapshin   }
80925d7b4fbSAlexey Lapshin };
81025d7b4fbSAlexey Lapshin 
81125d7b4fbSAlexey Lapshin class SymbolTableSection : public SectionBase {
81225d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
81325d7b4fbSAlexey Lapshin 
81425d7b4fbSAlexey Lapshin   void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
81525d7b4fbSAlexey Lapshin   void assignIndices();
81625d7b4fbSAlexey Lapshin 
81725d7b4fbSAlexey Lapshin protected:
81825d7b4fbSAlexey Lapshin   std::vector<std::unique_ptr<Symbol>> Symbols;
81925d7b4fbSAlexey Lapshin   StringTableSection *SymbolNames = nullptr;
82025d7b4fbSAlexey Lapshin   SectionIndexSection *SectionIndexTable = nullptr;
821744e589cSAndrew Ng   bool IndicesChanged = false;
82225d7b4fbSAlexey Lapshin 
82325d7b4fbSAlexey Lapshin   using SymPtr = std::unique_ptr<Symbol>;
82425d7b4fbSAlexey Lapshin 
82525d7b4fbSAlexey Lapshin public:
82625d7b4fbSAlexey Lapshin   SymbolTableSection() { Type = OriginalType = ELF::SHT_SYMTAB; }
82725d7b4fbSAlexey Lapshin 
82825d7b4fbSAlexey Lapshin   void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn,
82925d7b4fbSAlexey Lapshin                  uint64_t Value, uint8_t Visibility, uint16_t Shndx,
83025d7b4fbSAlexey Lapshin                  uint64_t SymbolSize);
83125d7b4fbSAlexey Lapshin   void prepareForLayout();
83225d7b4fbSAlexey Lapshin   // An 'empty' symbol table still contains a null symbol.
83325d7b4fbSAlexey Lapshin   bool empty() const { return Symbols.size() == 1; }
834744e589cSAndrew Ng   bool indicesChanged() const { return IndicesChanged; }
83525d7b4fbSAlexey Lapshin   void setShndxTable(SectionIndexSection *ShndxTable) {
83625d7b4fbSAlexey Lapshin     SectionIndexTable = ShndxTable;
83725d7b4fbSAlexey Lapshin   }
83825d7b4fbSAlexey Lapshin   const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }
83925d7b4fbSAlexey Lapshin   void fillShndxTable();
84025d7b4fbSAlexey Lapshin   const SectionBase *getStrTab() const { return SymbolNames; }
84125d7b4fbSAlexey Lapshin   Expected<const Symbol *> getSymbolByIndex(uint32_t Index) const;
84225d7b4fbSAlexey Lapshin   Expected<Symbol *> getSymbolByIndex(uint32_t Index);
84325d7b4fbSAlexey Lapshin   void updateSymbols(function_ref<void(Symbol &)> Callable);
84425d7b4fbSAlexey Lapshin 
84525d7b4fbSAlexey Lapshin   Error removeSectionReferences(
84625d7b4fbSAlexey Lapshin       bool AllowBrokenLinks,
84725d7b4fbSAlexey Lapshin       function_ref<bool(const SectionBase *)> ToRemove) override;
84825d7b4fbSAlexey Lapshin   Error initialize(SectionTableRef SecTable) override;
84925d7b4fbSAlexey Lapshin   void finalize() override;
85025d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Visitor) const override;
85125d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
85225d7b4fbSAlexey Lapshin   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
85325d7b4fbSAlexey Lapshin   void replaceSectionReferences(
85425d7b4fbSAlexey Lapshin       const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
85525d7b4fbSAlexey Lapshin 
85625d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
85725d7b4fbSAlexey Lapshin     return S->OriginalType == ELF::SHT_SYMTAB;
85825d7b4fbSAlexey Lapshin   }
85925d7b4fbSAlexey Lapshin };
86025d7b4fbSAlexey Lapshin 
86125d7b4fbSAlexey Lapshin struct Relocation {
86225d7b4fbSAlexey Lapshin   Symbol *RelocSymbol = nullptr;
86325d7b4fbSAlexey Lapshin   uint64_t Offset;
86425d7b4fbSAlexey Lapshin   uint64_t Addend;
86525d7b4fbSAlexey Lapshin   uint32_t Type;
86625d7b4fbSAlexey Lapshin };
86725d7b4fbSAlexey Lapshin 
86825d7b4fbSAlexey Lapshin // All relocation sections denote relocations to apply to another section.
86925d7b4fbSAlexey Lapshin // However, some relocation sections use a dynamic symbol table and others use
87025d7b4fbSAlexey Lapshin // a regular symbol table. Because the types of the two symbol tables differ in
87125d7b4fbSAlexey Lapshin // our system (because they should behave differently) we can't uniformly
87225d7b4fbSAlexey Lapshin // represent all relocations with the same base class if we expose an interface
87325d7b4fbSAlexey Lapshin // that mentions the symbol table type. So we split the two base types into two
87425d7b4fbSAlexey Lapshin // different classes, one which handles the section the relocation is applied to
87525d7b4fbSAlexey Lapshin // and another which handles the symbol table type. The symbol table type is
87625d7b4fbSAlexey Lapshin // taken as a type parameter to the class (see RelocSectionWithSymtabBase).
87725d7b4fbSAlexey Lapshin class RelocationSectionBase : public SectionBase {
87825d7b4fbSAlexey Lapshin protected:
87925d7b4fbSAlexey Lapshin   SectionBase *SecToApplyRel = nullptr;
88025d7b4fbSAlexey Lapshin 
88125d7b4fbSAlexey Lapshin public:
88225d7b4fbSAlexey Lapshin   const SectionBase *getSection() const { return SecToApplyRel; }
88325d7b4fbSAlexey Lapshin   void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }
88425d7b4fbSAlexey Lapshin 
88525d7b4fbSAlexey Lapshin   StringRef getNamePrefix() const;
88625d7b4fbSAlexey Lapshin 
88725d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
8889bb4cd59SFangrui Song     return is_contained({ELF::SHT_REL, ELF::SHT_RELA, ELF::SHT_CREL},
8899bb4cd59SFangrui Song                         S->OriginalType);
89025d7b4fbSAlexey Lapshin   }
89125d7b4fbSAlexey Lapshin };
89225d7b4fbSAlexey Lapshin 
89325d7b4fbSAlexey Lapshin // Takes the symbol table type to use as a parameter so that we can deduplicate
89425d7b4fbSAlexey Lapshin // that code between the two symbol table types.
89525d7b4fbSAlexey Lapshin template <class SymTabType>
89625d7b4fbSAlexey Lapshin class RelocSectionWithSymtabBase : public RelocationSectionBase {
89725d7b4fbSAlexey Lapshin   void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
89825d7b4fbSAlexey Lapshin 
89925d7b4fbSAlexey Lapshin protected:
90025d7b4fbSAlexey Lapshin   RelocSectionWithSymtabBase() = default;
90125d7b4fbSAlexey Lapshin 
90225d7b4fbSAlexey Lapshin   SymTabType *Symbols = nullptr;
90325d7b4fbSAlexey Lapshin 
90425d7b4fbSAlexey Lapshin public:
90525d7b4fbSAlexey Lapshin   Error initialize(SectionTableRef SecTable) override;
90625d7b4fbSAlexey Lapshin   void finalize() override;
90725d7b4fbSAlexey Lapshin };
90825d7b4fbSAlexey Lapshin 
90925d7b4fbSAlexey Lapshin class RelocationSection
91025d7b4fbSAlexey Lapshin     : public RelocSectionWithSymtabBase<SymbolTableSection> {
91125d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
91225d7b4fbSAlexey Lapshin 
91325d7b4fbSAlexey Lapshin   std::vector<Relocation> Relocations;
91425d7b4fbSAlexey Lapshin   const Object &Obj;
91525d7b4fbSAlexey Lapshin 
91625d7b4fbSAlexey Lapshin public:
91725d7b4fbSAlexey Lapshin   RelocationSection(const Object &O) : Obj(O) {}
91879ce70b8SBraden Helmer   void addRelocation(const Relocation &Rel) { Relocations.push_back(Rel); }
91925d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Visitor) const override;
92025d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
92125d7b4fbSAlexey Lapshin   Error removeSectionReferences(
92225d7b4fbSAlexey Lapshin       bool AllowBrokenLinks,
92325d7b4fbSAlexey Lapshin       function_ref<bool(const SectionBase *)> ToRemove) override;
92425d7b4fbSAlexey Lapshin   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
92525d7b4fbSAlexey Lapshin   void markSymbols() override;
92625d7b4fbSAlexey Lapshin   void replaceSectionReferences(
92725d7b4fbSAlexey Lapshin       const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
92825d7b4fbSAlexey Lapshin   const Object &getObject() const { return Obj; }
92925d7b4fbSAlexey Lapshin 
93025d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
93125d7b4fbSAlexey Lapshin     if (S->OriginalFlags & ELF::SHF_ALLOC)
93225d7b4fbSAlexey Lapshin       return false;
9339bb4cd59SFangrui Song     return RelocationSectionBase::classof(S);
93425d7b4fbSAlexey Lapshin   }
93525d7b4fbSAlexey Lapshin };
93625d7b4fbSAlexey Lapshin 
93725d7b4fbSAlexey Lapshin // TODO: The way stripping and groups interact is complicated
93825d7b4fbSAlexey Lapshin // and still needs to be worked on.
93925d7b4fbSAlexey Lapshin 
94025d7b4fbSAlexey Lapshin class GroupSection : public SectionBase {
94125d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
94225d7b4fbSAlexey Lapshin   const SymbolTableSection *SymTab = nullptr;
94325d7b4fbSAlexey Lapshin   Symbol *Sym = nullptr;
94425d7b4fbSAlexey Lapshin   ELF::Elf32_Word FlagWord;
94525d7b4fbSAlexey Lapshin   SmallVector<SectionBase *, 3> GroupMembers;
94625d7b4fbSAlexey Lapshin 
94725d7b4fbSAlexey Lapshin public:
948e142a556SPranav Kant   template <class T>
949e142a556SPranav Kant   using ConstRange = iterator_range<
950e142a556SPranav Kant       pointee_iterator<typename llvm::SmallVector<T *, 3>::const_iterator>>;
95125d7b4fbSAlexey Lapshin   // TODO: Contents is present in several classes of the hierarchy.
95225d7b4fbSAlexey Lapshin   // This needs to be refactored to avoid duplication.
95325d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> Contents;
95425d7b4fbSAlexey Lapshin 
95525d7b4fbSAlexey Lapshin   explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
95625d7b4fbSAlexey Lapshin 
95725d7b4fbSAlexey Lapshin   void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }
95825d7b4fbSAlexey Lapshin   void setSymbol(Symbol *S) { Sym = S; }
95925d7b4fbSAlexey Lapshin   void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }
96025d7b4fbSAlexey Lapshin   void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }
96125d7b4fbSAlexey Lapshin 
96225d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &) const override;
96325d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
96425d7b4fbSAlexey Lapshin   void finalize() override;
96525d7b4fbSAlexey Lapshin   Error removeSectionReferences(
96625d7b4fbSAlexey Lapshin       bool AllowBrokenLinks,
96725d7b4fbSAlexey Lapshin       function_ref<bool(const SectionBase *)> ToRemove) override;
96825d7b4fbSAlexey Lapshin   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
96925d7b4fbSAlexey Lapshin   void markSymbols() override;
97025d7b4fbSAlexey Lapshin   void replaceSectionReferences(
97125d7b4fbSAlexey Lapshin       const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
97225d7b4fbSAlexey Lapshin   void onRemove() override;
97325d7b4fbSAlexey Lapshin 
974e142a556SPranav Kant   ConstRange<SectionBase> members() const {
975e142a556SPranav Kant     return make_pointee_range(GroupMembers);
976e142a556SPranav Kant   }
977e142a556SPranav Kant 
97825d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
97925d7b4fbSAlexey Lapshin     return S->OriginalType == ELF::SHT_GROUP;
98025d7b4fbSAlexey Lapshin   }
98125d7b4fbSAlexey Lapshin };
98225d7b4fbSAlexey Lapshin 
98325d7b4fbSAlexey Lapshin class DynamicSymbolTableSection : public Section {
98425d7b4fbSAlexey Lapshin public:
98525d7b4fbSAlexey Lapshin   explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}
98625d7b4fbSAlexey Lapshin 
98725d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
98825d7b4fbSAlexey Lapshin     return S->OriginalType == ELF::SHT_DYNSYM;
98925d7b4fbSAlexey Lapshin   }
99025d7b4fbSAlexey Lapshin };
99125d7b4fbSAlexey Lapshin 
99225d7b4fbSAlexey Lapshin class DynamicSection : public Section {
99325d7b4fbSAlexey Lapshin public:
99425d7b4fbSAlexey Lapshin   explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}
99525d7b4fbSAlexey Lapshin 
99625d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
99725d7b4fbSAlexey Lapshin     return S->OriginalType == ELF::SHT_DYNAMIC;
99825d7b4fbSAlexey Lapshin   }
99925d7b4fbSAlexey Lapshin };
100025d7b4fbSAlexey Lapshin 
100125d7b4fbSAlexey Lapshin class DynamicRelocationSection
100225d7b4fbSAlexey Lapshin     : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {
100325d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
100425d7b4fbSAlexey Lapshin 
100525d7b4fbSAlexey Lapshin private:
100625d7b4fbSAlexey Lapshin   ArrayRef<uint8_t> Contents;
100725d7b4fbSAlexey Lapshin 
100825d7b4fbSAlexey Lapshin public:
100925d7b4fbSAlexey Lapshin   explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
101025d7b4fbSAlexey Lapshin 
101125d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &) const override;
101225d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
101325d7b4fbSAlexey Lapshin   Error removeSectionReferences(
101425d7b4fbSAlexey Lapshin       bool AllowBrokenLinks,
101525d7b4fbSAlexey Lapshin       function_ref<bool(const SectionBase *)> ToRemove) override;
101625d7b4fbSAlexey Lapshin 
101725d7b4fbSAlexey Lapshin   static bool classof(const SectionBase *S) {
101825d7b4fbSAlexey Lapshin     if (!(S->OriginalFlags & ELF::SHF_ALLOC))
101925d7b4fbSAlexey Lapshin       return false;
102025d7b4fbSAlexey Lapshin     return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
102125d7b4fbSAlexey Lapshin   }
102225d7b4fbSAlexey Lapshin };
102325d7b4fbSAlexey Lapshin 
102425d7b4fbSAlexey Lapshin class GnuDebugLinkSection : public SectionBase {
102525d7b4fbSAlexey Lapshin   MAKE_SEC_WRITER_FRIEND
102625d7b4fbSAlexey Lapshin 
102725d7b4fbSAlexey Lapshin private:
102825d7b4fbSAlexey Lapshin   StringRef FileName;
102925d7b4fbSAlexey Lapshin   uint32_t CRC32;
103025d7b4fbSAlexey Lapshin 
103125d7b4fbSAlexey Lapshin   void init(StringRef File);
103225d7b4fbSAlexey Lapshin 
103325d7b4fbSAlexey Lapshin public:
103425d7b4fbSAlexey Lapshin   // If we add this section from an external source we can use this ctor.
103525d7b4fbSAlexey Lapshin   explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC);
103625d7b4fbSAlexey Lapshin   Error accept(SectionVisitor &Visitor) const override;
103725d7b4fbSAlexey Lapshin   Error accept(MutableSectionVisitor &Visitor) override;
103825d7b4fbSAlexey Lapshin };
103925d7b4fbSAlexey Lapshin 
104025d7b4fbSAlexey Lapshin class Reader {
104125d7b4fbSAlexey Lapshin public:
104225d7b4fbSAlexey Lapshin   virtual ~Reader();
104325d7b4fbSAlexey Lapshin   virtual Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const = 0;
104425d7b4fbSAlexey Lapshin };
104525d7b4fbSAlexey Lapshin 
104625d7b4fbSAlexey Lapshin using object::Binary;
104725d7b4fbSAlexey Lapshin using object::ELFFile;
104825d7b4fbSAlexey Lapshin using object::ELFObjectFile;
104925d7b4fbSAlexey Lapshin using object::OwningBinary;
105025d7b4fbSAlexey Lapshin 
105125d7b4fbSAlexey Lapshin class BasicELFBuilder {
105225d7b4fbSAlexey Lapshin protected:
105325d7b4fbSAlexey Lapshin   std::unique_ptr<Object> Obj;
105425d7b4fbSAlexey Lapshin 
105525d7b4fbSAlexey Lapshin   void initFileHeader();
105625d7b4fbSAlexey Lapshin   void initHeaderSegment();
105725d7b4fbSAlexey Lapshin   StringTableSection *addStrTab();
105825d7b4fbSAlexey Lapshin   SymbolTableSection *addSymTab(StringTableSection *StrTab);
105925d7b4fbSAlexey Lapshin   Error initSections();
106025d7b4fbSAlexey Lapshin 
106125d7b4fbSAlexey Lapshin public:
106225d7b4fbSAlexey Lapshin   BasicELFBuilder() : Obj(std::make_unique<Object>()) {}
106325d7b4fbSAlexey Lapshin };
106425d7b4fbSAlexey Lapshin 
106525d7b4fbSAlexey Lapshin class BinaryELFBuilder : public BasicELFBuilder {
106625d7b4fbSAlexey Lapshin   MemoryBuffer *MemBuf;
106725d7b4fbSAlexey Lapshin   uint8_t NewSymbolVisibility;
106825d7b4fbSAlexey Lapshin   void addData(SymbolTableSection *SymTab);
106925d7b4fbSAlexey Lapshin 
107025d7b4fbSAlexey Lapshin public:
107125d7b4fbSAlexey Lapshin   BinaryELFBuilder(MemoryBuffer *MB, uint8_t NewSymbolVisibility)
107225d7b4fbSAlexey Lapshin       : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
107325d7b4fbSAlexey Lapshin 
107425d7b4fbSAlexey Lapshin   Expected<std::unique_ptr<Object>> build();
107525d7b4fbSAlexey Lapshin };
107625d7b4fbSAlexey Lapshin 
107725d7b4fbSAlexey Lapshin class IHexELFBuilder : public BasicELFBuilder {
107825d7b4fbSAlexey Lapshin   const std::vector<IHexRecord> &Records;
107925d7b4fbSAlexey Lapshin 
108025d7b4fbSAlexey Lapshin   void addDataSections();
108125d7b4fbSAlexey Lapshin 
108225d7b4fbSAlexey Lapshin public:
108325d7b4fbSAlexey Lapshin   IHexELFBuilder(const std::vector<IHexRecord> &Records) : Records(Records) {}
108425d7b4fbSAlexey Lapshin 
108525d7b4fbSAlexey Lapshin   Expected<std::unique_ptr<Object>> build();
108625d7b4fbSAlexey Lapshin };
108725d7b4fbSAlexey Lapshin 
108825d7b4fbSAlexey Lapshin template <class ELFT> class ELFBuilder {
108925d7b4fbSAlexey Lapshin private:
109025d7b4fbSAlexey Lapshin   using Elf_Addr = typename ELFT::Addr;
109125d7b4fbSAlexey Lapshin   using Elf_Shdr = typename ELFT::Shdr;
109225d7b4fbSAlexey Lapshin   using Elf_Word = typename ELFT::Word;
109325d7b4fbSAlexey Lapshin 
109425d7b4fbSAlexey Lapshin   const ELFFile<ELFT> &ElfFile;
109525d7b4fbSAlexey Lapshin   Object &Obj;
109625d7b4fbSAlexey Lapshin   size_t EhdrOffset = 0;
1097ec941432SFangrui Song   std::optional<StringRef> ExtractPartition;
109825d7b4fbSAlexey Lapshin 
109925d7b4fbSAlexey Lapshin   void setParentSegment(Segment &Child);
110025d7b4fbSAlexey Lapshin   Error readProgramHeaders(const ELFFile<ELFT> &HeadersFile);
110125d7b4fbSAlexey Lapshin   Error initGroupSection(GroupSection *GroupSec);
110225d7b4fbSAlexey Lapshin   Error initSymbolTable(SymbolTableSection *SymTab);
110325d7b4fbSAlexey Lapshin   Error readSectionHeaders();
110425d7b4fbSAlexey Lapshin   Error readSections(bool EnsureSymtab);
110525d7b4fbSAlexey Lapshin   Error findEhdrOffset();
110625d7b4fbSAlexey Lapshin   Expected<SectionBase &> makeSection(const Elf_Shdr &Shdr);
110725d7b4fbSAlexey Lapshin 
110825d7b4fbSAlexey Lapshin public:
110925d7b4fbSAlexey Lapshin   ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
1110ec941432SFangrui Song              std::optional<StringRef> ExtractPartition);
111125d7b4fbSAlexey Lapshin 
111225d7b4fbSAlexey Lapshin   Error build(bool EnsureSymtab);
111325d7b4fbSAlexey Lapshin };
111425d7b4fbSAlexey Lapshin 
111525d7b4fbSAlexey Lapshin class BinaryReader : public Reader {
111625d7b4fbSAlexey Lapshin   MemoryBuffer *MemBuf;
111725d7b4fbSAlexey Lapshin   uint8_t NewSymbolVisibility;
111825d7b4fbSAlexey Lapshin 
111925d7b4fbSAlexey Lapshin public:
112025d7b4fbSAlexey Lapshin   BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility)
112125d7b4fbSAlexey Lapshin       : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
112225d7b4fbSAlexey Lapshin   Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
112325d7b4fbSAlexey Lapshin };
112425d7b4fbSAlexey Lapshin 
112525d7b4fbSAlexey Lapshin class IHexReader : public Reader {
112625d7b4fbSAlexey Lapshin   MemoryBuffer *MemBuf;
112725d7b4fbSAlexey Lapshin 
112825d7b4fbSAlexey Lapshin   Expected<std::vector<IHexRecord>> parse() const;
112925d7b4fbSAlexey Lapshin   Error parseError(size_t LineNo, Error E) const {
113025d7b4fbSAlexey Lapshin     return LineNo == -1U
113125d7b4fbSAlexey Lapshin                ? createFileError(MemBuf->getBufferIdentifier(), std::move(E))
113225d7b4fbSAlexey Lapshin                : createFileError(MemBuf->getBufferIdentifier(), LineNo,
113325d7b4fbSAlexey Lapshin                                  std::move(E));
113425d7b4fbSAlexey Lapshin   }
113525d7b4fbSAlexey Lapshin   template <typename... Ts>
113625d7b4fbSAlexey Lapshin   Error parseError(size_t LineNo, char const *Fmt, const Ts &...Vals) const {
113725d7b4fbSAlexey Lapshin     Error E = createStringError(errc::invalid_argument, Fmt, Vals...);
113825d7b4fbSAlexey Lapshin     return parseError(LineNo, std::move(E));
113925d7b4fbSAlexey Lapshin   }
114025d7b4fbSAlexey Lapshin 
114125d7b4fbSAlexey Lapshin public:
114225d7b4fbSAlexey Lapshin   IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}
114325d7b4fbSAlexey Lapshin 
114425d7b4fbSAlexey Lapshin   Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
114525d7b4fbSAlexey Lapshin };
114625d7b4fbSAlexey Lapshin 
114725d7b4fbSAlexey Lapshin class ELFReader : public Reader {
114825d7b4fbSAlexey Lapshin   Binary *Bin;
1149ec941432SFangrui Song   std::optional<StringRef> ExtractPartition;
115025d7b4fbSAlexey Lapshin 
115125d7b4fbSAlexey Lapshin public:
115225d7b4fbSAlexey Lapshin   Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
1153ec941432SFangrui Song   explicit ELFReader(Binary *B, std::optional<StringRef> ExtractPartition)
115425d7b4fbSAlexey Lapshin       : Bin(B), ExtractPartition(ExtractPartition) {}
115525d7b4fbSAlexey Lapshin };
115625d7b4fbSAlexey Lapshin 
115725d7b4fbSAlexey Lapshin class Object {
115825d7b4fbSAlexey Lapshin private:
115925d7b4fbSAlexey Lapshin   using SecPtr = std::unique_ptr<SectionBase>;
116025d7b4fbSAlexey Lapshin   using SegPtr = std::unique_ptr<Segment>;
116125d7b4fbSAlexey Lapshin 
116225d7b4fbSAlexey Lapshin   std::vector<SecPtr> Sections;
116325d7b4fbSAlexey Lapshin   std::vector<SegPtr> Segments;
116425d7b4fbSAlexey Lapshin   std::vector<SecPtr> RemovedSections;
116525d7b4fbSAlexey Lapshin   DenseMap<SectionBase *, std::vector<uint8_t>> UpdatedSections;
116625d7b4fbSAlexey Lapshin 
116725d7b4fbSAlexey Lapshin   static bool sectionIsAlloc(const SectionBase &Sec) {
116825d7b4fbSAlexey Lapshin     return Sec.Flags & ELF::SHF_ALLOC;
116925d7b4fbSAlexey Lapshin   };
117025d7b4fbSAlexey Lapshin 
1171*10772807SIgor Kudrin   Error updateSectionData(SecPtr &Sec, ArrayRef<uint8_t> Data);
1172*10772807SIgor Kudrin 
117325d7b4fbSAlexey Lapshin public:
117425d7b4fbSAlexey Lapshin   template <class T>
117525d7b4fbSAlexey Lapshin   using ConstRange = iterator_range<pointee_iterator<
117625d7b4fbSAlexey Lapshin       typename std::vector<std::unique_ptr<T>>::const_iterator>>;
117725d7b4fbSAlexey Lapshin 
117825d7b4fbSAlexey Lapshin   // It is often the case that the ELF header and the program header table are
117925d7b4fbSAlexey Lapshin   // not present in any segment. This could be a problem during file layout,
118025d7b4fbSAlexey Lapshin   // because other segments may get assigned an offset where either of the
118125d7b4fbSAlexey Lapshin   // two should reside, which will effectively corrupt the resulting binary.
118225d7b4fbSAlexey Lapshin   // Other than that we use these segments to track program header offsets
118325d7b4fbSAlexey Lapshin   // when they may not follow the ELF header.
118425d7b4fbSAlexey Lapshin   Segment ElfHdrSegment;
118525d7b4fbSAlexey Lapshin   Segment ProgramHdrSegment;
118625d7b4fbSAlexey Lapshin 
1187c997fe65SFangrui Song   bool Is64Bits;
118825d7b4fbSAlexey Lapshin   uint8_t OSABI;
118925d7b4fbSAlexey Lapshin   uint8_t ABIVersion;
119025d7b4fbSAlexey Lapshin   uint64_t Entry;
119125d7b4fbSAlexey Lapshin   uint64_t SHOff;
119225d7b4fbSAlexey Lapshin   uint32_t Type;
119325d7b4fbSAlexey Lapshin   uint32_t Machine;
119425d7b4fbSAlexey Lapshin   uint32_t Version;
119525d7b4fbSAlexey Lapshin   uint32_t Flags;
119625d7b4fbSAlexey Lapshin 
119725d7b4fbSAlexey Lapshin   bool HadShdrs = true;
119825d7b4fbSAlexey Lapshin   bool MustBeRelocatable = false;
119925d7b4fbSAlexey Lapshin   StringTableSection *SectionNames = nullptr;
120025d7b4fbSAlexey Lapshin   SymbolTableSection *SymbolTable = nullptr;
120125d7b4fbSAlexey Lapshin   SectionIndexSection *SectionIndexTable = nullptr;
120225d7b4fbSAlexey Lapshin 
120325d7b4fbSAlexey Lapshin   bool IsMips64EL = false;
120425d7b4fbSAlexey Lapshin 
120525d7b4fbSAlexey Lapshin   SectionTableRef sections() const { return SectionTableRef(Sections); }
120625d7b4fbSAlexey Lapshin   iterator_range<
120725d7b4fbSAlexey Lapshin       filter_iterator<pointee_iterator<std::vector<SecPtr>::const_iterator>,
120825d7b4fbSAlexey Lapshin                       decltype(&sectionIsAlloc)>>
120925d7b4fbSAlexey Lapshin   allocSections() const {
121025d7b4fbSAlexey Lapshin     return make_filter_range(make_pointee_range(Sections), sectionIsAlloc);
121125d7b4fbSAlexey Lapshin   }
121225d7b4fbSAlexey Lapshin 
121325d7b4fbSAlexey Lapshin   const auto &getUpdatedSections() const { return UpdatedSections; }
121425d7b4fbSAlexey Lapshin   Error updateSection(StringRef Name, ArrayRef<uint8_t> Data);
1215*10772807SIgor Kudrin   Error updateSectionData(SectionBase &S, ArrayRef<uint8_t> Data);
121625d7b4fbSAlexey Lapshin 
121725d7b4fbSAlexey Lapshin   SectionBase *findSection(StringRef Name) {
121825d7b4fbSAlexey Lapshin     auto SecIt =
121925d7b4fbSAlexey Lapshin         find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });
122025d7b4fbSAlexey Lapshin     return SecIt == Sections.end() ? nullptr : SecIt->get();
122125d7b4fbSAlexey Lapshin   }
122225d7b4fbSAlexey Lapshin   SectionTableRef removedSections() { return SectionTableRef(RemovedSections); }
122325d7b4fbSAlexey Lapshin 
122425d7b4fbSAlexey Lapshin   ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
122525d7b4fbSAlexey Lapshin 
122625d7b4fbSAlexey Lapshin   Error removeSections(bool AllowBrokenLinks,
122725d7b4fbSAlexey Lapshin                        std::function<bool(const SectionBase &)> ToRemove);
1228122d368bSFangrui Song   Error compressOrDecompressSections(const CommonConfig &Config);
122925d7b4fbSAlexey Lapshin   Error replaceSections(const DenseMap<SectionBase *, SectionBase *> &FromTo);
123025d7b4fbSAlexey Lapshin   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
123125d7b4fbSAlexey Lapshin   template <class T, class... Ts> T &addSection(Ts &&...Args) {
123225d7b4fbSAlexey Lapshin     auto Sec = std::make_unique<T>(std::forward<Ts>(Args)...);
123325d7b4fbSAlexey Lapshin     auto Ptr = Sec.get();
123425d7b4fbSAlexey Lapshin     MustBeRelocatable |= isa<RelocationSection>(*Ptr);
123525d7b4fbSAlexey Lapshin     Sections.emplace_back(std::move(Sec));
123625d7b4fbSAlexey Lapshin     Ptr->Index = Sections.size();
123725d7b4fbSAlexey Lapshin     return *Ptr;
123825d7b4fbSAlexey Lapshin   }
123925d7b4fbSAlexey Lapshin   Error addNewSymbolTable();
124025d7b4fbSAlexey Lapshin   Segment &addSegment(ArrayRef<uint8_t> Data) {
124125d7b4fbSAlexey Lapshin     Segments.emplace_back(std::make_unique<Segment>(Data));
124225d7b4fbSAlexey Lapshin     return *Segments.back();
124325d7b4fbSAlexey Lapshin   }
124425d7b4fbSAlexey Lapshin   bool isRelocatable() const {
124525d7b4fbSAlexey Lapshin     return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;
124625d7b4fbSAlexey Lapshin   }
124725d7b4fbSAlexey Lapshin };
124825d7b4fbSAlexey Lapshin 
124925d7b4fbSAlexey Lapshin } // end namespace elf
125025d7b4fbSAlexey Lapshin } // end namespace objcopy
125125d7b4fbSAlexey Lapshin } // end namespace llvm
125225d7b4fbSAlexey Lapshin 
125325d7b4fbSAlexey Lapshin #endif // LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H
1254