//===- ELFObject.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ELFObject.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Path.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::objcopy::elf;
using namespace llvm::object;

template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) {
  uint8_t *B = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
               Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr);
  Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);
  Phdr.p_type = Seg.Type;
  Phdr.p_flags = Seg.Flags;
  Phdr.p_offset = Seg.Offset;
  Phdr.p_vaddr = Seg.VAddr;
  Phdr.p_paddr = Seg.PAddr;
  Phdr.p_filesz = Seg.FileSize;
  Phdr.p_memsz = Seg.MemSize;
  Phdr.p_align = Seg.Align;
}

Error SectionBase::removeSectionReferences(
    bool, function_ref<bool(const SectionBase *)>) {
  return Error::success();
}

Error SectionBase::removeSymbols(function_ref<bool(const Symbol &)>) {
  return Error::success();
}

Error SectionBase::initialize(SectionTableRef) { return Error::success(); }
void SectionBase::finalize() {}
void SectionBase::markSymbols() {}
void SectionBase::replaceSectionReferences(
    const DenseMap<SectionBase *, SectionBase *> &) {}
void SectionBase::onRemove() {}

template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
  uint8_t *B =
      reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Sec.HeaderOffset;
  Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);
  Shdr.sh_name = Sec.NameIndex;
  Shdr.sh_type = Sec.Type;
  Shdr.sh_flags = Sec.Flags;
  Shdr.sh_addr = Sec.Addr;
  Shdr.sh_offset = Sec.Offset;
  Shdr.sh_size = Sec.Size;
  Shdr.sh_link = Sec.Link;
  Shdr.sh_info = Sec.Info;
  Shdr.sh_addralign = Sec.Align;
  Shdr.sh_entsize = Sec.EntrySize;
}

template <class ELFT> Error ELFSectionSizer<ELFT>::visit(Section &) {
  return Error::success();
}

template <class ELFT> Error ELFSectionSizer<ELFT>::visit(OwnedDataSection &) {
  return Error::success();
}

template <class ELFT> Error ELFSectionSizer<ELFT>::visit(StringTableSection &) {
  return Error::success();
}

template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(DynamicRelocationSection &) {
  return Error::success();
}

template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(SymbolTableSection &Sec) {
  Sec.EntrySize = sizeof(Elf_Sym);
  Sec.Size = Sec.Symbols.size() * Sec.EntrySize;
  // Align to the largest field in Elf_Sym.
  Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
  return Error::success();
}

template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(RelocationSection &Sec) {
  Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
  Sec.Size = Sec.Relocations.size() * Sec.EntrySize;
  // Align to the largest field in Elf_Rel(a).
  Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
  return Error::success();
}

template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(GnuDebugLinkSection &) {
  return Error::success();
}

template <class ELFT> Error ELFSectionSizer<ELFT>::visit(GroupSection &Sec) {
  Sec.Size = sizeof(Elf_Word) + Sec.GroupMembers.size() * sizeof(Elf_Word);
  return Error::success();
}

template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(SectionIndexSection &) {
  return Error::success();
}

template <class ELFT> Error ELFSectionSizer<ELFT>::visit(CompressedSection &) {
  return Error::success();
}

template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(DecompressedSection &) {
  return Error::success();
}

Error BinarySectionWriter::visit(const SectionIndexSection &Sec) {
  return createStringError(errc::operation_not_permitted,
                           "cannot write symbol section index table '" +
                               Sec.Name + "' ");
}

Error BinarySectionWriter::visit(const SymbolTableSection &Sec) {
  return createStringError(errc::operation_not_permitted,
                           "cannot write symbol table '" + Sec.Name +
                               "' out to binary");
}

Error BinarySectionWriter::visit(const RelocationSection &Sec) {
  return createStringError(errc::operation_not_permitted,
                           "cannot write relocation section '" + Sec.Name +
                               "' out to binary");
}

Error BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) {
  return createStringError(errc::operation_not_permitted,
                           "cannot write '" + Sec.Name + "' out to binary");
}

Error BinarySectionWriter::visit(const GroupSection &Sec) {
  return createStringError(errc::operation_not_permitted,
                           "cannot write '" + Sec.Name + "' out to binary");
}

Error SectionWriter::visit(const Section &Sec) {
  if (Sec.Type != SHT_NOBITS)
    llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);

  return Error::success();
}

static bool addressOverflows32bit(uint64_t Addr) {
  // Sign extended 32 bit addresses (e.g 0xFFFFFFFF80000000) are ok
  return Addr > UINT32_MAX && Addr + 0x80000000 > UINT32_MAX;
}

template <class T> static T checkedGetHex(StringRef S) {
  T Value;
  bool Fail = S.getAsInteger(16, Value);
  assert(!Fail);
  (void)Fail;
  return Value;
}

// Fills exactly Len bytes of buffer with hexadecimal characters
// representing value 'X'
template <class T, class Iterator>
static Iterator toHexStr(T X, Iterator It, size_t Len) {
  // Fill range with '0'
  std::fill(It, It + Len, '0');

  for (long I = Len - 1; I >= 0; --I) {
    unsigned char Mod = static_cast<unsigned char>(X) & 15;
    *(It + I) = hexdigit(Mod, false);
    X >>= 4;
  }
  assert(X == 0);
  return It + Len;
}

uint8_t IHexRecord::getChecksum(StringRef S) {
  assert((S.size() & 1) == 0);
  uint8_t Checksum = 0;
  while (!S.empty()) {
    Checksum += checkedGetHex<uint8_t>(S.take_front(2));
    S = S.drop_front(2);
  }
  return -Checksum;
}

IHexLineData IHexRecord::getLine(uint8_t Type, uint16_t Addr,
                                 ArrayRef<uint8_t> Data) {
  IHexLineData Line(getLineLength(Data.size()));
  assert(Line.size());
  auto Iter = Line.begin();
  *Iter++ = ':';
  Iter = toHexStr(Data.size(), Iter, 2);
  Iter = toHexStr(Addr, Iter, 4);
  Iter = toHexStr(Type, Iter, 2);
  for (uint8_t X : Data)
    Iter = toHexStr(X, Iter, 2);
  StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
  Iter = toHexStr(getChecksum(S), Iter, 2);
  *Iter++ = '\r';
  *Iter++ = '\n';
  assert(Iter == Line.end());
  return Line;
}

static Error checkRecord(const IHexRecord &R) {
  switch (R.Type) {
  case IHexRecord::Data:
    if (R.HexData.size() == 0)
      return createStringError(
          errc::invalid_argument,
          "zero data length is not allowed for data records");
    break;
  case IHexRecord::EndOfFile:
    break;
  case IHexRecord::SegmentAddr:
    // 20-bit segment address. Data length must be 2 bytes
    // (4 bytes in hex)
    if (R.HexData.size() != 4)
      return createStringError(
          errc::invalid_argument,
          "segment address data should be 2 bytes in size");
    break;
  case IHexRecord::StartAddr80x86:
  case IHexRecord::StartAddr:
    if (R.HexData.size() != 8)
      return createStringError(errc::invalid_argument,
                               "start address data should be 4 bytes in size");
    // According to Intel HEX specification '03' record
    // only specifies the code address within the 20-bit
    // segmented address space of the 8086/80186. This
    // means 12 high order bits should be zeroes.
    if (R.Type == IHexRecord::StartAddr80x86 &&
        R.HexData.take_front(3) != "000")
      return createStringError(errc::invalid_argument,
                               "start address exceeds 20 bit for 80x86");
    break;
  case IHexRecord::ExtendedAddr:
    // 16-31 bits of linear base address
    if (R.HexData.size() != 4)
      return createStringError(
          errc::invalid_argument,
          "extended address data should be 2 bytes in size");
    break;
  default:
    // Unknown record type
    return createStringError(errc::invalid_argument, "unknown record type: %u",
                             static_cast<unsigned>(R.Type));
  }
  return Error::success();
}

// Checks that IHEX line contains valid characters.
// This allows converting hexadecimal data to integers
// without extra verification.
static Error checkChars(StringRef Line) {
  assert(!Line.empty());
  if (Line[0] != ':')
    return createStringError(errc::invalid_argument,
                             "missing ':' in the beginning of line.");

  for (size_t Pos = 1; Pos < Line.size(); ++Pos)
    if (hexDigitValue(Line[Pos]) == -1U)
      return createStringError(errc::invalid_argument,
                               "invalid character at position %zu.", Pos + 1);
  return Error::success();
}

Expected<IHexRecord> IHexRecord::parse(StringRef Line) {
  assert(!Line.empty());

  // ':' + Length + Address + Type + Checksum with empty data ':LLAAAATTCC'
  if (Line.size() < 11)
    return createStringError(errc::invalid_argument,
                             "line is too short: %zu chars.", Line.size());

  if (Error E = checkChars(Line))
    return std::move(E);

  IHexRecord Rec;
  size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));
  if (Line.size() != getLength(DataLen))
    return createStringError(errc::invalid_argument,
                             "invalid line length %zu (should be %zu)",
                             Line.size(), getLength(DataLen));

  Rec.Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));
  Rec.Type = checkedGetHex<uint8_t>(Line.substr(7, 2));
  Rec.HexData = Line.substr(9, DataLen * 2);

  if (getChecksum(Line.drop_front(1)) != 0)
    return createStringError(errc::invalid_argument, "incorrect checksum.");
  if (Error E = checkRecord(Rec))
    return std::move(E);
  return Rec;
}

static uint64_t sectionPhysicalAddr(const SectionBase *Sec) {
  Segment *Seg = Sec->ParentSegment;
  if (Seg && Seg->Type != ELF::PT_LOAD)
    Seg = nullptr;
  return Seg ? Seg->PAddr + Sec->OriginalOffset - Seg->OriginalOffset
             : Sec->Addr;
}

void IHexSectionWriterBase::writeSection(const SectionBase *Sec,
                                         ArrayRef<uint8_t> Data) {
  assert(Data.size() == Sec->Size);
  const uint32_t ChunkSize = 16;
  uint32_t Addr = sectionPhysicalAddr(Sec) & 0xFFFFFFFFU;
  while (!Data.empty()) {
    uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);
    if (Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
      if (Addr > 0xFFFFFU) {
        // Write extended address record, zeroing segment address
        // if needed.
        if (SegmentAddr != 0)
          SegmentAddr = writeSegmentAddr(0U);
        BaseAddr = writeBaseAddr(Addr);
      } else {
        // We can still remain 16-bit
        SegmentAddr = writeSegmentAddr(Addr);
      }
    }
    uint64_t SegOffset = Addr - BaseAddr - SegmentAddr;
    assert(SegOffset <= 0xFFFFU);
    DataSize = std::min(DataSize, 0x10000U - SegOffset);
    writeData(0, SegOffset, Data.take_front(DataSize));
    Addr += DataSize;
    Data = Data.drop_front(DataSize);
  }
}

uint64_t IHexSectionWriterBase::writeSegmentAddr(uint64_t Addr) {
  assert(Addr <= 0xFFFFFU);
  uint8_t Data[] = {static_cast<uint8_t>((Addr & 0xF0000U) >> 12), 0};
  writeData(2, 0, Data);
  return Addr & 0xF0000U;
}

uint64_t IHexSectionWriterBase::writeBaseAddr(uint64_t Addr) {
  assert(Addr <= 0xFFFFFFFFU);
  uint64_t Base = Addr & 0xFFFF0000U;
  uint8_t Data[] = {static_cast<uint8_t>(Base >> 24),
                    static_cast<uint8_t>((Base >> 16) & 0xFF)};
  writeData(4, 0, Data);
  return Base;
}

void IHexSectionWriterBase::writeData(uint8_t, uint16_t,
                                      ArrayRef<uint8_t> Data) {
  Offset += IHexRecord::getLineLength(Data.size());
}

