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(§ionIsAlloc)>> 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