xref: /freebsd-src/contrib/llvm-project/llvm/lib/ObjCopy/ELF/ELFObject.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===- ELFObject.h ----------------------------------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #ifndef LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H
1081ad6265SDimitry Andric #define LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H
1181ad6265SDimitry Andric 
1281ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1381ad6265SDimitry Andric #include "llvm/ADT/StringRef.h"
1481ad6265SDimitry Andric #include "llvm/ADT/Twine.h"
1581ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
1681ad6265SDimitry Andric #include "llvm/MC/StringTableBuilder.h"
1781ad6265SDimitry Andric #include "llvm/ObjCopy/CommonConfig.h"
1881ad6265SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
1981ad6265SDimitry Andric #include "llvm/Support/Errc.h"
2081ad6265SDimitry Andric #include "llvm/Support/FileOutputBuffer.h"
2181ad6265SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
2281ad6265SDimitry Andric #include <cstddef>
2381ad6265SDimitry Andric #include <cstdint>
2481ad6265SDimitry Andric #include <functional>
2581ad6265SDimitry Andric #include <memory>
2681ad6265SDimitry Andric #include <set>
2781ad6265SDimitry Andric #include <vector>
2881ad6265SDimitry Andric 
2981ad6265SDimitry Andric namespace llvm {
3081ad6265SDimitry Andric enum class DebugCompressionType;
3181ad6265SDimitry Andric namespace objcopy {
3281ad6265SDimitry Andric namespace elf {
3381ad6265SDimitry Andric 
3481ad6265SDimitry Andric class SectionBase;
3581ad6265SDimitry Andric class Section;
3681ad6265SDimitry Andric class OwnedDataSection;
3781ad6265SDimitry Andric class StringTableSection;
3881ad6265SDimitry Andric class SymbolTableSection;
3981ad6265SDimitry Andric class RelocationSection;
4081ad6265SDimitry Andric class DynamicRelocationSection;
4181ad6265SDimitry Andric class GnuDebugLinkSection;
4281ad6265SDimitry Andric class GroupSection;
4381ad6265SDimitry Andric class SectionIndexSection;
4481ad6265SDimitry Andric class CompressedSection;
4581ad6265SDimitry Andric class DecompressedSection;
4681ad6265SDimitry Andric class Segment;
4781ad6265SDimitry Andric class Object;
4881ad6265SDimitry Andric struct Symbol;
4981ad6265SDimitry Andric 
5081ad6265SDimitry Andric class SectionTableRef {
5181ad6265SDimitry Andric   ArrayRef<std::unique_ptr<SectionBase>> Sections;
5281ad6265SDimitry Andric 
5381ad6265SDimitry Andric public:
5481ad6265SDimitry Andric   using iterator = pointee_iterator<const std::unique_ptr<SectionBase> *>;
5581ad6265SDimitry Andric 
5681ad6265SDimitry Andric   explicit SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs)
5781ad6265SDimitry Andric       : Sections(Secs) {}
5881ad6265SDimitry Andric   SectionTableRef(const SectionTableRef &) = default;
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric   iterator begin() const { return iterator(Sections.data()); }
6181ad6265SDimitry Andric   iterator end() const { return iterator(Sections.data() + Sections.size()); }
6281ad6265SDimitry Andric   size_t size() const { return Sections.size(); }
6381ad6265SDimitry Andric 
6481ad6265SDimitry Andric   Expected<SectionBase *> getSection(uint32_t Index, Twine ErrMsg);
6581ad6265SDimitry Andric 
6681ad6265SDimitry Andric   template <class T>
6781ad6265SDimitry Andric   Expected<T *> getSectionOfType(uint32_t Index, Twine IndexErrMsg,
6881ad6265SDimitry Andric                                  Twine TypeErrMsg);
6981ad6265SDimitry Andric };
7081ad6265SDimitry Andric 
7181ad6265SDimitry Andric enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };
7281ad6265SDimitry Andric 
7381ad6265SDimitry Andric class SectionVisitor {
7481ad6265SDimitry Andric public:
7581ad6265SDimitry Andric   virtual ~SectionVisitor() = default;
7681ad6265SDimitry Andric 
7781ad6265SDimitry Andric   virtual Error visit(const Section &Sec) = 0;
7881ad6265SDimitry Andric   virtual Error visit(const OwnedDataSection &Sec) = 0;
7981ad6265SDimitry Andric   virtual Error visit(const StringTableSection &Sec) = 0;
8081ad6265SDimitry Andric   virtual Error visit(const SymbolTableSection &Sec) = 0;
8181ad6265SDimitry Andric   virtual Error visit(const RelocationSection &Sec) = 0;
8281ad6265SDimitry Andric   virtual Error visit(const DynamicRelocationSection &Sec) = 0;
8381ad6265SDimitry Andric   virtual Error visit(const GnuDebugLinkSection &Sec) = 0;
8481ad6265SDimitry Andric   virtual Error visit(const GroupSection &Sec) = 0;
8581ad6265SDimitry Andric   virtual Error visit(const SectionIndexSection &Sec) = 0;
8681ad6265SDimitry Andric   virtual Error visit(const CompressedSection &Sec) = 0;
8781ad6265SDimitry Andric   virtual Error visit(const DecompressedSection &Sec) = 0;
8881ad6265SDimitry Andric };
8981ad6265SDimitry Andric 
9081ad6265SDimitry Andric class MutableSectionVisitor {
9181ad6265SDimitry Andric public:
9281ad6265SDimitry Andric   virtual ~MutableSectionVisitor() = default;
9381ad6265SDimitry Andric 
9481ad6265SDimitry Andric   virtual Error visit(Section &Sec) = 0;
9581ad6265SDimitry Andric   virtual Error visit(OwnedDataSection &Sec) = 0;
9681ad6265SDimitry Andric   virtual Error visit(StringTableSection &Sec) = 0;
9781ad6265SDimitry Andric   virtual Error visit(SymbolTableSection &Sec) = 0;
9881ad6265SDimitry Andric   virtual Error visit(RelocationSection &Sec) = 0;
9981ad6265SDimitry Andric   virtual Error visit(DynamicRelocationSection &Sec) = 0;
10081ad6265SDimitry Andric   virtual Error visit(GnuDebugLinkSection &Sec) = 0;
10181ad6265SDimitry Andric   virtual Error visit(GroupSection &Sec) = 0;
10281ad6265SDimitry Andric   virtual Error visit(SectionIndexSection &Sec) = 0;
10381ad6265SDimitry Andric   virtual Error visit(CompressedSection &Sec) = 0;
10481ad6265SDimitry Andric   virtual Error visit(DecompressedSection &Sec) = 0;
10581ad6265SDimitry Andric };
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric class SectionWriter : public SectionVisitor {
10881ad6265SDimitry Andric protected:
10981ad6265SDimitry Andric   WritableMemoryBuffer &Out;
11081ad6265SDimitry Andric 
11181ad6265SDimitry Andric public:
11281ad6265SDimitry Andric   virtual ~SectionWriter() = default;
11381ad6265SDimitry Andric 
11481ad6265SDimitry Andric   Error visit(const Section &Sec) override;
11581ad6265SDimitry Andric   Error visit(const OwnedDataSection &Sec) override;
11681ad6265SDimitry Andric   Error visit(const StringTableSection &Sec) override;
11781ad6265SDimitry Andric   Error visit(const DynamicRelocationSection &Sec) override;
118972a253aSDimitry Andric   Error visit(const SymbolTableSection &Sec) override = 0;
119972a253aSDimitry Andric   Error visit(const RelocationSection &Sec) override = 0;
120972a253aSDimitry Andric   Error visit(const GnuDebugLinkSection &Sec) override = 0;
121972a253aSDimitry Andric   Error visit(const GroupSection &Sec) override = 0;
122972a253aSDimitry Andric   Error visit(const SectionIndexSection &Sec) override = 0;
123972a253aSDimitry Andric   Error visit(const CompressedSection &Sec) override = 0;
124972a253aSDimitry Andric   Error visit(const DecompressedSection &Sec) override = 0;
12581ad6265SDimitry Andric 
12681ad6265SDimitry Andric   explicit SectionWriter(WritableMemoryBuffer &Buf) : Out(Buf) {}
12781ad6265SDimitry Andric };
12881ad6265SDimitry Andric 
12981ad6265SDimitry Andric template <class ELFT> class ELFSectionWriter : public SectionWriter {
13081ad6265SDimitry Andric private:
13181ad6265SDimitry Andric   using Elf_Word = typename ELFT::Word;
13281ad6265SDimitry Andric   using Elf_Rel = typename ELFT::Rel;
13381ad6265SDimitry Andric   using Elf_Rela = typename ELFT::Rela;
13481ad6265SDimitry Andric   using Elf_Sym = typename ELFT::Sym;
13581ad6265SDimitry Andric 
13681ad6265SDimitry Andric public:
13781ad6265SDimitry Andric   virtual ~ELFSectionWriter() {}
13881ad6265SDimitry Andric   Error visit(const SymbolTableSection &Sec) override;
13981ad6265SDimitry Andric   Error visit(const RelocationSection &Sec) override;
14081ad6265SDimitry Andric   Error visit(const GnuDebugLinkSection &Sec) override;
14181ad6265SDimitry Andric   Error visit(const GroupSection &Sec) override;
14281ad6265SDimitry Andric   Error visit(const SectionIndexSection &Sec) override;
14381ad6265SDimitry Andric   Error visit(const CompressedSection &Sec) override;
14481ad6265SDimitry Andric   Error visit(const DecompressedSection &Sec) override;
14581ad6265SDimitry Andric 
14681ad6265SDimitry Andric   explicit ELFSectionWriter(WritableMemoryBuffer &Buf) : SectionWriter(Buf) {}
14781ad6265SDimitry Andric };
14881ad6265SDimitry Andric 
14981ad6265SDimitry Andric template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {
15081ad6265SDimitry Andric private:
15181ad6265SDimitry Andric   using Elf_Rel = typename ELFT::Rel;
15281ad6265SDimitry Andric   using Elf_Rela = typename ELFT::Rela;
15381ad6265SDimitry Andric   using Elf_Sym = typename ELFT::Sym;
15481ad6265SDimitry Andric   using Elf_Word = typename ELFT::Word;
15581ad6265SDimitry Andric   using Elf_Xword = typename ELFT::Xword;
15681ad6265SDimitry Andric 
15781ad6265SDimitry Andric public:
15881ad6265SDimitry Andric   Error visit(Section &Sec) override;
15981ad6265SDimitry Andric   Error visit(OwnedDataSection &Sec) override;
16081ad6265SDimitry Andric   Error visit(StringTableSection &Sec) override;
16181ad6265SDimitry Andric   Error visit(DynamicRelocationSection &Sec) override;
16281ad6265SDimitry Andric   Error visit(SymbolTableSection &Sec) override;
16381ad6265SDimitry Andric   Error visit(RelocationSection &Sec) override;
16481ad6265SDimitry Andric   Error visit(GnuDebugLinkSection &Sec) override;
16581ad6265SDimitry Andric   Error visit(GroupSection &Sec) override;
16681ad6265SDimitry Andric   Error visit(SectionIndexSection &Sec) override;
16781ad6265SDimitry Andric   Error visit(CompressedSection &Sec) override;
16881ad6265SDimitry Andric   Error visit(DecompressedSection &Sec) override;
16981ad6265SDimitry Andric };
17081ad6265SDimitry Andric 
17181ad6265SDimitry Andric #define MAKE_SEC_WRITER_FRIEND                                                 \
17281ad6265SDimitry Andric   friend class SectionWriter;                                                  \
17381ad6265SDimitry Andric   friend class IHexSectionWriterBase;                                          \
17481ad6265SDimitry Andric   friend class IHexSectionWriter;                                              \
175*0fca6ea1SDimitry Andric   friend class SRECSectionWriter;                                              \
176*0fca6ea1SDimitry Andric   friend class SRECSectionWriterBase;                                          \
177*0fca6ea1SDimitry Andric   friend class SRECSizeCalculator;                                             \
17881ad6265SDimitry Andric   template <class ELFT> friend class ELFSectionWriter;                         \
17981ad6265SDimitry Andric   template <class ELFT> friend class ELFSectionSizer;
18081ad6265SDimitry Andric 
18181ad6265SDimitry Andric class BinarySectionWriter : public SectionWriter {
18281ad6265SDimitry Andric public:
18381ad6265SDimitry Andric   virtual ~BinarySectionWriter() {}
18481ad6265SDimitry Andric 
18581ad6265SDimitry Andric   Error visit(const SymbolTableSection &Sec) override;
18681ad6265SDimitry Andric   Error visit(const RelocationSection &Sec) override;
18781ad6265SDimitry Andric   Error visit(const GnuDebugLinkSection &Sec) override;
18881ad6265SDimitry Andric   Error visit(const GroupSection &Sec) override;
18981ad6265SDimitry Andric   Error visit(const SectionIndexSection &Sec) override;
19081ad6265SDimitry Andric   Error visit(const CompressedSection &Sec) override;
19181ad6265SDimitry Andric   Error visit(const DecompressedSection &Sec) override;
19281ad6265SDimitry Andric 
19381ad6265SDimitry Andric   explicit BinarySectionWriter(WritableMemoryBuffer &Buf)
19481ad6265SDimitry Andric       : SectionWriter(Buf) {}
19581ad6265SDimitry Andric };
19681ad6265SDimitry Andric 
19781ad6265SDimitry Andric using IHexLineData = SmallVector<char, 64>;
19881ad6265SDimitry Andric 
19981ad6265SDimitry Andric struct IHexRecord {
20081ad6265SDimitry Andric   // Memory address of the record.
20181ad6265SDimitry Andric   uint16_t Addr;
20281ad6265SDimitry Andric   // Record type (see below).
20381ad6265SDimitry Andric   uint16_t Type;
20481ad6265SDimitry Andric   // Record data in hexadecimal form.
20581ad6265SDimitry Andric   StringRef HexData;
20681ad6265SDimitry Andric 
20781ad6265SDimitry Andric   // Helper method to get file length of the record
20881ad6265SDimitry Andric   // including newline character
20981ad6265SDimitry Andric   static size_t getLength(size_t DataSize) {
21081ad6265SDimitry Andric     // :LLAAAATT[DD...DD]CC'
21181ad6265SDimitry Andric     return DataSize * 2 + 11;
21281ad6265SDimitry Andric   }
21381ad6265SDimitry Andric 
21481ad6265SDimitry Andric   // Gets length of line in a file (getLength + CRLF).
21581ad6265SDimitry Andric   static size_t getLineLength(size_t DataSize) {
21681ad6265SDimitry Andric     return getLength(DataSize) + 2;
21781ad6265SDimitry Andric   }
21881ad6265SDimitry Andric 
21981ad6265SDimitry Andric   // Given type, address and data returns line which can
22081ad6265SDimitry Andric   // be written to output file.
22181ad6265SDimitry Andric   static IHexLineData getLine(uint8_t Type, uint16_t Addr,
22281ad6265SDimitry Andric                               ArrayRef<uint8_t> Data);
22381ad6265SDimitry Andric 
22481ad6265SDimitry Andric   // Parses the line and returns record if possible.
22581ad6265SDimitry Andric   // Line should be trimmed from whitespace characters.
22681ad6265SDimitry Andric   static Expected<IHexRecord> parse(StringRef Line);
22781ad6265SDimitry Andric 
22881ad6265SDimitry Andric   // Calculates checksum of stringified record representation
22981ad6265SDimitry Andric   // S must NOT contain leading ':' and trailing whitespace
23081ad6265SDimitry Andric   // characters
23181ad6265SDimitry Andric   static uint8_t getChecksum(StringRef S);
23281ad6265SDimitry Andric 
23381ad6265SDimitry Andric   enum Type {
23481ad6265SDimitry Andric     // Contains data and a 16-bit starting address for the data.
23581ad6265SDimitry Andric     // The byte count specifies number of data bytes in the record.
23681ad6265SDimitry Andric     Data = 0,
23781ad6265SDimitry Andric     // Must occur exactly once per file in the last line of the file.
23881ad6265SDimitry Andric     // The data field is empty (thus byte count is 00) and the address
23981ad6265SDimitry Andric     // field is typically 0000.
24081ad6265SDimitry Andric     EndOfFile = 1,
24181ad6265SDimitry Andric     // The data field contains a 16-bit segment base address (thus byte
24281ad6265SDimitry Andric     // count is always 02) compatible with 80x86 real mode addressing.
24381ad6265SDimitry Andric     // The address field (typically 0000) is ignored. The segment address
24481ad6265SDimitry Andric     // from the most recent 02 record is multiplied by 16 and added to each
24581ad6265SDimitry Andric     // subsequent data record address to form the physical starting address
24681ad6265SDimitry Andric     // for the data. This allows addressing up to one megabyte of address
24781ad6265SDimitry Andric     // space.
24881ad6265SDimitry Andric     SegmentAddr = 2,
24981ad6265SDimitry Andric     // or 80x86 processors, specifies the initial content of the CS:IP
25081ad6265SDimitry Andric     // registers. The address field is 0000, the byte count is always 04,
25181ad6265SDimitry Andric     // the first two data bytes are the CS value, the latter two are the
25281ad6265SDimitry Andric     // IP value.
25381ad6265SDimitry Andric     StartAddr80x86 = 3,
25481ad6265SDimitry Andric     // Allows for 32 bit addressing (up to 4GiB). The record's address field
25581ad6265SDimitry Andric     // is ignored (typically 0000) and its byte count is always 02. The two
25681ad6265SDimitry Andric     // data bytes (big endian) specify the upper 16 bits of the 32 bit
25781ad6265SDimitry Andric     // absolute address for all subsequent type 00 records
25881ad6265SDimitry Andric     ExtendedAddr = 4,
25981ad6265SDimitry Andric     // The address field is 0000 (not used) and the byte count is always 04.
26081ad6265SDimitry Andric     // The four data bytes represent a 32-bit address value. In the case of
26181ad6265SDimitry Andric     // 80386 and higher CPUs, this address is loaded into the EIP register.
26281ad6265SDimitry Andric     StartAddr = 5,
26381ad6265SDimitry Andric     // We have no other valid types
26481ad6265SDimitry Andric     InvalidType = 6
26581ad6265SDimitry Andric   };
26681ad6265SDimitry Andric };
26781ad6265SDimitry Andric 
26881ad6265SDimitry Andric // Base class for IHexSectionWriter. This class implements writing algorithm,
26981ad6265SDimitry Andric // but doesn't actually write records. It is used for output buffer size
27081ad6265SDimitry Andric // calculation in IHexWriter::finalize.
27181ad6265SDimitry Andric class IHexSectionWriterBase : public BinarySectionWriter {
27281ad6265SDimitry Andric   // 20-bit segment address
27381ad6265SDimitry Andric   uint32_t SegmentAddr = 0;
27481ad6265SDimitry Andric   // Extended linear address
27581ad6265SDimitry Andric   uint32_t BaseAddr = 0;
27681ad6265SDimitry Andric 
27781ad6265SDimitry Andric   // Write segment address corresponding to 'Addr'
27881ad6265SDimitry Andric   uint64_t writeSegmentAddr(uint64_t Addr);
27981ad6265SDimitry Andric   // Write extended linear (base) address corresponding to 'Addr'
28081ad6265SDimitry Andric   uint64_t writeBaseAddr(uint64_t Addr);
28181ad6265SDimitry Andric 
28281ad6265SDimitry Andric protected:
28381ad6265SDimitry Andric   // Offset in the output buffer
28481ad6265SDimitry Andric   uint64_t Offset = 0;
28581ad6265SDimitry Andric 
28681ad6265SDimitry Andric   void writeSection(const SectionBase *Sec, ArrayRef<uint8_t> Data);
28781ad6265SDimitry Andric   virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);
28881ad6265SDimitry Andric 
28981ad6265SDimitry Andric public:
29081ad6265SDimitry Andric   explicit IHexSectionWriterBase(WritableMemoryBuffer &Buf)
29181ad6265SDimitry Andric       : BinarySectionWriter(Buf) {}
29281ad6265SDimitry Andric 
29381ad6265SDimitry Andric   uint64_t getBufferOffset() const { return Offset; }
29481ad6265SDimitry Andric   Error visit(const Section &Sec) final;
29581ad6265SDimitry Andric   Error visit(const OwnedDataSection &Sec) final;
29681ad6265SDimitry Andric   Error visit(const StringTableSection &Sec) override;
29781ad6265SDimitry Andric   Error visit(const DynamicRelocationSection &Sec) final;
29881ad6265SDimitry Andric   using BinarySectionWriter::visit;
29981ad6265SDimitry Andric };
30081ad6265SDimitry Andric 
30181ad6265SDimitry Andric // Real IHEX section writer
30281ad6265SDimitry Andric class IHexSectionWriter : public IHexSectionWriterBase {
30381ad6265SDimitry Andric public:
30481ad6265SDimitry Andric   IHexSectionWriter(WritableMemoryBuffer &Buf) : IHexSectionWriterBase(Buf) {}
30581ad6265SDimitry Andric 
30681ad6265SDimitry Andric   void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;
30781ad6265SDimitry Andric   Error visit(const StringTableSection &Sec) override;
30881ad6265SDimitry Andric };
30981ad6265SDimitry Andric 
31081ad6265SDimitry Andric class Writer {
31181ad6265SDimitry Andric protected:
31281ad6265SDimitry Andric   Object &Obj;
31381ad6265SDimitry Andric   std::unique_ptr<WritableMemoryBuffer> Buf;
31481ad6265SDimitry Andric   raw_ostream &Out;
31581ad6265SDimitry Andric 
31681ad6265SDimitry Andric public:
31781ad6265SDimitry Andric   virtual ~Writer();
31881ad6265SDimitry Andric   virtual Error finalize() = 0;
31981ad6265SDimitry Andric   virtual Error write() = 0;
32081ad6265SDimitry Andric 
32181ad6265SDimitry Andric   Writer(Object &O, raw_ostream &Out) : Obj(O), Out(Out) {}
32281ad6265SDimitry Andric };
32381ad6265SDimitry Andric 
32481ad6265SDimitry Andric template <class ELFT> class ELFWriter : public Writer {
32581ad6265SDimitry Andric private:
32681ad6265SDimitry Andric   using Elf_Addr = typename ELFT::Addr;
32781ad6265SDimitry Andric   using Elf_Shdr = typename ELFT::Shdr;
32881ad6265SDimitry Andric   using Elf_Phdr = typename ELFT::Phdr;
32981ad6265SDimitry Andric   using Elf_Ehdr = typename ELFT::Ehdr;
33081ad6265SDimitry Andric 
33181ad6265SDimitry Andric   void initEhdrSegment();
33281ad6265SDimitry Andric 
33381ad6265SDimitry Andric   void writeEhdr();
33481ad6265SDimitry Andric   void writePhdr(const Segment &Seg);
33581ad6265SDimitry Andric   void writeShdr(const SectionBase &Sec);
33681ad6265SDimitry Andric 
33781ad6265SDimitry Andric   void writePhdrs();
33881ad6265SDimitry Andric   void writeShdrs();
33981ad6265SDimitry Andric   Error writeSectionData();
34081ad6265SDimitry Andric   void writeSegmentData();
34181ad6265SDimitry Andric 
34281ad6265SDimitry Andric   void assignOffsets();
34381ad6265SDimitry Andric 
34481ad6265SDimitry Andric   std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;
34581ad6265SDimitry Andric 
34681ad6265SDimitry Andric   size_t totalSize() const;
34781ad6265SDimitry Andric 
34881ad6265SDimitry Andric public:
34981ad6265SDimitry Andric   virtual ~ELFWriter() {}
35081ad6265SDimitry Andric   bool WriteSectionHeaders;
35181ad6265SDimitry Andric 
35281ad6265SDimitry Andric   // For --only-keep-debug, select an alternative section/segment layout
35381ad6265SDimitry Andric   // algorithm.
35481ad6265SDimitry Andric   bool OnlyKeepDebug;
35581ad6265SDimitry Andric 
35681ad6265SDimitry Andric   Error finalize() override;
35781ad6265SDimitry Andric   Error write() override;
35881ad6265SDimitry Andric   ELFWriter(Object &Obj, raw_ostream &Out, bool WSH, bool OnlyKeepDebug);
35981ad6265SDimitry Andric };
36081ad6265SDimitry Andric 
36181ad6265SDimitry Andric class BinaryWriter : public Writer {
36281ad6265SDimitry Andric private:
3635f757f3fSDimitry Andric   const uint8_t GapFill;
3645f757f3fSDimitry Andric   const uint64_t PadTo;
36581ad6265SDimitry Andric   std::unique_ptr<BinarySectionWriter> SecWriter;
36681ad6265SDimitry Andric 
36781ad6265SDimitry Andric   uint64_t TotalSize = 0;
36881ad6265SDimitry Andric 
36981ad6265SDimitry Andric public:
37081ad6265SDimitry Andric   ~BinaryWriter() {}
37181ad6265SDimitry Andric   Error finalize() override;
37281ad6265SDimitry Andric   Error write() override;
3735f757f3fSDimitry Andric   BinaryWriter(Object &Obj, raw_ostream &Out, const CommonConfig &Config)
3745f757f3fSDimitry Andric       : Writer(Obj, Out), GapFill(Config.GapFill), PadTo(Config.PadTo) {}
37581ad6265SDimitry Andric };
37681ad6265SDimitry Andric 
377*0fca6ea1SDimitry Andric // A base class for writing ascii hex formats such as srec and ihex.
378*0fca6ea1SDimitry Andric class ASCIIHexWriter : public Writer {
379*0fca6ea1SDimitry Andric public:
380*0fca6ea1SDimitry Andric   ASCIIHexWriter(Object &Obj, raw_ostream &OS, StringRef OutputFile)
381*0fca6ea1SDimitry Andric       : Writer(Obj, OS), OutputFileName(OutputFile) {}
382*0fca6ea1SDimitry Andric   Error finalize() override;
383*0fca6ea1SDimitry Andric 
384*0fca6ea1SDimitry Andric protected:
385*0fca6ea1SDimitry Andric   StringRef OutputFileName;
386*0fca6ea1SDimitry Andric   size_t TotalSize = 0;
387*0fca6ea1SDimitry Andric   std::vector<const SectionBase *> Sections;
388*0fca6ea1SDimitry Andric 
389*0fca6ea1SDimitry Andric   Error checkSection(const SectionBase &S) const;
390*0fca6ea1SDimitry Andric   virtual Expected<size_t>
391*0fca6ea1SDimitry Andric   getTotalSize(WritableMemoryBuffer &EmptyBuffer) const = 0;
39281ad6265SDimitry Andric };
39381ad6265SDimitry Andric 
394*0fca6ea1SDimitry Andric class IHexWriter : public ASCIIHexWriter {
395*0fca6ea1SDimitry Andric public:
396*0fca6ea1SDimitry Andric   Error write() override;
397*0fca6ea1SDimitry Andric   IHexWriter(Object &Obj, raw_ostream &Out, StringRef OutputFile)
398*0fca6ea1SDimitry Andric       : ASCIIHexWriter(Obj, Out, OutputFile) {}
39981ad6265SDimitry Andric 
400*0fca6ea1SDimitry Andric private:
40181ad6265SDimitry Andric   uint64_t writeEntryPointRecord(uint8_t *Buf);
40281ad6265SDimitry Andric   uint64_t writeEndOfFileRecord(uint8_t *Buf);
403*0fca6ea1SDimitry Andric   Expected<size_t>
404*0fca6ea1SDimitry Andric   getTotalSize(WritableMemoryBuffer &EmptyBuffer) const override;
405*0fca6ea1SDimitry Andric };
40681ad6265SDimitry Andric 
407*0fca6ea1SDimitry Andric class SRECWriter : public ASCIIHexWriter {
40881ad6265SDimitry Andric public:
409*0fca6ea1SDimitry Andric   SRECWriter(Object &Obj, raw_ostream &OS, StringRef OutputFile)
410*0fca6ea1SDimitry Andric       : ASCIIHexWriter(Obj, OS, OutputFile) {}
41181ad6265SDimitry Andric   Error write() override;
412*0fca6ea1SDimitry Andric 
413*0fca6ea1SDimitry Andric private:
414*0fca6ea1SDimitry Andric   size_t writeHeader(uint8_t *Buf);
415*0fca6ea1SDimitry Andric   size_t writeTerminator(uint8_t *Buf, uint8_t Type);
416*0fca6ea1SDimitry Andric   Expected<size_t>
417*0fca6ea1SDimitry Andric   getTotalSize(WritableMemoryBuffer &EmptyBuffer) const override;
418*0fca6ea1SDimitry Andric };
419*0fca6ea1SDimitry Andric 
420*0fca6ea1SDimitry Andric using SRecLineData = SmallVector<char, 64>;
421*0fca6ea1SDimitry Andric struct SRecord {
422*0fca6ea1SDimitry Andric   uint8_t Type;
423*0fca6ea1SDimitry Andric   uint32_t Address;
424*0fca6ea1SDimitry Andric   ArrayRef<uint8_t> Data;
425*0fca6ea1SDimitry Andric   SRecLineData toString() const;
426*0fca6ea1SDimitry Andric   uint8_t getCount() const;
427*0fca6ea1SDimitry Andric   // Get address size in characters.
428*0fca6ea1SDimitry Andric   uint8_t getAddressSize() const;
429*0fca6ea1SDimitry Andric   uint8_t getChecksum() const;
430*0fca6ea1SDimitry Andric   size_t getSize() const;
431*0fca6ea1SDimitry Andric   static SRecord getHeader(StringRef FileName);
432*0fca6ea1SDimitry Andric   static uint8_t getType(uint32_t Address);
433*0fca6ea1SDimitry Andric 
434*0fca6ea1SDimitry Andric   enum Type : uint8_t {
435*0fca6ea1SDimitry Andric     // Vendor specific text comment.
436*0fca6ea1SDimitry Andric     S0 = 0,
437*0fca6ea1SDimitry Andric     // Data that starts at a 16 bit address.
438*0fca6ea1SDimitry Andric     S1 = 1,
439*0fca6ea1SDimitry Andric     // Data that starts at a 24 bit address.
440*0fca6ea1SDimitry Andric     S2 = 2,
441*0fca6ea1SDimitry Andric     // Data that starts at a 32 bit address.
442*0fca6ea1SDimitry Andric     S3 = 3,
443*0fca6ea1SDimitry Andric     // Reserved.
444*0fca6ea1SDimitry Andric     S4 = 4,
445*0fca6ea1SDimitry Andric     // 16 bit count of S1/S2/S3 records (optional).
446*0fca6ea1SDimitry Andric     S5 = 5,
447*0fca6ea1SDimitry Andric     // 32 bit count of S1/S2/S3 records (optional).
448*0fca6ea1SDimitry Andric     S6 = 6,
449*0fca6ea1SDimitry Andric     // Terminates a series of S3 records.
450*0fca6ea1SDimitry Andric     S7 = 7,
451*0fca6ea1SDimitry Andric     // Terminates a series of S2 records.
452*0fca6ea1SDimitry Andric     S8 = 8,
453*0fca6ea1SDimitry Andric     // Terminates a series of S1 records.
454*0fca6ea1SDimitry Andric     S9 = 9
455*0fca6ea1SDimitry Andric   };
456*0fca6ea1SDimitry Andric };
457*0fca6ea1SDimitry Andric 
458*0fca6ea1SDimitry Andric class SRECSectionWriterBase : public BinarySectionWriter {
459*0fca6ea1SDimitry Andric public:
460*0fca6ea1SDimitry Andric   explicit SRECSectionWriterBase(WritableMemoryBuffer &Buf,
461*0fca6ea1SDimitry Andric                                  uint64_t StartOffset)
462*0fca6ea1SDimitry Andric       : BinarySectionWriter(Buf), Offset(StartOffset), HeaderSize(StartOffset) {
463*0fca6ea1SDimitry Andric   }
464*0fca6ea1SDimitry Andric 
465*0fca6ea1SDimitry Andric   using BinarySectionWriter::visit;
466*0fca6ea1SDimitry Andric 
467*0fca6ea1SDimitry Andric   void writeRecords(uint32_t Entry);
468*0fca6ea1SDimitry Andric   uint64_t getBufferOffset() const { return Offset; }
469*0fca6ea1SDimitry Andric   Error visit(const Section &S) override;
470*0fca6ea1SDimitry Andric   Error visit(const OwnedDataSection &S) override;
471*0fca6ea1SDimitry Andric   Error visit(const StringTableSection &S) override;
472*0fca6ea1SDimitry Andric   Error visit(const DynamicRelocationSection &S) override;
473*0fca6ea1SDimitry Andric   uint8_t getType() const { return Type; };
474*0fca6ea1SDimitry Andric 
475*0fca6ea1SDimitry Andric protected:
476*0fca6ea1SDimitry Andric   // Offset in the output buffer.
477*0fca6ea1SDimitry Andric   uint64_t Offset;
478*0fca6ea1SDimitry Andric   // Sections start after the header.
479*0fca6ea1SDimitry Andric   uint64_t HeaderSize;
480*0fca6ea1SDimitry Andric   // Type of records to write.
481*0fca6ea1SDimitry Andric   uint8_t Type = SRecord::S1;
482*0fca6ea1SDimitry Andric   std::vector<SRecord> Records;
483*0fca6ea1SDimitry Andric 
484*0fca6ea1SDimitry Andric   void writeSection(const SectionBase &S, ArrayRef<uint8_t> Data);
485*0fca6ea1SDimitry Andric   virtual void writeRecord(SRecord &Record, uint64_t Off) = 0;
486*0fca6ea1SDimitry Andric };
487*0fca6ea1SDimitry Andric 
488*0fca6ea1SDimitry Andric // An SRECSectionWriterBase that visits sections but does not write anything.
489*0fca6ea1SDimitry Andric // This class is only used to calculate the size of the output file.
490*0fca6ea1SDimitry Andric class SRECSizeCalculator : public SRECSectionWriterBase {
491*0fca6ea1SDimitry Andric public:
492*0fca6ea1SDimitry Andric   SRECSizeCalculator(WritableMemoryBuffer &EmptyBuffer, uint64_t Offset)
493*0fca6ea1SDimitry Andric       : SRECSectionWriterBase(EmptyBuffer, Offset) {}
494*0fca6ea1SDimitry Andric 
495*0fca6ea1SDimitry Andric protected:
496*0fca6ea1SDimitry Andric   void writeRecord(SRecord &Record, uint64_t Off) override {}
497*0fca6ea1SDimitry Andric };
498*0fca6ea1SDimitry Andric 
499*0fca6ea1SDimitry Andric class SRECSectionWriter : public SRECSectionWriterBase {
500*0fca6ea1SDimitry Andric public:
501*0fca6ea1SDimitry Andric   SRECSectionWriter(WritableMemoryBuffer &Buf, uint64_t Offset)
502*0fca6ea1SDimitry Andric       : SRECSectionWriterBase(Buf, Offset) {}
503*0fca6ea1SDimitry Andric   Error visit(const StringTableSection &Sec) override;
504*0fca6ea1SDimitry Andric 
505*0fca6ea1SDimitry Andric protected:
506*0fca6ea1SDimitry Andric   void writeRecord(SRecord &Record, uint64_t Off) override;
50781ad6265SDimitry Andric };
50881ad6265SDimitry Andric 
50981ad6265SDimitry Andric class SectionBase {
51081ad6265SDimitry Andric public:
51181ad6265SDimitry Andric   std::string Name;
51281ad6265SDimitry Andric   Segment *ParentSegment = nullptr;
51381ad6265SDimitry Andric   uint64_t HeaderOffset = 0;
51481ad6265SDimitry Andric   uint32_t Index = 0;
51581ad6265SDimitry Andric 
51681ad6265SDimitry Andric   uint32_t OriginalIndex = 0;
51781ad6265SDimitry Andric   uint64_t OriginalFlags = 0;
51881ad6265SDimitry Andric   uint64_t OriginalType = ELF::SHT_NULL;
51981ad6265SDimitry Andric   uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();
52081ad6265SDimitry Andric 
52181ad6265SDimitry Andric   uint64_t Addr = 0;
52281ad6265SDimitry Andric   uint64_t Align = 1;
52381ad6265SDimitry Andric   uint32_t EntrySize = 0;
52481ad6265SDimitry Andric   uint64_t Flags = 0;
52581ad6265SDimitry Andric   uint64_t Info = 0;
52681ad6265SDimitry Andric   uint64_t Link = ELF::SHN_UNDEF;
52781ad6265SDimitry Andric   uint64_t NameIndex = 0;
52881ad6265SDimitry Andric   uint64_t Offset = 0;
52981ad6265SDimitry Andric   uint64_t Size = 0;
53081ad6265SDimitry Andric   uint64_t Type = ELF::SHT_NULL;
53181ad6265SDimitry Andric   ArrayRef<uint8_t> OriginalData;
53281ad6265SDimitry Andric   bool HasSymbol = false;
53381ad6265SDimitry Andric 
53481ad6265SDimitry Andric   SectionBase() = default;
53581ad6265SDimitry Andric   SectionBase(const SectionBase &) = default;
53681ad6265SDimitry Andric 
53781ad6265SDimitry Andric   virtual ~SectionBase() = default;
53881ad6265SDimitry Andric 
53981ad6265SDimitry Andric   virtual Error initialize(SectionTableRef SecTable);
54081ad6265SDimitry Andric   virtual void finalize();
54181ad6265SDimitry Andric   // Remove references to these sections. The list of sections must be sorted.
54281ad6265SDimitry Andric   virtual Error
54381ad6265SDimitry Andric   removeSectionReferences(bool AllowBrokenLinks,
54481ad6265SDimitry Andric                           function_ref<bool(const SectionBase *)> ToRemove);
54581ad6265SDimitry Andric   virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
54681ad6265SDimitry Andric   virtual Error accept(SectionVisitor &Visitor) const = 0;
54781ad6265SDimitry Andric   virtual Error accept(MutableSectionVisitor &Visitor) = 0;
54881ad6265SDimitry Andric   virtual void markSymbols();
54981ad6265SDimitry Andric   virtual void
55081ad6265SDimitry Andric   replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
55181ad6265SDimitry Andric   virtual bool hasContents() const { return false; }
55281ad6265SDimitry Andric   // Notify the section that it is subject to removal.
55381ad6265SDimitry Andric   virtual void onRemove();
55406c3fb27SDimitry Andric 
55506c3fb27SDimitry Andric   virtual void restoreSymTabLink(SymbolTableSection &) {}
55681ad6265SDimitry Andric };
55781ad6265SDimitry Andric 
55881ad6265SDimitry Andric class Segment {
55981ad6265SDimitry Andric private:
56081ad6265SDimitry Andric   struct SectionCompare {
56181ad6265SDimitry Andric     bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {
56281ad6265SDimitry Andric       // Some sections might have the same address if one of them is empty. To
56381ad6265SDimitry Andric       // fix this we can use the lexicographic ordering on ->Addr and the
56481ad6265SDimitry Andric       // original index.
56581ad6265SDimitry Andric       if (Lhs->OriginalOffset == Rhs->OriginalOffset)
56681ad6265SDimitry Andric         return Lhs->OriginalIndex < Rhs->OriginalIndex;
56781ad6265SDimitry Andric       return Lhs->OriginalOffset < Rhs->OriginalOffset;
56881ad6265SDimitry Andric     }
56981ad6265SDimitry Andric   };
57081ad6265SDimitry Andric 
57181ad6265SDimitry Andric public:
57281ad6265SDimitry Andric   uint32_t Type = 0;
57381ad6265SDimitry Andric   uint32_t Flags = 0;
57481ad6265SDimitry Andric   uint64_t Offset = 0;
57581ad6265SDimitry Andric   uint64_t VAddr = 0;
57681ad6265SDimitry Andric   uint64_t PAddr = 0;
57781ad6265SDimitry Andric   uint64_t FileSize = 0;
57881ad6265SDimitry Andric   uint64_t MemSize = 0;
57981ad6265SDimitry Andric   uint64_t Align = 0;
58081ad6265SDimitry Andric 
58181ad6265SDimitry Andric   uint32_t Index = 0;
58281ad6265SDimitry Andric   uint64_t OriginalOffset = 0;
58381ad6265SDimitry Andric   Segment *ParentSegment = nullptr;
58481ad6265SDimitry Andric   ArrayRef<uint8_t> Contents;
58581ad6265SDimitry Andric   std::set<const SectionBase *, SectionCompare> Sections;
58681ad6265SDimitry Andric 
58781ad6265SDimitry Andric   explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
58881ad6265SDimitry Andric   Segment() = default;
58981ad6265SDimitry Andric 
59081ad6265SDimitry Andric   const SectionBase *firstSection() const {
59181ad6265SDimitry Andric     if (!Sections.empty())
59281ad6265SDimitry Andric       return *Sections.begin();
59381ad6265SDimitry Andric     return nullptr;
59481ad6265SDimitry Andric   }
59581ad6265SDimitry Andric 
59681ad6265SDimitry Andric   void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }
59781ad6265SDimitry Andric   void addSection(const SectionBase *Sec) { Sections.insert(Sec); }
59881ad6265SDimitry Andric 
59981ad6265SDimitry Andric   ArrayRef<uint8_t> getContents() const { return Contents; }
60081ad6265SDimitry Andric };
60181ad6265SDimitry Andric 
60281ad6265SDimitry Andric class Section : public SectionBase {
60381ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
60481ad6265SDimitry Andric 
60581ad6265SDimitry Andric   ArrayRef<uint8_t> Contents;
60681ad6265SDimitry Andric   SectionBase *LinkSection = nullptr;
60706c3fb27SDimitry Andric   bool HasSymTabLink = false;
60881ad6265SDimitry Andric 
60981ad6265SDimitry Andric public:
61081ad6265SDimitry Andric   explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
61181ad6265SDimitry Andric 
61281ad6265SDimitry Andric   Error accept(SectionVisitor &Visitor) const override;
61381ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
61481ad6265SDimitry Andric   Error removeSectionReferences(
61581ad6265SDimitry Andric       bool AllowBrokenLinks,
61681ad6265SDimitry Andric       function_ref<bool(const SectionBase *)> ToRemove) override;
61781ad6265SDimitry Andric   Error initialize(SectionTableRef SecTable) override;
61881ad6265SDimitry Andric   void finalize() override;
61981ad6265SDimitry Andric   bool hasContents() const override {
62081ad6265SDimitry Andric     return Type != ELF::SHT_NOBITS && Type != ELF::SHT_NULL;
62181ad6265SDimitry Andric   }
62206c3fb27SDimitry Andric   void restoreSymTabLink(SymbolTableSection &SymTab) override;
62381ad6265SDimitry Andric };
62481ad6265SDimitry Andric 
62581ad6265SDimitry Andric class OwnedDataSection : public SectionBase {
62681ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
62781ad6265SDimitry Andric 
62881ad6265SDimitry Andric   std::vector<uint8_t> Data;
62981ad6265SDimitry Andric 
63081ad6265SDimitry Andric public:
63181ad6265SDimitry Andric   OwnedDataSection(StringRef SecName, ArrayRef<uint8_t> Data)
63281ad6265SDimitry Andric       : Data(std::begin(Data), std::end(Data)) {
63381ad6265SDimitry Andric     Name = SecName.str();
63481ad6265SDimitry Andric     Type = OriginalType = ELF::SHT_PROGBITS;
63581ad6265SDimitry Andric     Size = Data.size();
63681ad6265SDimitry Andric     OriginalOffset = std::numeric_limits<uint64_t>::max();
63781ad6265SDimitry Andric   }
63881ad6265SDimitry Andric 
63981ad6265SDimitry Andric   OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,
64081ad6265SDimitry Andric                    uint64_t SecOff) {
64181ad6265SDimitry Andric     Name = SecName.str();
64281ad6265SDimitry Andric     Type = OriginalType = ELF::SHT_PROGBITS;
64381ad6265SDimitry Andric     Addr = SecAddr;
64481ad6265SDimitry Andric     Flags = OriginalFlags = SecFlags;
64581ad6265SDimitry Andric     OriginalOffset = SecOff;
64681ad6265SDimitry Andric   }
64781ad6265SDimitry Andric 
64881ad6265SDimitry Andric   OwnedDataSection(SectionBase &S, ArrayRef<uint8_t> Data)
64981ad6265SDimitry Andric       : SectionBase(S), Data(std::begin(Data), std::end(Data)) {
65081ad6265SDimitry Andric     Size = Data.size();
65181ad6265SDimitry Andric   }
65281ad6265SDimitry Andric 
65381ad6265SDimitry Andric   void appendHexData(StringRef HexData);
65481ad6265SDimitry Andric   Error accept(SectionVisitor &Sec) const override;
65581ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
65681ad6265SDimitry Andric   bool hasContents() const override { return true; }
65781ad6265SDimitry Andric };
65881ad6265SDimitry Andric 
65981ad6265SDimitry Andric class CompressedSection : public SectionBase {
66081ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
66181ad6265SDimitry Andric 
662bdd1243dSDimitry Andric   uint32_t ChType = 0;
66381ad6265SDimitry Andric   DebugCompressionType CompressionType;
66481ad6265SDimitry Andric   uint64_t DecompressedSize;
66581ad6265SDimitry Andric   uint64_t DecompressedAlign;
666753f127fSDimitry Andric   SmallVector<uint8_t, 128> CompressedData;
66781ad6265SDimitry Andric 
66881ad6265SDimitry Andric public:
66981ad6265SDimitry Andric   CompressedSection(const SectionBase &Sec,
670bdd1243dSDimitry Andric     DebugCompressionType CompressionType, bool Is64Bits);
671bdd1243dSDimitry Andric   CompressedSection(ArrayRef<uint8_t> CompressedData, uint32_t ChType,
672bdd1243dSDimitry Andric                     uint64_t DecompressedSize, uint64_t DecompressedAlign);
67381ad6265SDimitry Andric 
67481ad6265SDimitry Andric   uint64_t getDecompressedSize() const { return DecompressedSize; }
67581ad6265SDimitry Andric   uint64_t getDecompressedAlign() const { return DecompressedAlign; }
676bdd1243dSDimitry Andric   uint64_t getChType() const { return ChType; }
67781ad6265SDimitry Andric 
67881ad6265SDimitry Andric   Error accept(SectionVisitor &Visitor) const override;
67981ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
68081ad6265SDimitry Andric 
68181ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
68281ad6265SDimitry Andric     return S->OriginalFlags & ELF::SHF_COMPRESSED;
68381ad6265SDimitry Andric   }
68481ad6265SDimitry Andric };
68581ad6265SDimitry Andric 
68681ad6265SDimitry Andric class DecompressedSection : public SectionBase {
68781ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
68881ad6265SDimitry Andric 
68981ad6265SDimitry Andric public:
690bdd1243dSDimitry Andric   uint32_t ChType;
69181ad6265SDimitry Andric   explicit DecompressedSection(const CompressedSection &Sec)
692bdd1243dSDimitry Andric       : SectionBase(Sec), ChType(Sec.getChType()) {
69381ad6265SDimitry Andric     Size = Sec.getDecompressedSize();
69481ad6265SDimitry Andric     Align = Sec.getDecompressedAlign();
69581ad6265SDimitry Andric     Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED);
69681ad6265SDimitry Andric   }
69781ad6265SDimitry Andric 
69881ad6265SDimitry Andric   Error accept(SectionVisitor &Visitor) const override;
69981ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
70081ad6265SDimitry Andric };
70181ad6265SDimitry Andric 
70281ad6265SDimitry Andric // There are two types of string tables that can exist, dynamic and not dynamic.
70381ad6265SDimitry Andric // In the dynamic case the string table is allocated. Changing a dynamic string
70481ad6265SDimitry Andric // table would mean altering virtual addresses and thus the memory image. So
70581ad6265SDimitry Andric // dynamic string tables should not have an interface to modify them or
70681ad6265SDimitry Andric // reconstruct them. This type lets us reconstruct a string table. To avoid
70781ad6265SDimitry Andric // this class being used for dynamic string tables (which has happened) the
70881ad6265SDimitry Andric // classof method checks that the particular instance is not allocated. This
70981ad6265SDimitry Andric // then agrees with the makeSection method used to construct most sections.
71081ad6265SDimitry Andric class StringTableSection : public SectionBase {
71181ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
71281ad6265SDimitry Andric 
71381ad6265SDimitry Andric   StringTableBuilder StrTabBuilder;
71481ad6265SDimitry Andric 
71581ad6265SDimitry Andric public:
71681ad6265SDimitry Andric   StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {
71781ad6265SDimitry Andric     Type = OriginalType = ELF::SHT_STRTAB;
71881ad6265SDimitry Andric   }
71981ad6265SDimitry Andric 
72081ad6265SDimitry Andric   void addString(StringRef Name);
72181ad6265SDimitry Andric   uint32_t findIndex(StringRef Name) const;
72281ad6265SDimitry Andric   void prepareForLayout();
72381ad6265SDimitry Andric   Error accept(SectionVisitor &Visitor) const override;
72481ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
72581ad6265SDimitry Andric 
72681ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
72781ad6265SDimitry Andric     if (S->OriginalFlags & ELF::SHF_ALLOC)
72881ad6265SDimitry Andric       return false;
72981ad6265SDimitry Andric     return S->OriginalType == ELF::SHT_STRTAB;
73081ad6265SDimitry Andric   }
73181ad6265SDimitry Andric };
73281ad6265SDimitry Andric 
73381ad6265SDimitry Andric // Symbols have a st_shndx field that normally stores an index but occasionally
73481ad6265SDimitry Andric // stores a different special value. This enum keeps track of what the st_shndx
73581ad6265SDimitry Andric // field means. Most of the values are just copies of the special SHN_* values.
73681ad6265SDimitry Andric // SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
73781ad6265SDimitry Andric enum SymbolShndxType {
73881ad6265SDimitry Andric   SYMBOL_SIMPLE_INDEX = 0,
73981ad6265SDimitry Andric   SYMBOL_ABS = ELF::SHN_ABS,
74081ad6265SDimitry Andric   SYMBOL_COMMON = ELF::SHN_COMMON,
74181ad6265SDimitry Andric   SYMBOL_LOPROC = ELF::SHN_LOPROC,
74281ad6265SDimitry Andric   SYMBOL_AMDGPU_LDS = ELF::SHN_AMDGPU_LDS,
74381ad6265SDimitry Andric   SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,
74481ad6265SDimitry Andric   SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,
74581ad6265SDimitry Andric   SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,
74681ad6265SDimitry Andric   SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,
74781ad6265SDimitry Andric   SYMBOL_MIPS_ACOMMON = ELF::SHN_MIPS_ACOMMON,
74881ad6265SDimitry Andric   SYMBOL_MIPS_TEXT = ELF::SHN_MIPS_TEXT,
74981ad6265SDimitry Andric   SYMBOL_MIPS_DATA = ELF::SHN_MIPS_DATA,
75081ad6265SDimitry Andric   SYMBOL_MIPS_SCOMMON = ELF::SHN_MIPS_SCOMMON,
75181ad6265SDimitry Andric   SYMBOL_MIPS_SUNDEFINED = ELF::SHN_MIPS_SUNDEFINED,
75281ad6265SDimitry Andric   SYMBOL_HIPROC = ELF::SHN_HIPROC,
75381ad6265SDimitry Andric   SYMBOL_LOOS = ELF::SHN_LOOS,
75481ad6265SDimitry Andric   SYMBOL_HIOS = ELF::SHN_HIOS,
75581ad6265SDimitry Andric   SYMBOL_XINDEX = ELF::SHN_XINDEX,
75681ad6265SDimitry Andric };
75781ad6265SDimitry Andric 
75881ad6265SDimitry Andric struct Symbol {
75981ad6265SDimitry Andric   uint8_t Binding;
76081ad6265SDimitry Andric   SectionBase *DefinedIn = nullptr;
76181ad6265SDimitry Andric   SymbolShndxType ShndxType;
76281ad6265SDimitry Andric   uint32_t Index;
76381ad6265SDimitry Andric   std::string Name;
76481ad6265SDimitry Andric   uint32_t NameIndex;
76581ad6265SDimitry Andric   uint64_t Size;
76681ad6265SDimitry Andric   uint8_t Type;
76781ad6265SDimitry Andric   uint64_t Value;
76881ad6265SDimitry Andric   uint8_t Visibility;
76981ad6265SDimitry Andric   bool Referenced = false;
77081ad6265SDimitry Andric 
77181ad6265SDimitry Andric   uint16_t getShndx() const;
77281ad6265SDimitry Andric   bool isCommon() const;
77381ad6265SDimitry Andric };
77481ad6265SDimitry Andric 
77581ad6265SDimitry Andric class SectionIndexSection : public SectionBase {
77681ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
77781ad6265SDimitry Andric 
77881ad6265SDimitry Andric private:
77981ad6265SDimitry Andric   std::vector<uint32_t> Indexes;
78081ad6265SDimitry Andric   SymbolTableSection *Symbols = nullptr;
78181ad6265SDimitry Andric 
78281ad6265SDimitry Andric public:
78381ad6265SDimitry Andric   virtual ~SectionIndexSection() {}
78481ad6265SDimitry Andric   void addIndex(uint32_t Index) {
78581ad6265SDimitry Andric     assert(Size > 0);
78681ad6265SDimitry Andric     Indexes.push_back(Index);
78781ad6265SDimitry Andric   }
78881ad6265SDimitry Andric 
78981ad6265SDimitry Andric   void reserve(size_t NumSymbols) {
79081ad6265SDimitry Andric     Indexes.reserve(NumSymbols);
79181ad6265SDimitry Andric     Size = NumSymbols * 4;
79281ad6265SDimitry Andric   }
79381ad6265SDimitry Andric   void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }
79481ad6265SDimitry Andric   Error initialize(SectionTableRef SecTable) override;
79581ad6265SDimitry Andric   void finalize() override;
79681ad6265SDimitry Andric   Error accept(SectionVisitor &Visitor) const override;
79781ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
79881ad6265SDimitry Andric 
79981ad6265SDimitry Andric   SectionIndexSection() {
80081ad6265SDimitry Andric     Name = ".symtab_shndx";
80181ad6265SDimitry Andric     Align = 4;
80281ad6265SDimitry Andric     EntrySize = 4;
80381ad6265SDimitry Andric     Type = OriginalType = ELF::SHT_SYMTAB_SHNDX;
80481ad6265SDimitry Andric   }
80581ad6265SDimitry Andric };
80681ad6265SDimitry Andric 
80781ad6265SDimitry Andric class SymbolTableSection : public SectionBase {
80881ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
80981ad6265SDimitry Andric 
81081ad6265SDimitry Andric   void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
81181ad6265SDimitry Andric   void assignIndices();
81281ad6265SDimitry Andric 
81381ad6265SDimitry Andric protected:
81481ad6265SDimitry Andric   std::vector<std::unique_ptr<Symbol>> Symbols;
81581ad6265SDimitry Andric   StringTableSection *SymbolNames = nullptr;
81681ad6265SDimitry Andric   SectionIndexSection *SectionIndexTable = nullptr;
81706c3fb27SDimitry Andric   bool IndicesChanged = false;
81881ad6265SDimitry Andric 
81981ad6265SDimitry Andric   using SymPtr = std::unique_ptr<Symbol>;
82081ad6265SDimitry Andric 
82181ad6265SDimitry Andric public:
82281ad6265SDimitry Andric   SymbolTableSection() { Type = OriginalType = ELF::SHT_SYMTAB; }
82381ad6265SDimitry Andric 
82481ad6265SDimitry Andric   void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn,
82581ad6265SDimitry Andric                  uint64_t Value, uint8_t Visibility, uint16_t Shndx,
82681ad6265SDimitry Andric                  uint64_t SymbolSize);
82781ad6265SDimitry Andric   void prepareForLayout();
82881ad6265SDimitry Andric   // An 'empty' symbol table still contains a null symbol.
82981ad6265SDimitry Andric   bool empty() const { return Symbols.size() == 1; }
83006c3fb27SDimitry Andric   bool indicesChanged() const { return IndicesChanged; }
83181ad6265SDimitry Andric   void setShndxTable(SectionIndexSection *ShndxTable) {
83281ad6265SDimitry Andric     SectionIndexTable = ShndxTable;
83381ad6265SDimitry Andric   }
83481ad6265SDimitry Andric   const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }
83581ad6265SDimitry Andric   void fillShndxTable();
83681ad6265SDimitry Andric   const SectionBase *getStrTab() const { return SymbolNames; }
83781ad6265SDimitry Andric   Expected<const Symbol *> getSymbolByIndex(uint32_t Index) const;
83881ad6265SDimitry Andric   Expected<Symbol *> getSymbolByIndex(uint32_t Index);
83981ad6265SDimitry Andric   void updateSymbols(function_ref<void(Symbol &)> Callable);
84081ad6265SDimitry Andric 
84181ad6265SDimitry Andric   Error removeSectionReferences(
84281ad6265SDimitry Andric       bool AllowBrokenLinks,
84381ad6265SDimitry Andric       function_ref<bool(const SectionBase *)> ToRemove) override;
84481ad6265SDimitry Andric   Error initialize(SectionTableRef SecTable) override;
84581ad6265SDimitry Andric   void finalize() override;
84681ad6265SDimitry Andric   Error accept(SectionVisitor &Visitor) const override;
84781ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
84881ad6265SDimitry Andric   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
84981ad6265SDimitry Andric   void replaceSectionReferences(
85081ad6265SDimitry Andric       const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
85181ad6265SDimitry Andric 
85281ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
85381ad6265SDimitry Andric     return S->OriginalType == ELF::SHT_SYMTAB;
85481ad6265SDimitry Andric   }
85581ad6265SDimitry Andric };
85681ad6265SDimitry Andric 
85781ad6265SDimitry Andric struct Relocation {
85881ad6265SDimitry Andric   Symbol *RelocSymbol = nullptr;
85981ad6265SDimitry Andric   uint64_t Offset;
86081ad6265SDimitry Andric   uint64_t Addend;
86181ad6265SDimitry Andric   uint32_t Type;
86281ad6265SDimitry Andric };
86381ad6265SDimitry Andric 
86481ad6265SDimitry Andric // All relocation sections denote relocations to apply to another section.
86581ad6265SDimitry Andric // However, some relocation sections use a dynamic symbol table and others use
86681ad6265SDimitry Andric // a regular symbol table. Because the types of the two symbol tables differ in
86781ad6265SDimitry Andric // our system (because they should behave differently) we can't uniformly
86881ad6265SDimitry Andric // represent all relocations with the same base class if we expose an interface
86981ad6265SDimitry Andric // that mentions the symbol table type. So we split the two base types into two
87081ad6265SDimitry Andric // different classes, one which handles the section the relocation is applied to
87181ad6265SDimitry Andric // and another which handles the symbol table type. The symbol table type is
87281ad6265SDimitry Andric // taken as a type parameter to the class (see RelocSectionWithSymtabBase).
87381ad6265SDimitry Andric class RelocationSectionBase : public SectionBase {
87481ad6265SDimitry Andric protected:
87581ad6265SDimitry Andric   SectionBase *SecToApplyRel = nullptr;
87681ad6265SDimitry Andric 
87781ad6265SDimitry Andric public:
87881ad6265SDimitry Andric   const SectionBase *getSection() const { return SecToApplyRel; }
87981ad6265SDimitry Andric   void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }
88081ad6265SDimitry Andric 
88181ad6265SDimitry Andric   StringRef getNamePrefix() const;
88281ad6265SDimitry Andric 
88381ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
884*0fca6ea1SDimitry Andric     return is_contained({ELF::SHT_REL, ELF::SHT_RELA, ELF::SHT_CREL},
885*0fca6ea1SDimitry Andric                         S->OriginalType);
88681ad6265SDimitry Andric   }
88781ad6265SDimitry Andric };
88881ad6265SDimitry Andric 
88981ad6265SDimitry Andric // Takes the symbol table type to use as a parameter so that we can deduplicate
89081ad6265SDimitry Andric // that code between the two symbol table types.
89181ad6265SDimitry Andric template <class SymTabType>
89281ad6265SDimitry Andric class RelocSectionWithSymtabBase : public RelocationSectionBase {
89381ad6265SDimitry Andric   void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
89481ad6265SDimitry Andric 
89581ad6265SDimitry Andric protected:
89681ad6265SDimitry Andric   RelocSectionWithSymtabBase() = default;
89781ad6265SDimitry Andric 
89881ad6265SDimitry Andric   SymTabType *Symbols = nullptr;
89981ad6265SDimitry Andric 
90081ad6265SDimitry Andric public:
90181ad6265SDimitry Andric   Error initialize(SectionTableRef SecTable) override;
90281ad6265SDimitry Andric   void finalize() override;
90381ad6265SDimitry Andric };
90481ad6265SDimitry Andric 
90581ad6265SDimitry Andric class RelocationSection
90681ad6265SDimitry Andric     : public RelocSectionWithSymtabBase<SymbolTableSection> {
90781ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
90881ad6265SDimitry Andric 
90981ad6265SDimitry Andric   std::vector<Relocation> Relocations;
91081ad6265SDimitry Andric   const Object &Obj;
91181ad6265SDimitry Andric 
91281ad6265SDimitry Andric public:
91381ad6265SDimitry Andric   RelocationSection(const Object &O) : Obj(O) {}
914*0fca6ea1SDimitry Andric   void addRelocation(const Relocation &Rel) { Relocations.push_back(Rel); }
91581ad6265SDimitry Andric   Error accept(SectionVisitor &Visitor) const override;
91681ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
91781ad6265SDimitry Andric   Error removeSectionReferences(
91881ad6265SDimitry Andric       bool AllowBrokenLinks,
91981ad6265SDimitry Andric       function_ref<bool(const SectionBase *)> ToRemove) override;
92081ad6265SDimitry Andric   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
92181ad6265SDimitry Andric   void markSymbols() override;
92281ad6265SDimitry Andric   void replaceSectionReferences(
92381ad6265SDimitry Andric       const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
92481ad6265SDimitry Andric   const Object &getObject() const { return Obj; }
92581ad6265SDimitry Andric 
92681ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
92781ad6265SDimitry Andric     if (S->OriginalFlags & ELF::SHF_ALLOC)
92881ad6265SDimitry Andric       return false;
929*0fca6ea1SDimitry Andric     return RelocationSectionBase::classof(S);
93081ad6265SDimitry Andric   }
93181ad6265SDimitry Andric };
93281ad6265SDimitry Andric 
93381ad6265SDimitry Andric // TODO: The way stripping and groups interact is complicated
93481ad6265SDimitry Andric // and still needs to be worked on.
93581ad6265SDimitry Andric 
93681ad6265SDimitry Andric class GroupSection : public SectionBase {
93781ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
93881ad6265SDimitry Andric   const SymbolTableSection *SymTab = nullptr;
93981ad6265SDimitry Andric   Symbol *Sym = nullptr;
94081ad6265SDimitry Andric   ELF::Elf32_Word FlagWord;
94181ad6265SDimitry Andric   SmallVector<SectionBase *, 3> GroupMembers;
94281ad6265SDimitry Andric 
94381ad6265SDimitry Andric public:
944*0fca6ea1SDimitry Andric   template <class T>
945*0fca6ea1SDimitry Andric   using ConstRange = iterator_range<
946*0fca6ea1SDimitry Andric       pointee_iterator<typename llvm::SmallVector<T *, 3>::const_iterator>>;
94781ad6265SDimitry Andric   // TODO: Contents is present in several classes of the hierarchy.
94881ad6265SDimitry Andric   // This needs to be refactored to avoid duplication.
94981ad6265SDimitry Andric   ArrayRef<uint8_t> Contents;
95081ad6265SDimitry Andric 
95181ad6265SDimitry Andric   explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
95281ad6265SDimitry Andric 
95381ad6265SDimitry Andric   void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }
95481ad6265SDimitry Andric   void setSymbol(Symbol *S) { Sym = S; }
95581ad6265SDimitry Andric   void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }
95681ad6265SDimitry Andric   void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }
95781ad6265SDimitry Andric 
95881ad6265SDimitry Andric   Error accept(SectionVisitor &) const override;
95981ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
96081ad6265SDimitry Andric   void finalize() override;
96181ad6265SDimitry Andric   Error removeSectionReferences(
96281ad6265SDimitry Andric       bool AllowBrokenLinks,
96381ad6265SDimitry Andric       function_ref<bool(const SectionBase *)> ToRemove) override;
96481ad6265SDimitry Andric   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
96581ad6265SDimitry Andric   void markSymbols() override;
96681ad6265SDimitry Andric   void replaceSectionReferences(
96781ad6265SDimitry Andric       const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
96881ad6265SDimitry Andric   void onRemove() override;
96981ad6265SDimitry Andric 
970*0fca6ea1SDimitry Andric   ConstRange<SectionBase> members() const {
971*0fca6ea1SDimitry Andric     return make_pointee_range(GroupMembers);
972*0fca6ea1SDimitry Andric   }
973*0fca6ea1SDimitry Andric 
97481ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
97581ad6265SDimitry Andric     return S->OriginalType == ELF::SHT_GROUP;
97681ad6265SDimitry Andric   }
97781ad6265SDimitry Andric };
97881ad6265SDimitry Andric 
97981ad6265SDimitry Andric class DynamicSymbolTableSection : public Section {
98081ad6265SDimitry Andric public:
98181ad6265SDimitry Andric   explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}
98281ad6265SDimitry Andric 
98381ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
98481ad6265SDimitry Andric     return S->OriginalType == ELF::SHT_DYNSYM;
98581ad6265SDimitry Andric   }
98681ad6265SDimitry Andric };
98781ad6265SDimitry Andric 
98881ad6265SDimitry Andric class DynamicSection : public Section {
98981ad6265SDimitry Andric public:
99081ad6265SDimitry Andric   explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}
99181ad6265SDimitry Andric 
99281ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
99381ad6265SDimitry Andric     return S->OriginalType == ELF::SHT_DYNAMIC;
99481ad6265SDimitry Andric   }
99581ad6265SDimitry Andric };
99681ad6265SDimitry Andric 
99781ad6265SDimitry Andric class DynamicRelocationSection
99881ad6265SDimitry Andric     : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {
99981ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
100081ad6265SDimitry Andric 
100181ad6265SDimitry Andric private:
100281ad6265SDimitry Andric   ArrayRef<uint8_t> Contents;
100381ad6265SDimitry Andric 
100481ad6265SDimitry Andric public:
100581ad6265SDimitry Andric   explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
100681ad6265SDimitry Andric 
100781ad6265SDimitry Andric   Error accept(SectionVisitor &) const override;
100881ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
100981ad6265SDimitry Andric   Error removeSectionReferences(
101081ad6265SDimitry Andric       bool AllowBrokenLinks,
101181ad6265SDimitry Andric       function_ref<bool(const SectionBase *)> ToRemove) override;
101281ad6265SDimitry Andric 
101381ad6265SDimitry Andric   static bool classof(const SectionBase *S) {
101481ad6265SDimitry Andric     if (!(S->OriginalFlags & ELF::SHF_ALLOC))
101581ad6265SDimitry Andric       return false;
101681ad6265SDimitry Andric     return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
101781ad6265SDimitry Andric   }
101881ad6265SDimitry Andric };
101981ad6265SDimitry Andric 
102081ad6265SDimitry Andric class GnuDebugLinkSection : public SectionBase {
102181ad6265SDimitry Andric   MAKE_SEC_WRITER_FRIEND
102281ad6265SDimitry Andric 
102381ad6265SDimitry Andric private:
102481ad6265SDimitry Andric   StringRef FileName;
102581ad6265SDimitry Andric   uint32_t CRC32;
102681ad6265SDimitry Andric 
102781ad6265SDimitry Andric   void init(StringRef File);
102881ad6265SDimitry Andric 
102981ad6265SDimitry Andric public:
103081ad6265SDimitry Andric   // If we add this section from an external source we can use this ctor.
103181ad6265SDimitry Andric   explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC);
103281ad6265SDimitry Andric   Error accept(SectionVisitor &Visitor) const override;
103381ad6265SDimitry Andric   Error accept(MutableSectionVisitor &Visitor) override;
103481ad6265SDimitry Andric };
103581ad6265SDimitry Andric 
103681ad6265SDimitry Andric class Reader {
103781ad6265SDimitry Andric public:
103881ad6265SDimitry Andric   virtual ~Reader();
103981ad6265SDimitry Andric   virtual Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const = 0;
104081ad6265SDimitry Andric };
104181ad6265SDimitry Andric 
104281ad6265SDimitry Andric using object::Binary;
104381ad6265SDimitry Andric using object::ELFFile;
104481ad6265SDimitry Andric using object::ELFObjectFile;
104581ad6265SDimitry Andric using object::OwningBinary;
104681ad6265SDimitry Andric 
104781ad6265SDimitry Andric class BasicELFBuilder {
104881ad6265SDimitry Andric protected:
104981ad6265SDimitry Andric   std::unique_ptr<Object> Obj;
105081ad6265SDimitry Andric 
105181ad6265SDimitry Andric   void initFileHeader();
105281ad6265SDimitry Andric   void initHeaderSegment();
105381ad6265SDimitry Andric   StringTableSection *addStrTab();
105481ad6265SDimitry Andric   SymbolTableSection *addSymTab(StringTableSection *StrTab);
105581ad6265SDimitry Andric   Error initSections();
105681ad6265SDimitry Andric 
105781ad6265SDimitry Andric public:
105881ad6265SDimitry Andric   BasicELFBuilder() : Obj(std::make_unique<Object>()) {}
105981ad6265SDimitry Andric };
106081ad6265SDimitry Andric 
106181ad6265SDimitry Andric class BinaryELFBuilder : public BasicELFBuilder {
106281ad6265SDimitry Andric   MemoryBuffer *MemBuf;
106381ad6265SDimitry Andric   uint8_t NewSymbolVisibility;
106481ad6265SDimitry Andric   void addData(SymbolTableSection *SymTab);
106581ad6265SDimitry Andric 
106681ad6265SDimitry Andric public:
106781ad6265SDimitry Andric   BinaryELFBuilder(MemoryBuffer *MB, uint8_t NewSymbolVisibility)
106881ad6265SDimitry Andric       : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
106981ad6265SDimitry Andric 
107081ad6265SDimitry Andric   Expected<std::unique_ptr<Object>> build();
107181ad6265SDimitry Andric };
107281ad6265SDimitry Andric 
107381ad6265SDimitry Andric class IHexELFBuilder : public BasicELFBuilder {
107481ad6265SDimitry Andric   const std::vector<IHexRecord> &Records;
107581ad6265SDimitry Andric 
107681ad6265SDimitry Andric   void addDataSections();
107781ad6265SDimitry Andric 
107881ad6265SDimitry Andric public:
107981ad6265SDimitry Andric   IHexELFBuilder(const std::vector<IHexRecord> &Records) : Records(Records) {}
108081ad6265SDimitry Andric 
108181ad6265SDimitry Andric   Expected<std::unique_ptr<Object>> build();
108281ad6265SDimitry Andric };
108381ad6265SDimitry Andric 
108481ad6265SDimitry Andric template <class ELFT> class ELFBuilder {
108581ad6265SDimitry Andric private:
108681ad6265SDimitry Andric   using Elf_Addr = typename ELFT::Addr;
108781ad6265SDimitry Andric   using Elf_Shdr = typename ELFT::Shdr;
108881ad6265SDimitry Andric   using Elf_Word = typename ELFT::Word;
108981ad6265SDimitry Andric 
109081ad6265SDimitry Andric   const ELFFile<ELFT> &ElfFile;
109181ad6265SDimitry Andric   Object &Obj;
109281ad6265SDimitry Andric   size_t EhdrOffset = 0;
1093bdd1243dSDimitry Andric   std::optional<StringRef> ExtractPartition;
109481ad6265SDimitry Andric 
109581ad6265SDimitry Andric   void setParentSegment(Segment &Child);
109681ad6265SDimitry Andric   Error readProgramHeaders(const ELFFile<ELFT> &HeadersFile);
109781ad6265SDimitry Andric   Error initGroupSection(GroupSection *GroupSec);
109881ad6265SDimitry Andric   Error initSymbolTable(SymbolTableSection *SymTab);
109981ad6265SDimitry Andric   Error readSectionHeaders();
110081ad6265SDimitry Andric   Error readSections(bool EnsureSymtab);
110181ad6265SDimitry Andric   Error findEhdrOffset();
110281ad6265SDimitry Andric   Expected<SectionBase &> makeSection(const Elf_Shdr &Shdr);
110381ad6265SDimitry Andric 
110481ad6265SDimitry Andric public:
110581ad6265SDimitry Andric   ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
1106bdd1243dSDimitry Andric              std::optional<StringRef> ExtractPartition);
110781ad6265SDimitry Andric 
110881ad6265SDimitry Andric   Error build(bool EnsureSymtab);
110981ad6265SDimitry Andric };
111081ad6265SDimitry Andric 
111181ad6265SDimitry Andric class BinaryReader : public Reader {
111281ad6265SDimitry Andric   MemoryBuffer *MemBuf;
111381ad6265SDimitry Andric   uint8_t NewSymbolVisibility;
111481ad6265SDimitry Andric 
111581ad6265SDimitry Andric public:
111681ad6265SDimitry Andric   BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility)
111781ad6265SDimitry Andric       : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
111881ad6265SDimitry Andric   Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
111981ad6265SDimitry Andric };
112081ad6265SDimitry Andric 
112181ad6265SDimitry Andric class IHexReader : public Reader {
112281ad6265SDimitry Andric   MemoryBuffer *MemBuf;
112381ad6265SDimitry Andric 
112481ad6265SDimitry Andric   Expected<std::vector<IHexRecord>> parse() const;
112581ad6265SDimitry Andric   Error parseError(size_t LineNo, Error E) const {
112681ad6265SDimitry Andric     return LineNo == -1U
112781ad6265SDimitry Andric                ? createFileError(MemBuf->getBufferIdentifier(), std::move(E))
112881ad6265SDimitry Andric                : createFileError(MemBuf->getBufferIdentifier(), LineNo,
112981ad6265SDimitry Andric                                  std::move(E));
113081ad6265SDimitry Andric   }
113181ad6265SDimitry Andric   template <typename... Ts>
113281ad6265SDimitry Andric   Error parseError(size_t LineNo, char const *Fmt, const Ts &...Vals) const {
113381ad6265SDimitry Andric     Error E = createStringError(errc::invalid_argument, Fmt, Vals...);
113481ad6265SDimitry Andric     return parseError(LineNo, std::move(E));
113581ad6265SDimitry Andric   }
113681ad6265SDimitry Andric 
113781ad6265SDimitry Andric public:
113881ad6265SDimitry Andric   IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}
113981ad6265SDimitry Andric 
114081ad6265SDimitry Andric   Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
114181ad6265SDimitry Andric };
114281ad6265SDimitry Andric 
114381ad6265SDimitry Andric class ELFReader : public Reader {
114481ad6265SDimitry Andric   Binary *Bin;
1145bdd1243dSDimitry Andric   std::optional<StringRef> ExtractPartition;
114681ad6265SDimitry Andric 
114781ad6265SDimitry Andric public:
114881ad6265SDimitry Andric   Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
1149bdd1243dSDimitry Andric   explicit ELFReader(Binary *B, std::optional<StringRef> ExtractPartition)
115081ad6265SDimitry Andric       : Bin(B), ExtractPartition(ExtractPartition) {}
115181ad6265SDimitry Andric };
115281ad6265SDimitry Andric 
115381ad6265SDimitry Andric class Object {
115481ad6265SDimitry Andric private:
115581ad6265SDimitry Andric   using SecPtr = std::unique_ptr<SectionBase>;
115681ad6265SDimitry Andric   using SegPtr = std::unique_ptr<Segment>;
115781ad6265SDimitry Andric 
115881ad6265SDimitry Andric   std::vector<SecPtr> Sections;
115981ad6265SDimitry Andric   std::vector<SegPtr> Segments;
116081ad6265SDimitry Andric   std::vector<SecPtr> RemovedSections;
116181ad6265SDimitry Andric   DenseMap<SectionBase *, std::vector<uint8_t>> UpdatedSections;
116281ad6265SDimitry Andric 
116381ad6265SDimitry Andric   static bool sectionIsAlloc(const SectionBase &Sec) {
116481ad6265SDimitry Andric     return Sec.Flags & ELF::SHF_ALLOC;
116581ad6265SDimitry Andric   };
116681ad6265SDimitry Andric 
116781ad6265SDimitry Andric public:
116881ad6265SDimitry Andric   template <class T>
116981ad6265SDimitry Andric   using ConstRange = iterator_range<pointee_iterator<
117081ad6265SDimitry Andric       typename std::vector<std::unique_ptr<T>>::const_iterator>>;
117181ad6265SDimitry Andric 
117281ad6265SDimitry Andric   // It is often the case that the ELF header and the program header table are
117381ad6265SDimitry Andric   // not present in any segment. This could be a problem during file layout,
117481ad6265SDimitry Andric   // because other segments may get assigned an offset where either of the
117581ad6265SDimitry Andric   // two should reside, which will effectively corrupt the resulting binary.
117681ad6265SDimitry Andric   // Other than that we use these segments to track program header offsets
117781ad6265SDimitry Andric   // when they may not follow the ELF header.
117881ad6265SDimitry Andric   Segment ElfHdrSegment;
117981ad6265SDimitry Andric   Segment ProgramHdrSegment;
118081ad6265SDimitry Andric 
1181bdd1243dSDimitry Andric   bool Is64Bits;
118281ad6265SDimitry Andric   uint8_t OSABI;
118381ad6265SDimitry Andric   uint8_t ABIVersion;
118481ad6265SDimitry Andric   uint64_t Entry;
118581ad6265SDimitry Andric   uint64_t SHOff;
118681ad6265SDimitry Andric   uint32_t Type;
118781ad6265SDimitry Andric   uint32_t Machine;
118881ad6265SDimitry Andric   uint32_t Version;
118981ad6265SDimitry Andric   uint32_t Flags;
119081ad6265SDimitry Andric 
119181ad6265SDimitry Andric   bool HadShdrs = true;
119281ad6265SDimitry Andric   bool MustBeRelocatable = false;
119381ad6265SDimitry Andric   StringTableSection *SectionNames = nullptr;
119481ad6265SDimitry Andric   SymbolTableSection *SymbolTable = nullptr;
119581ad6265SDimitry Andric   SectionIndexSection *SectionIndexTable = nullptr;
119681ad6265SDimitry Andric 
119781ad6265SDimitry Andric   bool IsMips64EL = false;
119881ad6265SDimitry Andric 
119981ad6265SDimitry Andric   SectionTableRef sections() const { return SectionTableRef(Sections); }
120081ad6265SDimitry Andric   iterator_range<
120181ad6265SDimitry Andric       filter_iterator<pointee_iterator<std::vector<SecPtr>::const_iterator>,
120281ad6265SDimitry Andric                       decltype(&sectionIsAlloc)>>
120381ad6265SDimitry Andric   allocSections() const {
120481ad6265SDimitry Andric     return make_filter_range(make_pointee_range(Sections), sectionIsAlloc);
120581ad6265SDimitry Andric   }
120681ad6265SDimitry Andric 
120781ad6265SDimitry Andric   const auto &getUpdatedSections() const { return UpdatedSections; }
120881ad6265SDimitry Andric   Error updateSection(StringRef Name, ArrayRef<uint8_t> Data);
120981ad6265SDimitry Andric 
121081ad6265SDimitry Andric   SectionBase *findSection(StringRef Name) {
121181ad6265SDimitry Andric     auto SecIt =
121281ad6265SDimitry Andric         find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });
121381ad6265SDimitry Andric     return SecIt == Sections.end() ? nullptr : SecIt->get();
121481ad6265SDimitry Andric   }
121581ad6265SDimitry Andric   SectionTableRef removedSections() { return SectionTableRef(RemovedSections); }
121681ad6265SDimitry Andric 
121781ad6265SDimitry Andric   ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
121881ad6265SDimitry Andric 
121981ad6265SDimitry Andric   Error removeSections(bool AllowBrokenLinks,
122081ad6265SDimitry Andric                        std::function<bool(const SectionBase &)> ToRemove);
1221*0fca6ea1SDimitry Andric   Error compressOrDecompressSections(const CommonConfig &Config);
122281ad6265SDimitry Andric   Error replaceSections(const DenseMap<SectionBase *, SectionBase *> &FromTo);
122381ad6265SDimitry Andric   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
122481ad6265SDimitry Andric   template <class T, class... Ts> T &addSection(Ts &&...Args) {
122581ad6265SDimitry Andric     auto Sec = std::make_unique<T>(std::forward<Ts>(Args)...);
122681ad6265SDimitry Andric     auto Ptr = Sec.get();
122781ad6265SDimitry Andric     MustBeRelocatable |= isa<RelocationSection>(*Ptr);
122881ad6265SDimitry Andric     Sections.emplace_back(std::move(Sec));
122981ad6265SDimitry Andric     Ptr->Index = Sections.size();
123081ad6265SDimitry Andric     return *Ptr;
123181ad6265SDimitry Andric   }
123281ad6265SDimitry Andric   Error addNewSymbolTable();
123381ad6265SDimitry Andric   Segment &addSegment(ArrayRef<uint8_t> Data) {
123481ad6265SDimitry Andric     Segments.emplace_back(std::make_unique<Segment>(Data));
123581ad6265SDimitry Andric     return *Segments.back();
123681ad6265SDimitry Andric   }
123781ad6265SDimitry Andric   bool isRelocatable() const {
123881ad6265SDimitry Andric     return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;
123981ad6265SDimitry Andric   }
124081ad6265SDimitry Andric };
124181ad6265SDimitry Andric 
124281ad6265SDimitry Andric } // end namespace elf
124381ad6265SDimitry Andric } // end namespace objcopy
124481ad6265SDimitry Andric } // end namespace llvm
124581ad6265SDimitry Andric 
124681ad6265SDimitry Andric #endif // LLVM_LIB_OBJCOPY_ELF_ELFOBJECT_H
1247