Error IHexSectionWriterBase::visit(const Section &Sec) {
  writeSection(&Sec, Sec.Contents);
  return Error::success();
}

Error IHexSectionWriterBase::visit(const OwnedDataSection &Sec) {
  writeSection(&Sec, Sec.Data);
  return Error::success();
}

Error IHexSectionWriterBase::visit(const StringTableSection &Sec) {
  // Check that sizer has already done its work
  assert(Sec.Size == Sec.StrTabBuilder.getSize());
  // We are free to pass an invalid pointer to writeSection as long
  // as we don't actually write any data. The real writer class has
  // to override this method .
  writeSection(&Sec, {nullptr, static_cast<size_t>(Sec.Size)});
  return Error::success();
}

Error IHexSectionWriterBase::visit(const DynamicRelocationSection &Sec) {
  writeSection(&Sec, Sec.Contents);
  return Error::success();
}

void IHexSectionWriter::writeData(uint8_t Type, uint16_t Addr,
                                  ArrayRef<uint8_t> Data) {
  IHexLineData HexData = IHexRecord::getLine(Type, Addr, Data);
  memcpy(Out.getBufferStart() + Offset, HexData.data(), HexData.size());
  Offset += HexData.size();
}

Error IHexSectionWriter::visit(const StringTableSection &Sec) {
  assert(Sec.Size == Sec.StrTabBuilder.getSize());
  std::vector<uint8_t> Data(Sec.Size);
  Sec.StrTabBuilder.write(Data.data());
  writeSection(&Sec, Data);
  return Error::success();
}

Error Section::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error Section::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

void Section::restoreSymTabLink(SymbolTableSection &SymTab) {
  if (HasSymTabLink) {
    assert(LinkSection == nullptr);
    LinkSection = &SymTab;
  }
}

Error SectionWriter::visit(const OwnedDataSection &Sec) {
  llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);
  return Error::success();
}

template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const DecompressedSection &Sec) {
  ArrayRef<uint8_t> Compressed =
      Sec.OriginalData.slice(sizeof(Elf_Chdr_Impl<ELFT>));
  SmallVector<uint8_t, 128> Decompressed;
  DebugCompressionType Type;
  switch (Sec.ChType) {
  case ELFCOMPRESS_ZLIB:
    Type = DebugCompressionType::Zlib;
    break;
  case ELFCOMPRESS_ZSTD:
    Type = DebugCompressionType::Zstd;
    break;
  default:
    return createStringError(errc::invalid_argument,
                             "--decompress-debug-sections: ch_type (" +
                                 Twine(Sec.ChType) + ") of section '" +
                                 Sec.Name + "' is unsupported");
  }
  if (auto *Reason =
          compression::getReasonIfUnsupported(compression::formatFor(Type)))
    return createStringError(errc::invalid_argument,
                             "failed to decompress section '" + Sec.Name +
                                 "': " + Reason);
  if (Error E = compression::decompress(Type, Compressed, Decompressed,
                                        static_cast<size_t>(Sec.Size)))
    return createStringError(errc::invalid_argument,
                             "failed to decompress section '" + Sec.Name +
                                 "': " + toString(std::move(E)));

  uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
  std::copy(Decompressed.begin(), Decompressed.end(), Buf);

  return Error::success();
}

Error BinarySectionWriter::visit(const DecompressedSection &Sec) {
  return createStringError(errc::operation_not_permitted,
                           "cannot write compressed section '" + Sec.Name +
                               "' ");
}

Error DecompressedSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error DecompressedSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

Error OwnedDataSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error OwnedDataSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

void OwnedDataSection::appendHexData(StringRef HexData) {
  assert((HexData.size() & 1) == 0);
  while (!HexData.empty()) {
    Data.push_back(checkedGetHex<uint8_t>(HexData.take_front(2)));
    HexData = HexData.drop_front(2);
  }
  Size = Data.size();
}

Error BinarySectionWriter::visit(const CompressedSection &Sec) {
  return createStringError(errc::operation_not_permitted,
                           "cannot write compressed section '" + Sec.Name +
                               "' ");
}

template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) {
  uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
  Elf_Chdr_Impl<ELFT> Chdr = {};
  switch (Sec.CompressionType) {
  case DebugCompressionType::None:
    std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf);
    return Error::success();
  case DebugCompressionType::Zlib:
    Chdr.ch_type = ELF::ELFCOMPRESS_ZLIB;
    break;
  case DebugCompressionType::Zstd:
    Chdr.ch_type = ELF::ELFCOMPRESS_ZSTD;
    break;
  }
  Chdr.ch_size = Sec.DecompressedSize;
  Chdr.ch_addralign = Sec.DecompressedAlign;
  memcpy(Buf, &Chdr, sizeof(Chdr));
  Buf += sizeof(Chdr);

  std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);
  return Error::success();
}

CompressedSection::CompressedSection(const SectionBase &Sec,
                                     DebugCompressionType CompressionType,
                                     bool Is64Bits)
    : SectionBase(Sec), CompressionType(CompressionType),
      DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {
  compression::compress(compression::Params(CompressionType), OriginalData,
                        CompressedData);

  Flags |= ELF::SHF_COMPRESSED;
  size_t ChdrSize = Is64Bits ? sizeof(object::Elf_Chdr_Impl<object::ELF64LE>)
                             : sizeof(object::Elf_Chdr_Impl<object::ELF32LE>);
  Size = ChdrSize + CompressedData.size();
  Align = 8;
}

CompressedSection::CompressedSection(ArrayRef<uint8_t> CompressedData,
                                     uint32_t ChType, uint64_t DecompressedSize,
                                     uint64_t DecompressedAlign)
    : ChType(ChType), CompressionType(DebugCompressionType::None),
      DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
  OriginalData = CompressedData;
}

Error CompressedSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error CompressedSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

void StringTableSection::addString(StringRef Name) { StrTabBuilder.add(Name); }

uint32_t StringTableSection::findIndex(StringRef Name) const {
  return StrTabBuilder.getOffset(Name);
}

void StringTableSection::prepareForLayout() {
  StrTabBuilder.finalize();
  Size = StrTabBuilder.getSize();
}

Error SectionWriter::visit(const StringTableSection &Sec) {
  Sec.StrTabBuilder.write(reinterpret_cast<uint8_t *>(Out.getBufferStart()) +
                          Sec.Offset);
  return Error::success();
}

Error StringTableSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error StringTableSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {
  uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
  llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));
  return Error::success();
}

Error SectionIndexSection::initialize(SectionTableRef SecTable) {
  Size = 0;
  Expected<SymbolTableSection *> Sec =
      SecTable.getSectionOfType<SymbolTableSection>(
          Link,
          "Link field value " + Twine(Link) + " in section " + Name +
              " is invalid",
          "Link field value " + Twine(Link) + " in section " + Name +
              " is not a symbol table");
  if (!Sec)
    return Sec.takeError();

  setSymTab(*Sec);
  Symbols->setShndxTable(this);
  return Error::success();
}

void SectionIndexSection::finalize() { Link = Symbols->Index; }

Error SectionIndexSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error SectionIndexSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
  switch (Index) {
  case SHN_ABS:
  case SHN_COMMON:
    return true;
  }

  if (Machine == EM_AMDGPU) {
    return Index == SHN_AMDGPU_LDS;
  }

  if (Machine == EM_MIPS) {
    switch (Index) {
    case SHN_MIPS_ACOMMON:
    case SHN_MIPS_SCOMMON:
    case SHN_MIPS_SUNDEFINED:
      return true;
    }
  }

  if (Machine == EM_HEXAGON) {
    switch (Index) {
    case SHN_HEXAGON_SCOMMON:
    case SHN_HEXAGON_SCOMMON_1:
    case SHN_HEXAGON_SCOMMON_2:
    case SHN_HEXAGON_SCOMMON_4:
    case SHN_HEXAGON_SCOMMON_8:
      return true;
    }
  }
  return false;
}

// Large indexes force us to clarify exactly what this function should do. This
// function should return the value that will appear in st_shndx when written
// out.
uint16_t Symbol::getShndx() const {
  if (DefinedIn != nullptr) {
    if (DefinedIn->Index >= SHN_LORESERVE)
      return SHN_XINDEX;
    return DefinedIn->Index;
  }

  if (ShndxType == SYMBOL_SIMPLE_INDEX) {
    // This means that we don't have a defined section but we do need to
    // output a legitimate section index.
    return SHN_UNDEF;
  }

  assert(ShndxType == SYMBOL_ABS || ShndxType == SYMBOL_COMMON ||
         (ShndxType >= SYMBOL_LOPROC && ShndxType <= SYMBOL_HIPROC) ||
         (ShndxType >= SYMBOL_LOOS && ShndxType <= SYMBOL_HIOS));
  return static_cast<uint16_t>(ShndxType);
}

bool Symbol::isCommon() const { return getShndx() == SHN_COMMON; }

void SymbolTableSection::assignIndices() {
  uint32_t Index = 0;
  for (auto &Sym : Symbols) {
    if (Sym->Index != Index)
      IndicesChanged = true;
    Sym->Index = Index++;
  }
}

void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
                                   SectionBase *DefinedIn, uint64_t Value,
                                   uint8_t Visibility, uint16_t Shndx,
                                   uint64_t SymbolSize) {
  Symbol Sym;
  Sym.Name = Name.str();
  Sym.Binding = Bind;
  Sym.Type = Type;
  Sym.DefinedIn = DefinedIn;
  if (DefinedIn != nullptr)
    DefinedIn->HasSymbol = true;
  if (DefinedIn == nullptr) {
    if (Shndx >= SHN_LORESERVE)
      Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
    else
      Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
  }
  Sym.Value = Value;
  Sym.Visibility = Visibility;
  Sym.Size = SymbolSize;
  Sym.Index = Symbols.size();
  Symbols.emplace_back(std::make_unique<Symbol>(Sym));
  Size += this->EntrySize;
}

Error SymbolTableSection::removeSectionReferences(
    bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
  if (ToRemove(SectionIndexTable))
    SectionIndexTable = nullptr;
  if (ToRemove(SymbolNames)) {
    if (!AllowBrokenLinks)
      return createStringError(
          llvm::errc::invalid_argument,
          "string table '%s' cannot be removed because it is "
          "referenced by the symbol table '%s'",
          SymbolNames->Name.data(), this->Name.data());
    SymbolNames = nullptr;
  }
  return removeSymbols(
      [ToRemove](const Symbol &Sym) { return ToRemove(Sym.DefinedIn); });
}

void SymbolTableSection::updateSymbols(function_ref<void(Symbol &)> Callable) {
  for (SymPtr &Sym : llvm::drop_begin(Symbols))
    Callable(*Sym);
  std::stable_partition(
      std::begin(Symbols), std::end(Symbols),
      [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });
  assignIndices();
}

Error SymbolTableSection::removeSymbols(
    function_ref<bool(const Symbol &)> ToRemove) {
  Symbols.erase(
      std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
                     [ToRemove](const SymPtr &Sym) { return ToRemove(*Sym); }),
      std::end(Symbols));
  auto PrevSize = Size;
  Size = Symbols.size() * EntrySize;
  if (Size < PrevSize)
    IndicesChanged = true;
  assignIndices();
  return Error::success();
}

void SymbolTableSection::replaceSectionReferences(
    const DenseMap<SectionBase *, SectionBase *> &FromTo) {
  for (std::unique_ptr<Symbol> &Sym : Symbols)
    if (SectionBase *To = FromTo.lookup(Sym->DefinedIn))
      Sym->DefinedIn = To;
}

Error SymbolTableSection::initialize(SectionTableRef SecTable) {
  Size = 0;
  Expected<StringTableSection *> Sec =
      SecTable.getSectionOfType<StringTableSection>(
          Link,
          "Symbol table has link index of " + Twine(Link) +
              " which is not a valid index",
          "Symbol table has link index of " + Twine(Link) +
              " which is not a string table");
  if (!Sec)
    return Sec.takeError();

  setStrTab(*Sec);
  return Error::success();
}

void SymbolTableSection::finalize() {
  uint32_t MaxLocalIndex = 0;
  for (std::unique_ptr<Symbol> &Sym : Symbols) {
    Sym->NameIndex =
        SymbolNames == nullptr ? 0 : SymbolNames->findIndex(Sym->Name);
    if (Sym->Binding == STB_LOCAL)
      MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);
  }
  // Now we need to set the Link and Info fields.
  Link = SymbolNames == nullptr ? 0 : SymbolNames->Index;
  Info = MaxLocalIndex + 1;
}

void SymbolTableSection::prepareForLayout() {
  // Reserve proper amount of space in section index table, so we can
  // layout sections correctly. We will fill the table with correct
  // indexes later in fillShdnxTable.
  if (SectionIndexTable)
    SectionIndexTable->reserve(Symbols.size());

  // Add all of our strings to SymbolNames so that SymbolNames has the right
  // size before layout is decided.
  // If the symbol names section has been removed, don't try to add strings to
  // the table.
  if (SymbolNames != nullptr)
    for (std::unique_ptr<Symbol> &Sym : Symbols)
      SymbolNames->addString(Sym->Name);
}

void SymbolTableSection::fillShndxTable() {
  if (SectionIndexTable == nullptr)
    return;
  // Fill section index table with real section indexes. This function must
  // be called after assignOffsets.
  for (const std::unique_ptr<Symbol> &Sym : Symbols) {
    if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)
      SectionIndexTable->addIndex(Sym->DefinedIn->Index);
    else
      SectionIndexTable->addIndex(SHN_UNDEF);
  }
}

Expected<const Symbol *>
SymbolTableSection::getSymbolByIndex(uint32_t Index) const {
  if (Symbols.size() <= Index)
    return createStringError(errc::invalid_argument,
                             "invalid symbol index: " + Twine(Index));
  return Symbols[Index].get();
}

Expected<Symbol *> SymbolTableSection::getSymbolByIndex(uint32_t Index) {
  Expected<const Symbol *> Sym =
      static_cast<const SymbolTableSection *>(this)->getSymbolByIndex(Index);
  if (!Sym)
    return Sym.takeError();

  return const_cast<Symbol *>(*Sym);
}

template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const SymbolTableSection &Sec) {
  Elf_Sym *Sym = reinterpret_cast<Elf_Sym *>(Out.getBufferStart() + Sec.Offset);
  // Loop though symbols setting each entry of the symbol table.
  for (const std::unique_ptr<Symbol> &Symbol : Sec.Symbols) {
    Sym->st_name = Symbol->NameIndex;
    Sym->st_value = Symbol->Value;
    Sym->st_size = Symbol->Size;
    Sym->st_other = Symbol->Visibility;
    Sym->setBinding(Symbol->Binding);
    Sym->setType(Symbol->Type);
    Sym->st_shndx = Symbol->getShndx();
    ++Sym;
  }
  return Error::success();
}

Error SymbolTableSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error SymbolTableSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

StringRef RelocationSectionBase::getNamePrefix() const {
  switch (Type) {
  case SHT_REL:
    return ".rel";
  case SHT_RELA:
    return ".rela";
  default:
    llvm_unreachable("not a relocation section");
  }
}

Error RelocationSection::removeSectionReferences(
    bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
  if (ToRemove(Symbols)) {
    if (!AllowBrokenLinks)
      return createStringError(
          llvm::errc::invalid_argument,
          "symbol table '%s' cannot be removed because it is "
          "referenced by the relocation section '%s'",
          Symbols->Name.data(), this->Name.data());
    Symbols = nullptr;
  }

  for (const Relocation &R : Relocations) {
    if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||
        !ToRemove(R.RelocSymbol->DefinedIn))
      continue;
    return createStringError(llvm::errc::invalid_argument,
                             "section '%s' cannot be removed: (%s+0x%" PRIx64
                             ") has relocation against symbol '%s'",
                             R.RelocSymbol->DefinedIn->Name.data(),
                             SecToApplyRel->Name.data(), R.Offset,
                             R.RelocSymbol->Name.c_str());
  }

  return Error::success();
}

template <class SymTabType>
Error RelocSectionWithSymtabBase<SymTabType>::initialize(
    SectionTableRef SecTable) {
  if (Link != SHN_UNDEF) {
    Expected<SymTabType *> Sec = SecTable.getSectionOfType<SymTabType>(
        Link,
        "Link field value " + Twine(Link) + " in section " + Name +
            " is invalid",
        "Link field value " + Twine(Link) + " in section " + Name +
            " is not a symbol table");
    if (!Sec)
      return Sec.takeError();

    setSymTab(*Sec);
  }

  if (Info != SHN_UNDEF) {
    Expected<SectionBase *> Sec =
        SecTable.getSection(Info, "Info field value " + Twine(Info) +
                                      " in section " + Name + " is invalid");
    if (!Sec)
      return Sec.takeError();

    setSection(*Sec);
  } else
    setSection(nullptr);

  return Error::success();
}

template <class SymTabType>
void RelocSectionWithSymtabBase<SymTabType>::finalize() {
  this->Link = Symbols ? Symbols->Index : 0;

  if (SecToApplyRel != nullptr)
    this->Info = SecToApplyRel->Index;
}

template <class ELFT>
static void setAddend(Elf_Rel_Impl<ELFT, false> &, uint64_t) {}

template <class ELFT>
static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
  Rela.r_addend = Addend;
}

template <class RelRange, class T>
static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL) {
  for (const auto &Reloc : Relocations) {
    Buf->r_offset = Reloc.Offset;
    setAddend(*Buf, Reloc.Addend);
    Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
                          Reloc.Type, IsMips64EL);
    ++Buf;
  }
}

template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {
  uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
  if (Sec.Type == SHT_REL)
    writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf),
             Sec.getObject().IsMips64EL);
  else
    writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf),
             Sec.getObject().IsMips64EL);
  return Error::success();
}

Error RelocationSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error RelocationSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

Error RelocationSection::removeSymbols(
    function_ref<bool(const Symbol &)> ToRemove) {
  for (const Relocation &Reloc : Relocations)
    if (Reloc.RelocSymbol && ToRemove(*Reloc.RelocSymbol))
      return createStringError(
          llvm::errc::invalid_argument,
          "not stripping symbol '%s' because it is named in a relocation",
          Reloc.RelocSymbol->Name.data());
  return Error::success();
}

void RelocationSection::markSymbols() {
  for (const Relocation &Reloc : Relocations)
    if (Reloc.RelocSymbol)
      Reloc.RelocSymbol->Referenced = true;
}

void RelocationSection::replaceSectionReferences(
    const DenseMap<SectionBase *, SectionBase *> &FromTo) {
  // Update the target section if it was replaced.
  if (SectionBase *To = FromTo.lookup(SecToApplyRel))
    SecToApplyRel = To;
}

Error SectionWriter::visit(const DynamicRelocationSection &Sec) {
  llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
  return Error::success();
}

Error DynamicRelocationSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

Error DynamicRelocationSection::removeSectionReferences(
    bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
  if (ToRemove(Symbols)) {
    if (!AllowBrokenLinks)
      return createStringError(
          llvm::errc::invalid_argument,
          "symbol table '%s' cannot be removed because it is "
          "referenced by the relocation section '%s'",
          Symbols->Name.data(), this->Name.data());
    Symbols = nullptr;
  }

  // SecToApplyRel contains a section referenced by sh_info field. It keeps
  // a section to which the relocation section applies. When we remove any
  // sections we also remove their relocation sections. Since we do that much
  // earlier, this assert should never be triggered.
  assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
  return Error::success();
}

Error Section::removeSectionReferences(
    bool AllowBrokenDependency,
    function_ref<bool(const SectionBase *)> ToRemove) {
  if (ToRemove(LinkSection)) {
    if (!AllowBrokenDependency)
      return createStringError(llvm::errc::invalid_argument,
                               "section '%s' cannot be removed because it is "
                               "referenced by the section '%s'",
                               LinkSection->Name.data(), this->Name.data());
    LinkSection = nullptr;
  }
  return Error::success();
}

void GroupSection::finalize() {
  this->Info = Sym ? Sym->Index : 0;
  this->Link = SymTab ? SymTab->Index : 0;
  // Linker deduplication for GRP_COMDAT is based on Sym->Name. The local/global
  // status is not part of the equation. If Sym is localized, the intention is
  // likely to make the group fully localized. Drop GRP_COMDAT to suppress
  // deduplication. See https://groups.google.com/g/generic-abi/c/2X6mR-s2zoc
  if ((FlagWord & GRP_COMDAT) && Sym && Sym->Binding == STB_LOCAL)
    this->FlagWord &= ~GRP_COMDAT;
}

Error GroupSection::removeSectionReferences(
    bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
  if (ToRemove(SymTab)) {
    if (!AllowBrokenLinks)
      return createStringError(
          llvm::errc::invalid_argument,
          "section '.symtab' cannot be removed because it is "
          "referenced by the group section '%s'",
          this->Name.data());
    SymTab = nullptr;
    Sym = nullptr;
  }
  llvm::erase_if(GroupMembers, ToRemove);
  return Error::success();
}

Error GroupSection::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
  if (ToRemove(*Sym))
    return createStringError(llvm::errc::invalid_argument,
                             "symbol '%s' cannot be removed because it is "
                             "referenced by the section '%s[%d]'",
                             Sym->Name.data(), this->Name.data(), this->Index);
  return Error::success();
}

void GroupSection::markSymbols() {
  if (Sym)
    Sym->Referenced = true;
}

void GroupSection::replaceSectionReferences(
    const DenseMap<SectionBase *, SectionBase *> &FromTo) {
  for (SectionBase *&Sec : GroupMembers)
    if (SectionBase *To = FromTo.lookup(Sec))
      Sec = To;
}

void GroupSection::onRemove() {
  // As the header section of the group is removed, drop the Group flag in its
  // former members.
  for (SectionBase *Sec : GroupMembers)
    Sec->Flags &= ~SHF_GROUP;
}

Error Section::initialize(SectionTableRef SecTable) {
  if (Link == ELF::SHN_UNDEF)
    return Error::success();

  Expected<SectionBase *> Sec =
      SecTable.getSection(Link, "Link field value " + Twine(Link) +
                                    " in section " + Name + " is invalid");
  if (!Sec)
    return Sec.takeError();

  LinkSection = *Sec;

  if (LinkSection->Type == ELF::SHT_SYMTAB) {
    HasSymTabLink = true;
    LinkSection = nullptr;
  }

  return Error::success();
}

void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; }

void GnuDebugLinkSection::init(StringRef File) {
  FileName = sys::path::filename(File);
  // The format for the .gnu_debuglink starts with the file name and is
  // followed by a null terminator and then the CRC32 of the file. The CRC32
  // should be 4 byte aligned. So we add the FileName size, a 1 for the null
  // byte, and then finally push the size to alignment and add 4.
  Size = alignTo(FileName.size() + 1, 4) + 4;
  // The CRC32 will only be aligned if we align the whole section.
  Align = 4;
  Type = OriginalType = ELF::SHT_PROGBITS;
  Name = ".gnu_debuglink";
  // For sections not found in segments, OriginalOffset is only used to
  // establish the order that sections should go in. By using the maximum
  // possible offset we cause this section to wind up at the end.
  OriginalOffset = std::numeric_limits<uint64_t>::max();
}

GnuDebugLinkSection::GnuDebugLinkSection(StringRef File,
                                         uint32_t PrecomputedCRC)
    : FileName(File), CRC32(PrecomputedCRC) {
  init(File);
}

template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {
  unsigned char *Buf =
      reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
  Elf_Word *CRC =
      reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
  *CRC = Sec.CRC32;
  llvm::copy(Sec.FileName, Buf);
  return Error::success();
}

Error GnuDebugLinkSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error GnuDebugLinkSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) {
  ELF::Elf32_Word *Buf =
      reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);
  support::endian::write32<ELFT::TargetEndianness>(Buf++, Sec.FlagWord);
  for (SectionBase *S : Sec.GroupMembers)
    support::endian::write32<ELFT::TargetEndianness>(Buf++, S->Index);
  return Error::success();
}

Error GroupSection::accept(SectionVisitor &Visitor) const {
  return Visitor.visit(*this);
}

Error GroupSection::accept(MutableSectionVisitor &Visitor) {
  return Visitor.visit(*this);
}

// Returns true IFF a section is wholly inside the range of a segment
static bool sectionWithinSegment(const SectionBase &Sec, const Segment &Seg) {
  // If a section is empty it should be treated like it has a size of 1. This is
  // to clarify the case when an empty section lies on a boundary between two
  // segments and ensures that the section "belongs" to the second segment and
  // not the first.
  uint64_t SecSize = Sec.Size ? Sec.Size : 1;

  // Ignore just added sections.
  if (Sec.OriginalOffset == std::numeric_limits<uint64_t>::max())
    return false;

  if (Sec.Type == SHT_NOBITS) {
    if (!(Sec.Flags & SHF_ALLOC))
      return false;

    bool SectionIsTLS = Sec.Flags & SHF_TLS;
    bool SegmentIsTLS = Seg.Type == PT_TLS;
    if (SectionIsTLS != SegmentIsTLS)
      return false;

    return Seg.VAddr <= Sec.Addr &&
           Seg.VAddr + Seg.MemSize >= Sec.Addr + SecSize;
  }

  return Seg.Offset <= Sec.OriginalOffset &&
         Seg.Offset + Seg.FileSize >= Sec.OriginalOffset + SecSize;
}

// Returns true IFF a segment's original offset is inside of another segment's
// range.
static bool segmentOverlapsSegment(const Segment &Child,
                                   const Segment &Parent) {

  return Parent.OriginalOffset <= Child.OriginalOffset &&
         Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset;
}

static bool compareSegmentsByOffset(const Segment *A, const Segment *B) {
  // Any segment without a parent segment should come before a segment
  // that has a parent segment.
  if (A->OriginalOffset < B->OriginalOffset)
    return true;
  if (A->OriginalOffset > B->OriginalOffset)
    return false;
  return A->Index < B->Index;
}

void BasicELFBuilder::initFileHeader() {
  Obj->Flags = 0x0;
  Obj->Type = ET_REL;
  Obj->OSABI = ELFOSABI_NONE;
  Obj->ABIVersion = 0;
  Obj->Entry = 0x0;
  Obj->Machine = EM_NONE;
  Obj->Version = 1;
}

void BasicELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }

StringTableSection *BasicELFBuilder::addStrTab() {
  auto &StrTab = Obj->addSection<StringTableSection>();
  StrTab.Name = ".strtab";

  Obj->SectionNames = &StrTab;
  return &StrTab;
}

SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {
  auto &SymTab = Obj->addSection<SymbolTableSection>();

  SymTab.Name = ".symtab";
  SymTab.Link = StrTab->Index;

  // The symbol table always needs a null symbol
  SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);

  Obj->SymbolTable = &SymTab;
  return &SymTab;
}

Error BasicELFBuilder::initSections() {
  for (SectionBase &Sec : Obj->sections())
    if (Error Err = Sec.initialize(Obj->sections()))
      return Err;

  return Error::success();
}

void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
  auto Data = ArrayRef<uint8_t>(
      reinterpret_cast<const uint8_t *>(MemBuf->getBufferStart()),
      MemBuf->getBufferSize());
  auto &DataSection = Obj->addSection<Section>(Data);
  DataSection.Name = ".data";
  DataSection.Type = ELF::SHT_PROGBITS;
  DataSection.Size = Data.size();
  DataSection.Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE;

  std::string SanitizedFilename = MemBuf->getBufferIdentifier().str();
  std::replace_if(
      std::begin(SanitizedFilename), std::end(SanitizedFilename),
      [](char C) { return !isAlnum(C); }, '_');
  Twine Prefix = Twine("_binary_") + SanitizedFilename;

  SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,
                    /*Value=*/0, NewSymbolVisibility, 0, 0);
  SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection,
                    /*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0);
  SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr,
                    /*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS,
                    0);
}

Expected<std::unique_ptr<Object>> BinaryELFBuilder::build() {
  initFileHeader();
  initHeaderSegment();

  SymbolTableSection *SymTab = addSymTab(addStrTab());
  if (Error Err = initSections())
    return std::move(Err);
  addData(SymTab);

  return std::move(Obj);
}

// Adds sections from IHEX data file. Data should have been
// fully validated by this time.
void IHexELFBuilder::addDataSections() {
  OwnedDataSection *Section = nullptr;
  uint64_t SegmentAddr = 0, BaseAddr = 0;
  uint32_t SecNo = 1;

  for (const IHexRecord &R : Records) {
    uint64_t RecAddr;
    switch (R.Type) {
    case IHexRecord::Data:
      // Ignore empty data records
      if (R.HexData.empty())
        continue;
      RecAddr = R.Addr + SegmentAddr + BaseAddr;
      if (!Section || Section->Addr + Section->Size != RecAddr) {
        // OriginalOffset field is only used to sort sections before layout, so
        // instead of keeping track of real offsets in IHEX file, and as
        // layoutSections() and layoutSectionsForOnlyKeepDebug() use
        // llvm::stable_sort(), we can just set it to a constant (zero).
        Section = &Obj->addSection<OwnedDataSection>(
            ".sec" + std::to_string(SecNo), RecAddr,
            ELF::SHF_ALLOC | ELF::SHF_WRITE, 0);
        SecNo++;
      }
      Section->appendHexData(R.HexData);
      break;
    case IHexRecord::EndOfFile:
      break;
    case IHexRecord::SegmentAddr:
      // 20-bit segment address.
      SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;
      break;
    case IHexRecord::StartAddr80x86:
    case IHexRecord::StartAddr:
      Obj->Entry = checkedGetHex<uint32_t>(R.HexData);
      assert(Obj->Entry <= 0xFFFFFU);
      break;
    case IHexRecord::ExtendedAddr:
      // 16-31 bits of linear base address
      BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;
      break;
    default:
      llvm_unreachable("unknown record type");
    }
  }
}

Expected<std::unique_ptr<Object>> IHexELFBuilder::build() {
  initFileHeader();
  initHeaderSegment();
  StringTableSection *StrTab = addStrTab();
  addSymTab(StrTab);
  if (Error Err = initSections())
    return std::move(Err);
  addDataSections();

  return std::move(Obj);
}

template <class ELFT>
ELFBuilder<ELFT>::ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
                             std::optional<StringRef> ExtractPartition)
    : ElfFile(ElfObj.getELFFile()), Obj(Obj),
      ExtractPartition(ExtractPartition) {
  Obj.IsMips64EL = ElfFile.isMips64EL();
}

template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
  for (Segment &Parent : Obj.segments()) {
    // Every segment will overlap with itself but we don't want a segment to
    // be its own parent so we avoid that situation.
    if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) {
      // We want a canonical "most parental" segment but this requires
      // inspecting the ParentSegment.
      if (compareSegmentsByOffset(&Parent, &Child))
        if (Child.ParentSegment == nullptr ||
            compareSegmentsByOffset(&Parent, Child.ParentSegment)) {
          Child.ParentSegment = &Parent;
        }
    }
  }
}

template <class ELFT> Error ELFBuilder<ELFT>::findEhdrOffset() {
  if (!ExtractPartition)
    return Error::success();

  for (const SectionBase &Sec : Obj.sections()) {
    if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {
      EhdrOffset = Sec.Offset;
      return Error::success();
    }
  }
  return createStringError(errc::invalid_argument,
                           "could not find partition named '" +
                               *ExtractPartition + "'");
}

template <class ELFT>
Error ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {
  uint32_t Index = 0;

  Expected<typename ELFFile<ELFT>::Elf_Phdr_Range> Headers =
      HeadersFile.program_headers();
  if (!Headers)
    return Headers.takeError();

  for (const typename ELFFile<ELFT>::Elf_Phdr &Phdr : *Headers) {
    if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize())
      return createStringError(
          errc::invalid_argument,
          "program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) +
              " and file size 0x" + Twine::utohexstr(Phdr.p_filesz) +
              " goes past the end of the file");

    ArrayRef<uint8_t> Data{HeadersFile.base() + Phdr.p_offset,
                           (size_t)Phdr.p_filesz};
    Segment &Seg = Obj.addSegment(Data);
    Seg.Type = Phdr.p_type;
    Seg.Flags = Phdr.p_flags;
    Seg.OriginalOffset = Phdr.p_offset + EhdrOffset;
    Seg.Offset = Phdr.p_offset + EhdrOffset;
    Seg.VAddr = Phdr.p_vaddr;
    Seg.PAddr = Phdr.p_paddr;
    Seg.FileSize = Phdr.p_filesz;
    Seg.MemSize = Phdr.p_memsz;
    Seg.Align = Phdr.p_align;
    Seg.Index = Index++;
    for (SectionBase &Sec : Obj.sections())
      if (sectionWithinSegment(Sec, Seg)) {
        Seg.addSection(&Sec);
        if (!Sec.ParentSegment || Sec.ParentSegment->Offset > Seg.Offset)
          Sec.ParentSegment = &Seg;
      }
  }

  auto &ElfHdr = Obj.ElfHdrSegment;
  ElfHdr.Index = Index++;
  ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;

  const typename ELFT::Ehdr &Ehdr = HeadersFile.getHeader();
  auto &PrHdr = Obj.ProgramHdrSegment;
  PrHdr.Type = PT_PHDR;
  PrHdr.Flags = 0;
  // The spec requires us to have p_vaddr % p_align == p_offset % p_align.
  // Whereas this works automatically for ElfHdr, here OriginalOffset is
  // always non-zero and to ensure the equation we assign the same value to
  // VAddr as well.
  PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
  PrHdr.PAddr = 0;
  PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
  // The spec requires us to naturally align all the fields.
  PrHdr.Align = sizeof(Elf_Addr);
  PrHdr.Index = Index++;

  // Now we do an O(n^2) loop through the segments in order to match up
  // segments.
  for (Segment &Child : Obj.segments())
    setParentSegment(Child);
  setParentSegment(ElfHdr);
  setParentSegment(PrHdr);

  return Error::success();
}

template <class ELFT>
Error ELFBuilder<ELFT>::initGroupSection(GroupSection *GroupSec) {
  if (GroupSec->Align % sizeof(ELF::Elf32_Word) != 0)
    return createStringError(errc::invalid_argument,
                             "invalid alignment " + Twine(GroupSec->Align) +
                                 " of group section '" + GroupSec->Name + "'");
  SectionTableRef SecTable = Obj.sections();
  if (GroupSec->Link != SHN_UNDEF) {
    auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(
        GroupSec->Link,
        "link field value '" + Twine(GroupSec->Link) + "' in section '" +
            GroupSec->Name + "' is invalid",
        "link field value '" + Twine(GroupSec->Link) + "' in section '" +
            GroupSec->Name + "' is not a symbol table");
    if (!SymTab)
      return SymTab.takeError();

    Expected<Symbol *> Sym = (*SymTab)->getSymbolByIndex(GroupSec->Info);
    if (!Sym)
      return createStringError(errc::invalid_argument,
                               "info field value '" + Twine(GroupSec->Info) +
                                   "' in section '" + GroupSec->Name +
                                   "' is not a valid symbol index");
    GroupSec->setSymTab(*SymTab);
    GroupSec->setSymbol(*Sym);
  }
  if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) ||
      GroupSec->Contents.empty())
    return createStringError(errc::invalid_argument,
                             "the content of the section " + GroupSec->Name +
                                 " is malformed");
  const ELF::Elf32_Word *Word =
      reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data());
  const ELF::Elf32_Word *End =
      Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word);
  GroupSec->setFlagWord(
      support::endian::read32<ELFT::TargetEndianness>(Word++));
  for (; Word != End; ++Word) {
    uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word);
    Expected<SectionBase *> Sec = SecTable.getSection(
        Index, "group member index " + Twine(Index) + " in section '" +
                   GroupSec->Name + "' is invalid");
    if (!Sec)
      return Sec.takeError();

    GroupSec->addMember(*Sec);
  }

  return Error::success();
}

template <class ELFT>
Error ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
  Expected<const Elf_Shdr *> Shdr = ElfFile.getSection(SymTab->Index);
  if (!Shdr)
    return Shdr.takeError();

  Expected<StringRef> StrTabData = ElfFile.getStringTableForSymtab(**Shdr);
  if (!StrTabData)
    return StrTabData.takeError();

  ArrayRef<Elf_Word> ShndxData;

  Expected<typename ELFFile<ELFT>::Elf_Sym_Range> Symbols =
      ElfFile.symbols(*Shdr);
  if (!Symbols)
    return Symbols.takeError();

  for (const typename ELFFile<ELFT>::Elf_Sym &Sym : *Symbols) {
    SectionBase *DefSection = nullptr;

    Expected<StringRef> Name = Sym.getName(*StrTabData);
    if (!Name)
      return Name.takeError();

    if (Sym.st_shndx == SHN_XINDEX) {
      if (SymTab->getShndxTable() == nullptr)
        return createStringError(errc::invalid_argument,
                                 "symbol '" + *Name +
                                     "' has index SHN_XINDEX but no "
                                     "SHT_SYMTAB_SHNDX section exists");
      if (ShndxData.data() == nullptr) {
        Expected<const Elf_Shdr *> ShndxSec =
            ElfFile.getSection(SymTab->getShndxTable()->Index);
        if (!ShndxSec)
          return ShndxSec.takeError();

        Expected<ArrayRef<Elf_Word>> Data =
            ElfFile.template getSectionContentsAsArray<Elf_Word>(**ShndxSec);
        if (!Data)
          return Data.takeError();

        ShndxData = *Data;
        if (ShndxData.size() != Symbols->size())
          return createStringError(
              errc::invalid_argument,
              "symbol section index table does not have the same number of "
              "entries as the symbol table");
      }
      Elf_Word Index = ShndxData[&Sym - Symbols->begin()];
      Expected<SectionBase *> Sec = Obj.sections().getSection(
          Index,
          "symbol '" + *Name + "' has invalid section index " + Twine(Index));
      if (!Sec)
        return Sec.takeError();

      DefSection = *Sec;
    } else if (Sym.st_shndx >= SHN_LORESERVE) {
      if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {
        return createStringError(
            errc::invalid_argument,
            "symbol '" + *Name +
                "' has unsupported value greater than or equal "
                "to SHN_LORESERVE: " +
                Twine(Sym.st_shndx));
      }
    } else if (Sym.st_shndx != SHN_UNDEF) {
      Expected<SectionBase *> Sec = Obj.sections().getSection(
          Sym.st_shndx, "symbol '" + *Name +
                            "' is defined has invalid section index " +
                            Twine(Sym.st_shndx));
      if (!Sec)
        return Sec.takeError();

      DefSection = *Sec;
    }

    SymTab->addSymbol(*Name, Sym.getBinding(), Sym.getType(), DefSection,
                      Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);
  }

  return Error::success();
}

template <class ELFT>
static void getAddend(uint64_t &, const Elf_Rel_Impl<ELFT, false> &) {}

template <class ELFT>
static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {
  ToSet = Rela.r_addend;
}

template <class T>
static Error initRelocations(RelocationSection *Relocs, T RelRange) {
  for (const auto &Rel : RelRange) {
    Relocation ToAdd;
    ToAdd.Offset = Rel.r_offset;
    getAddend(ToAdd.Addend, Rel);
    ToAdd.Type = Rel.getType(Relocs->getObject().IsMips64EL);

    if (uint32_t Sym = Rel.getSymbol(Relocs->getObject().IsMips64EL)) {
      if (!Relocs->getObject().SymbolTable)
        return createStringError(
            errc::invalid_argument,
            "'" + Relocs->Name + "': relocation references symbol with index " +
                Twine(Sym) + ", but there is no symbol table");
      Expected<Symbol *> SymByIndex =
          Relocs->getObject().SymbolTable->getSymbolByIndex(Sym);
      if (!SymByIndex)
        return SymByIndex.takeError();

      ToAdd.RelocSymbol = *SymByIndex;
    }

    Relocs->addRelocation(ToAdd);
  }

  return Error::success();
}

Expected<SectionBase *> SectionTableRef::getSection(uint32_t Index,
                                                    Twine ErrMsg) {
  if (Index == SHN_UNDEF || Index > Sections.size())
    return createStringError(errc::invalid_argument, ErrMsg);
  return Sections[Index - 1].get();
}

template <class T>
Expected<T *> SectionTableRef::getSectionOfType(uint32_t Index,
                                                Twine IndexErrMsg,
                                                Twine TypeErrMsg) {
  Expected<SectionBase *> BaseSec = getSection(Index, IndexErrMsg);
  if (!BaseSec)
    return BaseSec.takeError();

  if (T *Sec = dyn_cast<T>(*BaseSec))
    return Sec;

  return createStringError(errc::invalid_argument, TypeErrMsg);
}

template <class ELFT>
Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
  switch (Shdr.sh_type) {
  case SHT_REL:
  case SHT_RELA:
    if (Shdr.sh_flags & SHF_ALLOC) {
      if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
        return Obj.addSection<DynamicRelocationSection>(*Data);
      else
        return Data.takeError();
    }
    return Obj.addSection<RelocationSection>(Obj);
  case SHT_STRTAB:
    // If a string table is allocated we don't want to mess with it. That would
    // mean altering the memory image. There are no special link types or
    // anything so we can just use a Section.
    if (Shdr.sh_flags & SHF_ALLOC) {
      if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
        return Obj.addSection<Section>(*Data);
      else
        return Data.takeError();
    }
    return Obj.addSection<StringTableSection>();
  case SHT_HASH:
  case SHT_GNU_HASH:
    // Hash tables should refer to SHT_DYNSYM which we're not going to change.
    // Because of this we don't need to mess with the hash tables either.
    if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
      return Obj.addSection<Section>(*Data);
    else
      return Data.takeError();
  case SHT_GROUP:
    if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
      return Obj.addSection<GroupSection>(*Data);
    else
      return Data.takeError();
  case SHT_DYNSYM:
    if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
      return Obj.addSection<DynamicSymbolTableSection>(*Data);
    else
      return Data.takeError();
  case SHT_DYNAMIC:
    if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
      return Obj.addSection<DynamicSection>(*Data);
    else
      return Data.takeError();
  case SHT_SYMTAB: {
    // Multiple SHT_SYMTAB sections are forbidden by the ELF gABI.
    if (Obj.SymbolTable != nullptr)
      return createStringError(llvm::errc::invalid_argument,
                               "found multiple SHT_SYMTAB sections");
    auto &SymTab = Obj.addSection<SymbolTableSection>();
    Obj.SymbolTable = &SymTab;
    return SymTab;
  }
  case SHT_SYMTAB_SHNDX: {
    auto &ShndxSection = Obj.addSection<SectionIndexSection>();
    Obj.SectionIndexTable = &ShndxSection;
    return ShndxSection;
  }
  case SHT_NOBITS:
    return Obj.addSection<Section>(ArrayRef<uint8_t>());
  default: {
    Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr);
    if (!Data)
      return Data.takeError();

    Expected<StringRef> Name = ElfFile.getSectionName(Shdr);
    if (!Name)
      return Name.takeError();

    if (!(Shdr.sh_flags & ELF::SHF_COMPRESSED))
      return Obj.addSection<Section>(*Data);
    auto *Chdr = reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data->data());
    return Obj.addSection<CompressedSection>(CompressedSection(
        *Data, Chdr->ch_type, Chdr->ch_size, Chdr->ch_addralign));
  }
  }
}

template <class ELFT> Error ELFBuilder<ELFT>::readSectionHeaders() {
  uint32_t Index = 0;
  Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
      ElfFile.sections();
  if (!Sections)
    return Sections.takeError();

  for (const typename ELFFile<ELFT>::Elf_Shdr &Shdr : *Sections) {
    if (Index == 0) {
      ++Index;
      continue;
    }
    Expected<SectionBase &> Sec = makeSection(Shdr);
    if (!Sec)
      return Sec.takeError();

    Expected<StringRef> SecName = ElfFile.getSectionName(Shdr);
    if (!SecName)
      return SecName.takeError();
    Sec->Name = SecName->str();
    Sec->Type = Sec->OriginalType = Shdr.sh_type;
    Sec->Flags = Sec->OriginalFlags = Shdr.sh_flags;
    Sec->Addr = Shdr.sh_addr;
    Sec->Offset = Shdr.sh_offset;
    Sec->OriginalOffset = Shdr.sh_offset;
    Sec->Size = Shdr.sh_size;
    Sec->Link = Shdr.sh_link;
    Sec->Info = Shdr.sh_info;
    Sec->Align = Shdr.sh_addralign;
    Sec->EntrySize = Shdr.sh_entsize;
    Sec->Index = Index++;
    Sec->OriginalIndex = Sec->Index;
    Sec->OriginalData = ArrayRef<uint8_t>(
        ElfFile.base() + Shdr.sh_offset,
        (Shdr.sh_type == SHT_NOBITS) ? (size_t)0 : Shdr.sh_size);
  }

  return Error::success();
}

template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
  uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx;
  if (ShstrIndex == SHN_XINDEX) {
    Expected<const Elf_Shdr *> Sec = ElfFile.getSection(0);
    if (!Sec)
      return Sec.takeError();

    ShstrIndex = (*Sec)->sh_link;
  }

  if (ShstrIndex == SHN_UNDEF)
    Obj.HadShdrs = false;
  else {
    Expected<StringTableSection *> Sec =
        Obj.sections().template getSectionOfType<StringTableSection>(
            ShstrIndex,
            "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
                " is invalid",
            "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
                " does not reference a string table");
    if (!Sec)
      return Sec.takeError();

    Obj.SectionNames = *Sec;
  }

  // If a section index table exists we'll need to initialize it before we
  // initialize the symbol table because the symbol table might need to
  // reference it.
  if (Obj.SectionIndexTable)
    if (Error Err = Obj.SectionIndexTable->initialize(Obj.sections()))
      return Err;

  // Now that all of the sections have been added we can fill out some extra
  // details about symbol tables. We need the symbol table filled out before
  // any relocations.
  if (Obj.SymbolTable) {
    if (Error Err = Obj.SymbolTable->initialize(Obj.sections()))
      return Err;
    if (Error Err = initSymbolTable(Obj.SymbolTable))
      return Err;
  } else if (EnsureSymtab) {
    if (Error Err = Obj.addNewSymbolTable())
      return Err;
  }

  // Now that all sections and symbols have been added we can add
  // relocations that reference symbols and set the link and info fields for
  // relocation sections.
  for (SectionBase &Sec : Obj.sections()) {
    if (&Sec == Obj.SymbolTable)
      continue;
    if (Error Err = Sec.initialize(Obj.sections()))
      return Err;
    if (auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
      Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
          ElfFile.sections();
      if (!Sections)
        return Sections.takeError();

      const typename ELFFile<ELFT>::Elf_Shdr *Shdr =
          Sections->begin() + RelSec->Index;
      if (RelSec->Type == SHT_REL) {
        Expected<typename ELFFile<ELFT>::Elf_Rel_Range> Rels =
            ElfFile.rels(*Shdr);
        if (!Rels)
          return Rels.takeError();

        if (Error Err = initRelocations(RelSec, *Rels))
          return Err;
      } else {
        Expected<typename ELFFile<ELFT>::Elf_Rela_Range> Relas =
            ElfFile.relas(*Shdr);
        if (!Relas)
          return Relas.takeError();

        if (Error Err = initRelocations(RelSec, *Relas))
          return Err;
      }
    } else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
      if (Error Err = initGroupSection(GroupSec))
        return Err;
    }
  }

  return Error::success();
}

template <class ELFT> Error ELFBuilder<ELFT>::build(bool EnsureSymtab) {
  if (Error E = readSectionHeaders())
    return E;
  if (Error E = findEhdrOffset())
    return E;

  // The ELFFile whose ELF headers and program headers are copied into the
  // output file. Normally the same as ElfFile, but if we're extracting a
  // loadable partition it will point to the partition's headers.
  Expected<ELFFile<ELFT>> HeadersFile = ELFFile<ELFT>::create(toStringRef(
      {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}));
  if (!HeadersFile)
    return HeadersFile.takeError();

  const typename ELFFile<ELFT>::Elf_Ehdr &Ehdr = HeadersFile->getHeader();
  Obj.Is64Bits = Ehdr.e_ident[EI_CLASS] == ELFCLASS64;
  Obj.OSABI = Ehdr.e_ident[EI_OSABI];
  Obj.ABIVersion = Ehdr.e_ident[EI_ABIVERSION];
  Obj.Type = Ehdr.e_type;
  Obj.Machine = Ehdr.e_machine;
  Obj.Version = Ehdr.e_version;
  Obj.Entry = Ehdr.e_entry;
  Obj.Flags = Ehdr.e_flags;

  if (Error E = readSections(EnsureSymtab))
    return E;
  return readProgramHeaders(*HeadersFile);
}

Writer::~Writer() = default;

Reader::~Reader() = default;

Expected<std::unique_ptr<Object>>
BinaryReader::create(bool /*EnsureSymtab*/) const {
  return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build();
}

Expected<std::vector<IHexRecord>> IHexReader::parse() const {
  SmallVector<StringRef, 16> Lines;
  std::vector<IHexRecord> Records;
  bool HasSections = false;

  MemBuf->getBuffer().split(Lines, '\n');
  Records.reserve(Lines.size());
  for (size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
    StringRef Line = Lines[LineNo - 1].trim();
    if (Line.empty())
      continue;

    Expected<IHexRecord> R = IHexRecord::parse(Line);
    if (!R)
      return parseError(LineNo, R.takeError());
    if (R->Type == IHexRecord::EndOfFile)
      break;
    HasSections |= (R->Type == IHexRecord::Data);
    Records.push_back(*R);
  }
  if (!HasSections)
    return parseError(-1U, "no sections");

  return std::move(Records);
}

Expected<std::unique_ptr<Object>>
IHexReader::create(bool /*EnsureSymtab*/) const {
  Expected<std::vector<IHexRecord>> Records = parse();
  if (!Records)
    return Records.takeError();

  return IHexELFBuilder(*Records).build();
}

Expected<std::unique_ptr<Object>> ELFReader::create(bool EnsureSymtab) const {
  auto Obj = std::make_unique<Object>();
  if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {
    ELFBuilder<ELF32LE> Builder(*O, *Obj, ExtractPartition);
    if (Error Err = Builder.build(EnsureSymtab))
      return std::move(Err);
    return std::move(Obj);
  } else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
    ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);
    if (Error Err = Builder.build(EnsureSymtab))
      return std::move(Err);
    return std::move(Obj);
  } else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
    ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);
    if (Error Err = Builder.build(EnsureSymtab))
      return std::move(Err);
    return std::move(Obj);
  } else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
    ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);
    if (Error Err = Builder.build(EnsureSymtab))
      return std::move(Err);
    return std::move(Obj);
  }
  return createStringError(errc::invalid_argument, "invalid file type");
}

template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
  Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf->getBufferStart());
  std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
  Ehdr.e_ident[EI_MAG0] = 0x7f;
  Ehdr.e_ident[EI_MAG1] = 'E';
  Ehdr.e_ident[EI_MAG2] = 'L';
  Ehdr.e_ident[EI_MAG3] = 'F';
  Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
  Ehdr.e_ident[EI_DATA] =
      ELFT::TargetEndianness == support::big ? ELFDATA2MSB : ELFDATA2LSB;
  Ehdr.e_ident[EI_VERSION] = EV_CURRENT;
  Ehdr.e_ident[EI_OSABI] = Obj.OSABI;
  Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion;

  Ehdr.e_type = Obj.Type;
  Ehdr.e_machine = Obj.Machine;
  Ehdr.e_version = Obj.Version;
  Ehdr.e_entry = Obj.Entry;
  // We have to use the fully-qualified name llvm::size
  // since some compilers complain on ambiguous resolution.
  Ehdr.e_phnum = llvm::size(Obj.segments());
  Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
  Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;
  Ehdr.e_flags = Obj.Flags;
  Ehdr.e_ehsize = sizeof(Elf_Ehdr);
  if (WriteSectionHeaders && Obj.sections().size() != 0) {
    Ehdr.e_shentsize = sizeof(Elf_Shdr);
    Ehdr.e_shoff = Obj.SHOff;
    // """
    // If the number of sections is greater than or equal to
    // SHN_LORESERVE (0xff00), this member has the value zero and the actual
    // number of section header table entries is contained in the sh_size field
    // of the section header at index 0.
    // """
    auto Shnum = Obj.sections().size() + 1;
    if (Shnum >= SHN_LORESERVE)
      Ehdr.e_shnum = 0;
    else
      Ehdr.e_shnum = Shnum;
    // """
    // If the section name string table section index is greater than or equal
    // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)
    // and the actual index of the section name string table section is
    // contained in the sh_link field of the section header at index 0.
    // """
    if (Obj.SectionNames->Index >= SHN_LORESERVE)
      Ehdr.e_shstrndx = SHN_XINDEX;
    else
      Ehdr.e_shstrndx = Obj.SectionNames->Index;
  } else {
    Ehdr.e_shentsize = 0;
    Ehdr.e_shoff = 0;
    Ehdr.e_shnum = 0;
    Ehdr.e_shstrndx = 0;
  }
}

template <class ELFT> void ELFWriter<ELFT>::writePhdrs() {
  for (auto &Seg : Obj.segments())
    writePhdr(Seg);
}

template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {
  // This reference serves to write the dummy section header at the begining
  // of the file. It is not used for anything else
  Elf_Shdr &Shdr =
      *reinterpret_cast<Elf_Shdr *>(Buf->getBufferStart() + Obj.SHOff);
  Shdr.sh_name = 0;
  Shdr.sh_type = SHT_NULL;
  Shdr.sh_flags = 0;
  Shdr.sh_addr = 0;
  Shdr.sh_offset = 0;
  // See writeEhdr for why we do this.
  uint64_t Shnum = Obj.sections().size() + 1;
  if (Shnum >= SHN_LORESERVE)
    Shdr.sh_size = Shnum;
  else
    Shdr.sh_size = 0;
  // See writeEhdr for why we do this.
  if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)
    Shdr.sh_link = Obj.SectionNames->Index;
  else
    Shdr.sh_link = 0;
  Shdr.sh_info = 0;
  Shdr.sh_addralign = 0;
  Shdr.sh_entsize = 0;

  for (SectionBase &Sec : Obj.sections())
    writeShdr(Sec);
}

template <class ELFT> Error ELFWriter<ELFT>::writeSectionData() {
  for (SectionBase &Sec : Obj.sections())
    // Segments are responsible for writing their contents, so only write the
    // section data if the section is not in a segment. Note that this renders
    // sections in segments effectively immutable.
    if (Sec.ParentSegment == nullptr)
      if (Error Err = Sec.accept(*SecWriter))
        return Err;

  return Error::success();
}

template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
  for (Segment &Seg : Obj.segments()) {
    size_t Size = std::min<size_t>(Seg.FileSize, Seg.getContents().size());
    std::memcpy(Buf->getBufferStart() + Seg.Offset, Seg.getContents().data(),
                Size);
  }

  for (auto it : Obj.getUpdatedSections()) {
    SectionBase *Sec = it.first;
    ArrayRef<uint8_t> Data = it.second;

    auto *Parent = Sec->ParentSegment;
    assert(Parent && "This section should've been part of a segment.");
    uint64_t Offset =
        Sec->OriginalOffset - Parent->OriginalOffset + Parent->Offset;
    llvm::copy(Data, Buf->getBufferStart() + Offset);
  }

  // Iterate over removed sections and overwrite their old data with zeroes.
  for (auto &Sec : Obj.removedSections()) {
    Segment *Parent = Sec.ParentSegment;
    if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0)
      continue;
    uint64_t Offset =
        Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset;
    std::memset(Buf->getBufferStart() + Offset, 0, Sec.Size);
  }
}

template <class ELFT>
ELFWriter<ELFT>::ELFWriter(Object &Obj, raw_ostream &Buf, bool WSH,
                           bool OnlyKeepDebug)
    : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
      OnlyKeepDebug(OnlyKeepDebug) {}

Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
  auto It = llvm::find_if(Sections,
                          [&](const SecPtr &Sec) { return Sec->Name == Name; });
  if (It == Sections.end())
    return createStringError(errc::invalid_argument, "section '%s' not found",
                             Name.str().c_str());

  auto *OldSec = It->get();
  if (!OldSec->hasContents())
    return createStringError(
        errc::invalid_argument,
        "section '%s' cannot be updated because it does not have contents",
        Name.str().c_str());

  if (Data.size() > OldSec->Size && OldSec->ParentSegment)
    return createStringError(errc::invalid_argument,
                             "cannot fit data of size %zu into section '%s' "
                             "with size %" PRIu64 " that is part of a segment",
                             Data.size(), Name.str().c_str(), OldSec->Size);

  if (!OldSec->ParentSegment) {
    *It = std::make_unique<OwnedDataSection>(*OldSec, Data);
  } else {
    // The segment writer will be in charge of updating these contents.
    OldSec->Size = Data.size();
    UpdatedSections[OldSec] = Data;
  }

  return Error::success();
}

Error Object::removeSections(
    bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {

  auto Iter = std::stable_partition(
      std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
        if (ToRemove(*Sec))
          return false;
        if (auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {
          if (auto ToRelSec = RelSec->getSection())
            return !ToRemove(*ToRelSec);
        }
        return true;
      });
  if (SymbolTable != nullptr && ToRemove(*SymbolTable))
    SymbolTable = nullptr;
  if (SectionNames != nullptr && ToRemove(*SectionNames))
    SectionNames = nullptr;
  if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))
    SectionIndexTable = nullptr;
  // Now make sure there are no remaining references to the sections that will
  // be removed. Sometimes it is impossible to remove a reference so we emit
  // an error here instead.
  std::unordered_set<const SectionBase *> RemoveSections;
  RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
  for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
    for (auto &Segment : Segments)
      Segment->removeSection(RemoveSec.get());
    RemoveSec->onRemove();
    RemoveSections.insert(RemoveSec.get());
  }

  // For each section that remains alive, we want to remove the dead references.
  // This either might update the content of the section (e.g. remove symbols
  // from symbol table that belongs to removed section) or trigger an error if
  // a live section critically depends on a section being removed somehow
  // (e.g. the removed section is referenced by a relocation).
  for (auto &KeepSec : make_range(std::begin(Sections), Iter)) {
    if (Error E = KeepSec->removeSectionReferences(
            AllowBrokenLinks, [&RemoveSections](const SectionBase *Sec) {
              return RemoveSections.find(Sec) != RemoveSections.end();
            }))
      return E;
  }

  // Transfer removed sections into the Object RemovedSections container for use
  // later.
  std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
  // Now finally get rid of them all together.
  Sections.erase(Iter, std::end(Sections));
  return Error::success();
}

Error Object::replaceSections(
    const DenseMap<SectionBase *, SectionBase *> &FromTo) {
  auto SectionIndexLess = [](const SecPtr &Lhs, const SecPtr &Rhs) {
    return Lhs->Index < Rhs->Index;
  };
  assert(llvm::is_sorted(Sections, SectionIndexLess) &&
         "Sections are expected to be sorted by Index");
  // Set indices of new sections so that they can be later sorted into positions
  // of removed ones.
  for (auto &I : FromTo)
    I.second->Index = I.first->Index;

  // Notify all sections about the replacement.
  for (auto &Sec : Sections)
    Sec->replaceSectionReferences(FromTo);

  if (Error E = removeSections(
          /*AllowBrokenLinks=*/false,
          [=](const SectionBase &Sec) { return FromTo.count(&Sec) > 0; }))
    return E;
  llvm::sort(Sections, SectionIndexLess);
  return Error::success();
}

Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
  if (SymbolTable)
    for (const SecPtr &Sec : Sections)
      if (Error E = Sec->removeSymbols(ToRemove))
        return E;
  return Error::success();
}

Error Object::addNewSymbolTable() {
  assert(!SymbolTable && "Object must not has a SymbolTable.");

  // Reuse an existing SHT_STRTAB section if it exists.
  StringTableSection *StrTab = nullptr;
  for (SectionBase &Sec : sections()) {
    if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
      StrTab = static_cast<StringTableSection *>(&Sec);

      // Prefer a string table that is not the section header string table, if
      // such a table exists.
      if (SectionNames != &Sec)
        break;
    }
  }
  if (!StrTab)
    StrTab = &addSection<StringTableSection>();

  SymbolTableSection &SymTab = addSection<SymbolTableSection>();
  SymTab.Name = ".symtab";
  SymTab.Link = StrTab->Index;
  if (Error Err = SymTab.initialize(sections()))
    return Err;
  SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);

  SymbolTable = &SymTab;

  return Error::success();
}

// Orders segments such that if x = y->ParentSegment then y comes before x.
static void orderSegments(std::vector<Segment *> &Segments) {
  llvm::stable_sort(Segments, compareSegmentsByOffset);
}

// This function finds a consistent layout for a list of segments starting from
// an Offset. It assumes that Segments have been sorted by orderSegments and
// returns an Offset one past the end of the last segment.
static uint64_t layoutSegments(std::vector<Segment *> &Segments,
                               uint64_t Offset) {
  assert(llvm::is_sorted(Segments, compareSegmentsByOffset));
  // The only way a segment should move is if a section was between two
  // segments and that section was removed. If that section isn't in a segment
  // then it's acceptable, but not ideal, to simply move it to after the
  // segments. So we can simply layout segments one after the other accounting
  // for alignment.
  for (Segment *Seg : Segments) {
    // We assume that segments have been ordered by OriginalOffset and Index
    // such that a parent segment will always come before a child segment in
    // OrderedSegments. This means that the Offset of the ParentSegment should
    // already be set and we can set our offset relative to it.
    if (Seg->ParentSegment != nullptr) {
      Segment *Parent = Seg->ParentSegment;
      Seg->Offset =
          Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset;
    } else {
      Seg->Offset =
          alignTo(Offset, std::max<uint64_t>(Seg->Align, 1), Seg->VAddr);
    }
    Offset = std::max(Offset, Seg->Offset + Seg->FileSize);
  }
  return Offset;
}

// This function finds a consistent layout for a list of sections. It assumes
// that the ->ParentSegment of each section has already been laid out. The
// supplied starting Offset is used for the starting offset of any section that
// does not have a ParentSegment. It returns either the offset given if all
// sections had a ParentSegment or an offset one past the last section if there
// was a section that didn't have a ParentSegment.
template <class Range>
static uint64_t layoutSections(Range Sections, uint64_t Offset) {
  // Now the offset of every segment has been set we can assign the offsets
  // of each section. For sections that are covered by a segment we should use
  // the segment's original offset and the section's original offset to compute
  // the offset from the start of the segment. Using the offset from the start
  // of the segment we can assign a new offset to the section. For sections not
  // covered by segments we can just bump Offset to the next valid location.
  // While it is not necessary, layout the sections in the order based on their
  // original offsets to resemble the input file as close as possible.
  std::vector<SectionBase *> OutOfSegmentSections;
  uint32_t Index = 1;
  for (auto &Sec : Sections) {
    Sec.Index = Index++;
    if (Sec.ParentSegment != nullptr) {
      const Segment &Segment = *Sec.ParentSegment;
      Sec.Offset =
          Segment.Offset + (Sec.OriginalOffset - Segment.OriginalOffset);
    } else
      OutOfSegmentSections.push_back(&Sec);
  }

  llvm::stable_sort(OutOfSegmentSections,
                    [](const SectionBase *Lhs, const SectionBase *Rhs) {
                      return Lhs->OriginalOffset < Rhs->OriginalOffset;
                    });
  for (auto *Sec : OutOfSegmentSections) {
    Offset = alignTo(Offset, Sec->Align == 0 ? 1 : Sec->Align);
    Sec->Offset = Offset;
    if (Sec->Type != SHT_NOBITS)
      Offset += Sec->Size;
  }
  return Offset;
}

// Rewrite sh_offset after some sections are changed to SHT_NOBITS and thus
// occupy no space in the file.
static uint64_t layoutSectionsForOnlyKeepDebug(Object &Obj, uint64_t Off) {
  // The layout algorithm requires the sections to be handled in the order of
  // their offsets in the input file, at least inside segments.
  std::vector<SectionBase *> Sections;
  Sections.reserve(Obj.sections().size());
  uint32_t Index = 1;
  for (auto &Sec : Obj.sections()) {
    Sec.Index = Index++;
    Sections.push_back(&Sec);
  }
  llvm::stable_sort(Sections,
                    [](const SectionBase *Lhs, const SectionBase *Rhs) {
                      return Lhs->OriginalOffset < Rhs->OriginalOffset;
                    });

  for (auto *Sec : Sections) {
    auto *FirstSec = Sec->ParentSegment && Sec->ParentSegment->Type == PT_LOAD
                         ? Sec->ParentSegment->firstSection()
                         : nullptr;

    // The first section in a PT_LOAD has to have congruent offset and address
    // modulo the alignment, which usually equals the maximum page size.
    if (FirstSec && FirstSec == Sec)
      Off = alignTo(Off, Sec->ParentSegment->Align, Sec->Addr);

    // sh_offset is not significant for SHT_NOBITS sections, but the congruence
    // rule must be followed if it is the first section in a PT_LOAD. Do not
    // advance Off.
    if (Sec->Type == SHT_NOBITS) {
      Sec->Offset = Off;
      continue;
    }

    if (!FirstSec) {
      // FirstSec being nullptr generally means that Sec does not have the
      // SHF_ALLOC flag.
      Off = Sec->Align ? alignTo(Off, Sec->Align) : Off;
    } else if (FirstSec != Sec) {
      // The offset is relative to the first section in the PT_LOAD segment. Use
      // sh_offset for non-SHF_ALLOC sections.
      Off = Sec->OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;
    }
    Sec->Offset = Off;
    Off += Sec->Size;
  }
  return Off;
}

// Rewrite p_offset and p_filesz of non-PT_PHDR segments after sh_offset values
// have been updated.
static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector<Segment *> &Segments,
                                               uint64_t HdrEnd) {
  uint64_t MaxOffset = 0;
  for (Segment *Seg : Segments) {
    if (Seg->Type == PT_PHDR)
      continue;

    // The segment offset is generally the offset of the first section.
    //
    // For a segment containing no section (see sectionWithinSegment), if it has
    // a parent segment, copy the parent segment's offset field. This works for
    // empty PT_TLS. If no parent segment, use 0: the segment is not useful for
    // debugging anyway.
    const SectionBase *FirstSec = Seg->firstSection();
    uint64_t Offset =
        FirstSec ? FirstSec->Offset
                 : (Seg->ParentSegment ? Seg->ParentSegment->Offset : 0);
    uint64_t FileSize = 0;
    for (const SectionBase *Sec : Seg->Sections) {
      uint64_t Size = Sec->Type == SHT_NOBITS ? 0 : Sec->Size;
      if (Sec->Offset + Size > Offset)
        FileSize = std::max(FileSize, Sec->Offset + Size - Offset);
    }

    // If the segment includes EHDR and program headers, don't make it smaller
    // than the headers.
    if (Seg->Offset < HdrEnd && HdrEnd <= Seg->Offset + Seg->FileSize) {
      FileSize += Offset - Seg->Offset;
      Offset = Seg->Offset;
      FileSize = std::max(FileSize, HdrEnd - Offset);
    }

    Seg->Offset = Offset;
    Seg->FileSize = FileSize;
    MaxOffset = std::max(MaxOffset, Offset + FileSize);
  }
  return MaxOffset;
}

template <class ELFT> void ELFWriter<ELFT>::initEhdrSegment() {
  Segment &ElfHdr = Obj.ElfHdrSegment;
  ElfHdr.Type = PT_PHDR;
  ElfHdr.Flags = 0;
  ElfHdr.VAddr = 0;
  ElfHdr.PAddr = 0;
  ElfHdr.FileSize = ElfHdr.MemSize = sizeof(Elf_Ehdr);
  ElfHdr.Align = 0;
}

template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
  // We need a temporary list of segments that has a special order to it
  // so that we know that anytime ->ParentSegment is set that segment has
  // already had its offset properly set.
  std::vector<Segment *> OrderedSegments;
  for (Segment &Segment : Obj.segments())
    OrderedSegments.push_back(&Segment);
  OrderedSegments.push_back(&Obj.ElfHdrSegment);
  OrderedSegments.push_back(&Obj.ProgramHdrSegment);
  orderSegments(OrderedSegments);

  uint64_t Offset;
  if (OnlyKeepDebug) {
    // For --only-keep-debug, the sections that did not preserve contents were
    // changed to SHT_NOBITS. We now rewrite sh_offset fields of sections, and
    // then rewrite p_offset/p_filesz of program headers.
    uint64_t HdrEnd =
        sizeof(Elf_Ehdr) + llvm::size(Obj.segments()) * sizeof(Elf_Phdr);
    Offset = layoutSectionsForOnlyKeepDebug(Obj, HdrEnd);
    Offset = std::max(Offset,
                      layoutSegmentsForOnlyKeepDebug(OrderedSegments, HdrEnd));
  } else {
    // Offset is used as the start offset of the first segment to be laid out.
    // Since the ELF Header (ElfHdrSegment) must be at the start of the file,
    // we start at offset 0.
    Offset = layoutSegments(OrderedSegments, 0);
    Offset = layoutSections(Obj.sections(), Offset);
  }
  // If we need to write the section header table out then we need to align the
  // Offset so that SHOffset is valid.
  if (WriteSectionHeaders)
    Offset = alignTo(Offset, sizeof(Elf_Addr));
  Obj.SHOff = Offset;
}

template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
  // We already have the section header offset so we can calculate the total
  // size by just adding up the size of each section header.
  if (!WriteSectionHeaders)
    return Obj.SHOff;
  size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
  return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);
}

template <class ELFT> Error ELFWriter<ELFT>::write() {
  // Segment data must be written first, so that the ELF header and program
  // header tables can overwrite it, if covered by a segment.
  writeSegmentData();
  writeEhdr();
  writePhdrs();
  if (Error E = writeSectionData())
    return E;
  if (WriteSectionHeaders)
    writeShdrs();

  // TODO: Implement direct writing to the output stream (without intermediate
  // memory buffer Buf).
  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
  return Error::success();
}

static Error removeUnneededSections(Object &Obj) {
  // We can remove an empty symbol table from non-relocatable objects.
  // Relocatable objects typically have relocation sections whose
  // sh_link field points to .symtab, so we can't remove .symtab
  // even if it is empty.
  if (Obj.isRelocatable() || Obj.SymbolTable == nullptr ||
      !Obj.SymbolTable->empty())
    return Error::success();

  // .strtab can be used for section names. In such a case we shouldn't
  // remove it.
  auto *StrTab = Obj.SymbolTable->getStrTab() == Obj.SectionNames
                     ? nullptr
                     : Obj.SymbolTable->getStrTab();
  return Obj.removeSections(false, [&](const SectionBase &Sec) {
    return &Sec == Obj.SymbolTable || &Sec == StrTab;
  });
}

template <class ELFT> Error ELFWriter<ELFT>::finalize() {
  // It could happen that SectionNames has been removed and yet the user wants
  // a section header table output. We need to throw an error if a user tries
  // to do that.
  if (Obj.SectionNames == nullptr && WriteSectionHeaders)
    return createStringError(llvm::errc::invalid_argument,
                             "cannot write section header table because "
                             "section header string table was removed");

  if (Error E = removeUnneededSections(Obj))
    return E;

  // If the .symtab indices have not been changed, restore the sh_link to
  // .symtab for sections that were linked to .symtab.
  if (Obj.SymbolTable && !Obj.SymbolTable->indicesChanged())
    for (SectionBase &Sec : Obj.sections())
      Sec.restoreSymTabLink(*Obj.SymbolTable);

  // We need to assign indexes before we perform layout because we need to know
  // if we need large indexes or not. We can assign indexes first and check as
  // we go to see if we will actully need large indexes.
  bool NeedsLargeIndexes = false;
  if (Obj.sections().size() >= SHN_LORESERVE) {
    SectionTableRef Sections = Obj.sections();
    // Sections doesn't include the null section header, so account for this
    // when skipping the first N sections.
    NeedsLargeIndexes =
        any_of(drop_begin(Sections, SHN_LORESERVE - 1),
               [](const SectionBase &Sec) { return Sec.HasSymbol; });
    // TODO: handle case where only one section needs the large index table but
    // only needs it because the large index table hasn't been removed yet.
  }

  if (NeedsLargeIndexes) {
    // This means we definitely need to have a section index table but if we
    // already have one then we should use it instead of making a new one.
    if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {
      // Addition of a section to the end does not invalidate the indexes of
      // other sections and assigns the correct index to the new section.
      auto &Shndx = Obj.addSection<SectionIndexSection>();
      Obj.SymbolTable->setShndxTable(&Shndx);
      Shndx.setSymTab(Obj.SymbolTable);
    }
  } else {
    // Since we don't need SectionIndexTable we should remove it and all
    // references to it.
    if (Obj.SectionIndexTable != nullptr) {
      // We do not support sections referring to the section index table.
      if (Error E = Obj.removeSections(false /*AllowBrokenLinks*/,
                                       [this](const SectionBase &Sec) {
                                         return &Sec == Obj.SectionIndexTable;
                                       }))
        return E;
    }
  }

  // Make sure we add the names of all the sections. Importantly this must be
  // done after we decide to add or remove SectionIndexes.
  if (Obj.SectionNames != nullptr)
    for (const SectionBase &Sec : Obj.sections())
      Obj.SectionNames->addString(Sec.Name);

  initEhdrSegment();

  // Before we can prepare for layout the indexes need to be finalized.
  // Also, the output arch may not be the same as the input arch, so fix up
  // size-related fields before doing layout calculations.
  uint64_t Index = 0;
  auto SecSizer = std::make_unique<ELFSectionSizer<ELFT>>();
  for (SectionBase &Sec : Obj.sections()) {
    Sec.Index = Index++;
    if (Error Err = Sec.accept(*SecSizer))
      return Err;
  }

  // The symbol table does not update all other sections on update. For
  // instance, symbol names are not added as new symbols are added. This means
  // that some sections, like .strtab, don't yet have their final size.
  if (Obj.SymbolTable != nullptr)
    Obj.SymbolTable->prepareForLayout();

  // Now that all strings are added we want to finalize string table builders,
  // because that affects section sizes which in turn affects section offsets.
  for (SectionBase &Sec : Obj.sections())
    if (auto StrTab = dyn_cast<StringTableSection>(&Sec))
      StrTab->prepareForLayout();

  assignOffsets();

  // layoutSections could have modified section indexes, so we need
  // to fill the index table after assignOffsets.
  if (Obj.SymbolTable != nullptr)
    Obj.SymbolTable->fillShndxTable();

  // Finally now that all offsets and indexes have been set we can finalize any
  // remaining issues.
  uint64_t Offset = Obj.SHOff + sizeof(Elf_Shdr);
  for (SectionBase &Sec : Obj.sections()) {
    Sec.HeaderOffset = Offset;
    Offset += sizeof(Elf_Shdr);
    if (WriteSectionHeaders)
      Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
    Sec.finalize();
  }

  size_t TotalSize = totalSize();
  Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
  if (!Buf)
    return createStringError(errc::not_enough_memory,
                             "failed to allocate memory buffer of " +
                                 Twine::utohexstr(TotalSize) + " bytes");

  SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(*Buf);
  return Error::success();
}

Error BinaryWriter::write() {
  for (const SectionBase &Sec : Obj.allocSections())
    if (Error Err = Sec.accept(*SecWriter))
      return Err;

  // TODO: Implement direct writing to the output stream (without intermediate
  // memory buffer Buf).
  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
  return Error::success();
}

Error BinaryWriter::finalize() {
  // Compute the section LMA based on its sh_offset and the containing segment's
  // p_offset and p_paddr. Also compute the minimum LMA of all non-empty
  // sections as MinAddr. In the output, the contents between address 0 and
  // MinAddr will be skipped.
  uint64_t MinAddr = UINT64_MAX;
  for (SectionBase &Sec : Obj.allocSections()) {
    if (Sec.ParentSegment != nullptr)
      Sec.Addr =
          Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;
    if (Sec.Type != SHT_NOBITS && Sec.Size > 0)
      MinAddr = std::min(MinAddr, Sec.Addr);
  }

  // Now that every section has been laid out we just need to compute the total
  // file size. This might not be the same as the offset returned by
  // layoutSections, because we want to truncate the last segment to the end of
  // its last non-empty section, to match GNU objcopy's behaviour.
  TotalSize = 0;
  for (SectionBase &Sec : Obj.allocSections())
    if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
      Sec.Offset = Sec.Addr - MinAddr;
      TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
    }

  Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
  if (!Buf)
    return createStringError(errc::not_enough_memory,
                             "failed to allocate memory buffer of " +
                                 Twine::utohexstr(TotalSize) + " bytes");
  SecWriter = std::make_unique<BinarySectionWriter>(*Buf);
  return Error::success();
}

bool IHexWriter::SectionCompare::operator()(const SectionBase *Lhs,
                                            const SectionBase *Rhs) const {
  return (sectionPhysicalAddr(Lhs) & 0xFFFFFFFFU) <
         (sectionPhysicalAddr(Rhs) & 0xFFFFFFFFU);
}

uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
  IHexLineData HexData;
  uint8_t Data[4] = {};
  // We don't write entry point record if entry is zero.
  if (Obj.Entry == 0)
    return 0;

  if (Obj.Entry <= 0xFFFFFU) {
    Data[0] = ((Obj.Entry & 0xF0000U) >> 12) & 0xFF;
    support::endian::write(&Data[2], static_cast<uint16_t>(Obj.Entry),
                           support::big);
    HexData = IHexRecord::getLine(IHexRecord::StartAddr80x86, 0, Data);
  } else {
    support::endian::write(Data, static_cast<uint32_t>(Obj.Entry),
                           support::big);
    HexData = IHexRecord::getLine(IHexRecord::StartAddr, 0, Data);
  }
  memcpy(Buf, HexData.data(), HexData.size());
  return HexData.size();
}

uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
  IHexLineData HexData = IHexRecord::getLine(IHexRecord::EndOfFile, 0, {});
  memcpy(Buf, HexData.data(), HexData.size());
  return HexData.size();
}

Error IHexWriter::write() {
  IHexSectionWriter Writer(*Buf);
  // Write sections.
  for (const SectionBase *Sec : Sections)
    if (Error Err = Sec->accept(Writer))
      return Err;

  uint64_t Offset = Writer.getBufferOffset();
  // Write entry point address.
  Offset += writeEntryPointRecord(
      reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
  // Write EOF.
  Offset += writeEndOfFileRecord(
      reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
  assert(Offset == TotalSize);

  // TODO: Implement direct writing to the output stream (without intermediate
  // memory buffer Buf).
  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
  return Error::success();
}

Error IHexWriter::checkSection(const SectionBase &Sec) {
  uint64_t Addr = sectionPhysicalAddr(&Sec);
  if (addressOverflows32bit(Addr) || addressOverflows32bit(Addr + Sec.Size - 1))
    return createStringError(
        errc::invalid_argument,
        "Section '%s' address range [0x%llx, 0x%llx] is not 32 bit",
        Sec.Name.c_str(), Addr, Addr + Sec.Size - 1);
  return Error::success();
}

Error IHexWriter::finalize() {
  // We can't write 64-bit addresses.
  if (addressOverflows32bit(Obj.Entry))
    return createStringError(errc::invalid_argument,
                             "Entry point address 0x%llx overflows 32 bits",
                             Obj.Entry);

  for (const SectionBase &Sec : Obj.sections())
    if ((Sec.Flags & ELF::SHF_ALLOC) && Sec.Type != ELF::SHT_NOBITS &&
        Sec.Size > 0) {
      if (Error E = checkSection(Sec))
        return E;
      Sections.insert(&Sec);
    }

  std::unique_ptr<WritableMemoryBuffer> EmptyBuffer =
      WritableMemoryBuffer::getNewMemBuffer(0);
  if (!EmptyBuffer)
    return createStringError(errc::not_enough_memory,
                             "failed to allocate memory buffer of 0 bytes");

  IHexSectionWriterBase LengthCalc(*EmptyBuffer);
  for (const SectionBase *Sec : Sections)
    if (Error Err = Sec->accept(LengthCalc))
      return Err;

  // We need space to write section records + StartAddress record
  // (if start adress is not zero) + EndOfFile record.
  TotalSize = LengthCalc.getBufferOffset() +
              (Obj.Entry ? IHexRecord::getLineLength(4) : 0) +
              IHexRecord::getLineLength(0);

  Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
  if (!Buf)
    return createStringError(errc::not_enough_memory,
                             "failed to allocate memory buffer of " +
                                 Twine::utohexstr(TotalSize) + " bytes");

  return Error::success();
}

namespace llvm {
namespace objcopy {
namespace elf {

template class ELFBuilder<ELF64LE>;
template class ELFBuilder<ELF64BE>;
template class ELFBuilder<ELF32LE>;
template class ELFBuilder<ELF32BE>;

template class ELFWriter<ELF64LE>;
template class ELFWriter<ELF64BE>;
template class ELFWriter<ELF32LE>;
template class ELFWriter<ELF32BE>;

} // end namespace elf
} // end namespace objcopy
} // end namespace llvm
