//===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the XCOFFObjectFile class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/XCOFFObjectFile.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/DataExtractor.h"
#include <cstddef>
#include <cstring>

namespace llvm {

using namespace XCOFF;

namespace object {

static const uint8_t FunctionSym = 0x20;
static const uint16_t NoRelMask = 0x0001;
static const size_t SymbolAuxTypeOffset = 17;

// Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
// 'M'. Returns a pointer to the underlying object on success.
template <typename T>
static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
                                     const uint64_t Size = sizeof(T)) {
  uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
  if (Error E = Binary::checkOffset(M, Addr, Size))
    return std::move(E);
  return reinterpret_cast<const T *>(Addr);
}

static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
  return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
                                     Offset);
}

template <typename T> static const T *viewAs(uintptr_t in) {
  return reinterpret_cast<const T *>(in);
}

static StringRef generateXCOFFFixedNameStringRef(const char *Name) {
  auto NulCharPtr =
      static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
  return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
                    : StringRef(Name, XCOFF::NameSize);
}

template <typename T> StringRef XCOFFSectionHeader<T>::getName() const {
  const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
  return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name);
}

template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
  const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
  return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask;
}

template <typename T>
bool XCOFFSectionHeader<T>::isReservedSectionType() const {
  return getSectionType() & SectionFlagsReservedMask;
}

template <typename AddressType>
bool XCOFFRelocation<AddressType>::isRelocationSigned() const {
  return Info & XR_SIGN_INDICATOR_MASK;
}

template <typename AddressType>
bool XCOFFRelocation<AddressType>::isFixupIndicated() const {
  return Info & XR_FIXUP_INDICATOR_MASK;
}

template <typename AddressType>
uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const {
  // The relocation encodes the bit length being relocated minus 1. Add back
  // the 1 to get the actual length being relocated.
  return (Info & XR_BIASED_LENGTH_MASK) + 1;
}

template struct ExceptionSectionEntry<support::ubig32_t>;
template struct ExceptionSectionEntry<support::ubig64_t>;

template <typename T>
Expected<StringRef> getLoaderSecSymNameInStrTbl(const T *LoaderSecHeader,
                                                uint64_t Offset) {
  if (LoaderSecHeader->LengthOfStrTbl > Offset)
    return (reinterpret_cast<const char *>(LoaderSecHeader) +
            LoaderSecHeader->OffsetToStrTbl + Offset);

  return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
                     " in the loader section's string table with size 0x" +
                     Twine::utohexstr(LoaderSecHeader->LengthOfStrTbl) +
                     " is invalid");
}

Expected<StringRef> LoaderSectionSymbolEntry32::getSymbolName(
    const LoaderSectionHeader32 *LoaderSecHeader32) const {
  const NameOffsetInStrTbl *NameInStrTbl =
      reinterpret_cast<const NameOffsetInStrTbl *>(SymbolName);
  if (NameInStrTbl->IsNameInStrTbl != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
    return generateXCOFFFixedNameStringRef(SymbolName);

  return getLoaderSecSymNameInStrTbl(LoaderSecHeader32, NameInStrTbl->Offset);
}

Expected<StringRef> LoaderSectionSymbolEntry64::getSymbolName(
    const LoaderSectionHeader64 *LoaderSecHeader64) const {
  return getLoaderSecSymNameInStrTbl(LoaderSecHeader64, Offset);
}

uintptr_t
XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
                                               uint32_t Distance) {
  return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
}

const XCOFF::SymbolAuxType *
XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
  return viewAs<XCOFF::SymbolAuxType>(
      getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
}

void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
                                          uintptr_t TableAddress) const {
  if (Addr < TableAddress)
    report_fatal_error("Section header outside of section header table.");

  uintptr_t Offset = Addr - TableAddress;
  if (Offset >= getSectionHeaderSize() * getNumberOfSections())
    report_fatal_error("Section header outside of section header table.");

  if (Offset % getSectionHeaderSize() != 0)
    report_fatal_error(
        "Section header pointer does not point to a valid section header.");
}

const XCOFFSectionHeader32 *
XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
#ifndef NDEBUG
  checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
#endif
  return viewAs<XCOFFSectionHeader32>(Ref.p);
}

const XCOFFSectionHeader64 *
XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
#ifndef NDEBUG
  checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
#endif
  return viewAs<XCOFFSectionHeader64>(Ref.p);
}

XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
  assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
#ifndef NDEBUG
  checkSymbolEntryPointer(Ref.p);
#endif
  return XCOFFSymbolRef(Ref, this);
}

const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
  return static_cast<const XCOFFFileHeader32 *>(FileHeader);
}

const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
  return static_cast<const XCOFFFileHeader64 *>(FileHeader);
}

const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const {
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
  return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader);
}

const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const {
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
  return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader);
}

template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
  return static_cast<const T *>(SectionHeaderTable);
}

const XCOFFSectionHeader32 *
XCOFFObjectFile::sectionHeaderTable32() const {
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
  return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
}

const XCOFFSectionHeader64 *
XCOFFObjectFile::sectionHeaderTable64() const {
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
  return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
}

void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
  uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
      Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1);
#ifndef NDEBUG
  // This function is used by basic_symbol_iterator, which allows to
  // point to the end-of-symbol-table address.
  if (NextSymbolAddr != getEndOfSymbolTableAddress())
    checkSymbolEntryPointer(NextSymbolAddr);
#endif
  Symb.p = NextSymbolAddr;
}

Expected<StringRef>
XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
  // The byte offset is relative to the start of the string table.
  // A byte offset value of 0 is a null or zero-length symbol
  // name. A byte offset in the range 1 to 3 (inclusive) points into the length
  // field; as a soft-error recovery mechanism, we treat such cases as having an
  // offset of 0.
  if (Offset < 4)
    return StringRef(nullptr, 0);

  if (StringTable.Data != nullptr && StringTable.Size > Offset)
    return (StringTable.Data + Offset);

  return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
                     " in a string table with size 0x" +
                     Twine::utohexstr(StringTable.Size) + " is invalid");
}

StringRef XCOFFObjectFile::getStringTable() const {
  // If the size is less than or equal to 4, then the string table contains no
  // string data.
  return StringRef(StringTable.Data,
                   StringTable.Size <= 4 ? 0 : StringTable.Size);
}

Expected<StringRef>
XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
  if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
    return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
  return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
}

Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
  return toSymbolRef(Symb).getName();
}

Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
  return toSymbolRef(Symb).getValue();
}

uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
  return toSymbolRef(Symb).getValue();
}

uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
  uint64_t Result = 0;
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
  if (XCOFFSym.isCsectSymbol()) {
    Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
        XCOFFSym.getXCOFFCsectAuxRef();
    if (!CsectAuxRefOrError)
      // TODO: report the error up the stack.
      consumeError(CsectAuxRefOrError.takeError());
    else
      Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2();
  }
  return Result;
}

uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
  uint64_t Result = 0;
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
  if (XCOFFSym.isCsectSymbol()) {
    Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
        XCOFFSym.getXCOFFCsectAuxRef();
    if (!CsectAuxRefOrError)
      // TODO: report the error up the stack.
      consumeError(CsectAuxRefOrError.takeError());
    else {
      XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
      assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM);
      Result = CsectAuxRef.getSectionOrLength();
    }
  }
  return Result;
}

Expected<SymbolRef::Type>
XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);

  if (XCOFFSym.isFunction())
    return SymbolRef::ST_Function;

  if (XCOFF::C_FILE == XCOFFSym.getStorageClass())
    return SymbolRef::ST_File;

  int16_t SecNum = XCOFFSym.getSectionNumber();
  if (SecNum <= 0)
    return SymbolRef::ST_Other;

  Expected<DataRefImpl> SecDRIOrErr =
      getSectionByNum(XCOFFSym.getSectionNumber());

  if (!SecDRIOrErr)
    return SecDRIOrErr.takeError();

  DataRefImpl SecDRI = SecDRIOrErr.get();

  Expected<StringRef> SymNameOrError = XCOFFSym.getName();
  if (SymNameOrError) {
    // The "TOC" symbol is treated as SymbolRef::ST_Other.
    if (SymNameOrError.get() == "TOC")
      return SymbolRef::ST_Other;

    // The symbol for a section name is treated as SymbolRef::ST_Other.
    StringRef SecName;
    if (is64Bit())
      SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName();
    else
      SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName();

    if (SecName == SymNameOrError.get())
      return SymbolRef::ST_Other;
  } else
    return SymNameOrError.takeError();

  if (isSectionData(SecDRI) || isSectionBSS(SecDRI))
    return SymbolRef::ST_Data;

  if (isDebugSection(SecDRI))
    return SymbolRef::ST_Debug;

  return SymbolRef::ST_Other;
}

Expected<section_iterator>
XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
  const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();

  if (isReservedSectionNumber(SectNum))
    return section_end();

  Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
  if (!ExpSec)
    return ExpSec.takeError();

  return section_iterator(SectionRef(ExpSec.get(), this));
}

void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
  const char *Ptr = reinterpret_cast<const char *>(Sec.p);
  Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
}

Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
  return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
}

uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
  // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
  // with MSVC.
  if (is64Bit())
    return toSection64(Sec)->VirtualAddress;

  return toSection32(Sec)->VirtualAddress;
}

uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
  // Section numbers in XCOFF are numbered beginning at 1. A section number of
  // zero is used to indicate that a symbol is being imported or is undefined.
  if (is64Bit())
    return toSection64(Sec) - sectionHeaderTable64() + 1;
  else
    return toSection32(Sec) - sectionHeaderTable32() + 1;
}

uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
  // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
  // with MSVC.
  if (is64Bit())
    return toSection64(Sec)->SectionSize;

  return toSection32(Sec)->SectionSize;
}

Expected<ArrayRef<uint8_t>>
XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
  if (isSectionVirtual(Sec))
    return ArrayRef<uint8_t>();

  uint64_t OffsetToRaw;
  if (is64Bit())
    OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
  else
    OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;

  const uint8_t * ContentStart = base() + OffsetToRaw;
  uint64_t SectionSize = getSectionSize(Sec);
  if (Error E = Binary::checkOffset(
          Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
    return createError(
        toString(std::move(E)) + ": section data with offset 0x" +
        Twine::utohexstr(OffsetToRaw) + " and size 0x" +
        Twine::utohexstr(SectionSize) + " goes past the end of the file");

  return ArrayRef(ContentStart, SectionSize);
}

uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
  uint64_t Result = 0;
  llvm_unreachable("Not yet implemented!");
  return Result;
}

uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const {
  if (is64Bit())
    return toSection64(Sec)->FileOffsetToRawData;

  return toSection32(Sec)->FileOffsetToRawData;
}

Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData(
    XCOFF::SectionTypeFlags SectType) const {
  DataRefImpl DRI = getSectionByType(SectType);

  if (DRI.p == 0) // No section is not an error.
    return 0;

  uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI);
  uint64_t SizeOfSection = getSectionSize(DRI);

  uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset);
  if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) {
    SmallString<32> UnknownType;
    Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">")
        .toVector(UnknownType);
    const char *SectionName = UnknownType.c_str();

    switch (SectType) {
#define ECASE(Value, String)                                                   \
  case XCOFF::Value:                                                           \
    SectionName = String;                                                      \
    break

      ECASE(STYP_PAD, "pad");
      ECASE(STYP_DWARF, "dwarf");
      ECASE(STYP_TEXT, "text");
      ECASE(STYP_DATA, "data");
      ECASE(STYP_BSS, "bss");
      ECASE(STYP_EXCEPT, "expect");
      ECASE(STYP_INFO, "info");
      ECASE(STYP_TDATA, "tdata");
      ECASE(STYP_TBSS, "tbss");
      ECASE(STYP_LOADER, "loader");
      ECASE(STYP_DEBUG, "debug");
      ECASE(STYP_TYPCHK, "typchk");
      ECASE(STYP_OVRFLO, "ovrflo");
#undef ECASE
    }
    return createError(toString(std::move(E)) + ": " + SectionName +
                       " section with offset 0x" +
                       Twine::utohexstr(SectionOffset) + " and size 0x" +
                       Twine::utohexstr(SizeOfSection) +
                       " goes past the end of the file");
  }
  return SectionStart;
}

bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
  return false;
}

bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
  return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
}

bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
  uint32_t Flags = getSectionFlags(Sec);
  return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
}

bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
  uint32_t Flags = getSectionFlags(Sec);
  return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
}

bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const {
  uint32_t Flags = getSectionFlags(Sec);
  return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF);
}

bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
  return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
                   : toSection32(Sec)->FileOffsetToRawData == 0;
}

relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
  DataRefImpl Ret;
  if (is64Bit()) {
    const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
    auto RelocationsOrErr =
        relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
    if (Error E = RelocationsOrErr.takeError()) {
      // TODO: report the error up the stack.
      consumeError(std::move(E));
      return relocation_iterator(RelocationRef());
    }
    Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
  } else {
    const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
    auto RelocationsOrErr =
        relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
    if (Error E = RelocationsOrErr.takeError()) {
      // TODO: report the error up the stack.
      consumeError(std::move(E));
      return relocation_iterator(RelocationRef());
    }
    Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
  }
  return relocation_iterator(RelocationRef(Ret, this));
}

relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
  DataRefImpl Ret;
  if (is64Bit()) {
    const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
    auto RelocationsOrErr =
        relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
    if (Error E = RelocationsOrErr.takeError()) {
      // TODO: report the error up the stack.
      consumeError(std::move(E));
      return relocation_iterator(RelocationRef());
    }
    Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
  } else {
    const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
    auto RelocationsOrErr =
        relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
    if (Error E = RelocationsOrErr.takeError()) {
      // TODO: report the error up the stack.
      consumeError(std::move(E));
      return relocation_iterator(RelocationRef());
    }
    Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
  }
  return relocation_iterator(RelocationRef(Ret, this));
}

void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
  if (is64Bit())
    Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1);
  else
    Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
}

uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
  if (is64Bit()) {
    const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
    const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64();
    const uint64_t RelocAddress = Reloc->VirtualAddress;
    const uint16_t NumberOfSections = getNumberOfSections();
    for (uint16_t I = 0; I < NumberOfSections; ++I) {
      // Find which section this relocation belongs to, and get the
      // relocation offset relative to the start of the section.
      if (Sec64->VirtualAddress <= RelocAddress &&
          RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) {
        return RelocAddress - Sec64->VirtualAddress;
      }
      ++Sec64;
    }
  } else {
    const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
    const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
    const uint32_t RelocAddress = Reloc->VirtualAddress;
    const uint16_t NumberOfSections = getNumberOfSections();
    for (uint16_t I = 0; I < NumberOfSections; ++I) {
      // Find which section this relocation belongs to, and get the
      // relocation offset relative to the start of the section.
      if (Sec32->VirtualAddress <= RelocAddress &&
          RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
        return RelocAddress - Sec32->VirtualAddress;
      }
      ++Sec32;
    }
  }
  return InvalidRelocOffset;
}

symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
  uint32_t Index;
  if (is64Bit()) {
    const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
    Index = Reloc->SymbolIndex;

    if (Index >= getNumberOfSymbolTableEntries64())
      return symbol_end();
  } else {
    const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
    Index = Reloc->SymbolIndex;

    if (Index >= getLogicalNumberOfSymbolTableEntries32())
      return symbol_end();
  }
  DataRefImpl SymDRI;
  SymDRI.p = getSymbolEntryAddressByIndex(Index);
  return symbol_iterator(SymbolRef(SymDRI, this));
}

uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
  if (is64Bit())
    return viewAs<XCOFFRelocation64>(Rel.p)->Type;
  return viewAs<XCOFFRelocation32>(Rel.p)->Type;
}

void XCOFFObjectFile::getRelocationTypeName(
    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
  StringRef Res;
  if (is64Bit()) {
    const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
    Res = XCOFF::getRelocationTypeString(Reloc->Type);
  } else {
    const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
    Res = XCOFF::getRelocationTypeString(Reloc->Type);
  }
  Result.append(Res.begin(), Res.end());
}

Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
  uint32_t Result = SymbolRef::SF_None;

  if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS)
    Result |= SymbolRef::SF_Absolute;

  XCOFF::StorageClass SC = XCOFFSym.getStorageClass();
  if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC)
    Result |= SymbolRef::SF_Global;

  if (XCOFF::C_WEAKEXT == SC)
    Result |= SymbolRef::SF_Weak;

  if (XCOFFSym.isCsectSymbol()) {
    Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr =
        XCOFFSym.getXCOFFCsectAuxRef();
    if (CsectAuxEntOrErr) {
      if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM)
        Result |= SymbolRef::SF_Common;
    } else
      return CsectAuxEntOrErr.takeError();
  }

  if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF)
    Result |= SymbolRef::SF_Undefined;

  // There is no visibility in old 32 bit XCOFF object file interpret.
  if (is64Bit() || (auxiliaryHeader32() && (auxiliaryHeader32()->getVersion() ==
                                            NEW_XCOFF_INTERPRET))) {
    uint16_t SymType = XCOFFSym.getSymbolType();
    if ((SymType & VISIBILITY_MASK) == SYM_V_HIDDEN)
      Result |= SymbolRef::SF_Hidden;

    if ((SymType & VISIBILITY_MASK) == SYM_V_EXPORTED)
      Result |= SymbolRef::SF_Exported;
  }
  return Result;
}

basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
  DataRefImpl SymDRI;
  SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
  return basic_symbol_iterator(SymbolRef(SymDRI, this));
}

basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
  DataRefImpl SymDRI;
  const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
  SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
  return basic_symbol_iterator(SymbolRef(SymDRI, this));
}

section_iterator XCOFFObjectFile::section_begin() const {
  DataRefImpl DRI;
  DRI.p = getSectionHeaderTableAddress();
  return section_iterator(SectionRef(DRI, this));
}

section_iterator XCOFFObjectFile::section_end() const {
  DataRefImpl DRI;
  DRI.p = getWithOffset(getSectionHeaderTableAddress(),
                        getNumberOfSections() * getSectionHeaderSize());
  return section_iterator(SectionRef(DRI, this));
}

uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }

StringRef XCOFFObjectFile::getFileFormatName() const {
  return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
}

Triple::ArchType XCOFFObjectFile::getArch() const {
  return is64Bit() ? Triple::ppc64 : Triple::ppc;
}

Expected<SubtargetFeatures> XCOFFObjectFile::getFeatures() const {
  return SubtargetFeatures();
}

bool XCOFFObjectFile::isRelocatableObject() const {
  if (is64Bit())
    return !(fileHeader64()->Flags & NoRelMask);
  return !(fileHeader32()->Flags & NoRelMask);
}

Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
  // TODO FIXME Should get from auxiliary_header->o_entry when support for the
  // auxiliary_header is added.
  return 0;
}

StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
  return StringSwitch<StringRef>(Name)
      .Case("dwinfo", "debug_info")
      .Case("dwline", "debug_line")
      .Case("dwpbnms", "debug_pubnames")
      .Case("dwpbtyp", "debug_pubtypes")
      .Case("dwarnge", "debug_aranges")
      .Case("dwabrev", "debug_abbrev")
      .Case("dwstr", "debug_str")
      .Case("dwrnges", "debug_ranges")
      .Case("dwloc", "debug_loc")
      .Case("dwframe", "debug_frame")
      .Case("dwmac", "debug_macinfo")
      .Default(Name);
}

size_t XCOFFObjectFile::getFileHeaderSize() const {
  return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
}

size_t XCOFFObjectFile::getSectionHeaderSize() const {
  return is64Bit() ? sizeof(XCOFFSectionHeader64) :
                     sizeof(XCOFFSectionHeader32);
}

bool XCOFFObjectFile::is64Bit() const {
  return Binary::ID_XCOFF64 == getType();
}

Expected<StringRef> XCOFFObjectFile::getRawData(const char *Start,
                                                uint64_t Size,
                                                StringRef Name) const {
  uintptr_t StartPtr = reinterpret_cast<uintptr_t>(Start);
  // TODO: this path is untested.
  if (Error E = Binary::checkOffset(Data, StartPtr, Size))
    return createError(toString(std::move(E)) + ": " + Name.data() +
                       " data with offset 0x" + Twine::utohexstr(StartPtr) +
                       " and size 0x" + Twine::utohexstr(Size) +
                       " goes past the end of the file");
  return StringRef(Start, Size);
}

uint16_t XCOFFObjectFile::getMagic() const {
  return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
}

Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
  if (Num <= 0 || Num > getNumberOfSections())
    return createStringError(object_error::invalid_section_index,
                             "the section index (" + Twine(Num) +
                                 ") is invalid");

  DataRefImpl DRI;
  DRI.p = getWithOffset(getSectionHeaderTableAddress(),
                        getSectionHeaderSize() * (Num - 1));
  return DRI;
}

DataRefImpl
XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const {
  DataRefImpl DRI;
  auto GetSectionAddr = [&](const auto &Sections) -> uintptr_t {
    for (const auto &Sec : Sections)
      if (Sec.getSectionType() == SectType)
        return reinterpret_cast<uintptr_t>(&Sec);
    return uintptr_t(0);
  };
  if (is64Bit())
    DRI.p = GetSectionAddr(sections64());
  else
    DRI.p = GetSectionAddr(sections32());
  return DRI;
}

Expected<StringRef>
XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
  const int16_t SectionNum = SymEntPtr.getSectionNumber();

  switch (SectionNum) {
  case XCOFF::N_DEBUG:
    return "N_DEBUG";
  case XCOFF::N_ABS:
    return "N_ABS";
  case XCOFF::N_UNDEF:
    return "N_UNDEF";
  default:
    Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
    if (SecRef)
      return generateXCOFFFixedNameStringRef(
          getSectionNameInternal(SecRef.get()));
    return SecRef.takeError();
  }
}

unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
  XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this);
  return XCOFFSymRef.getSectionNumber();
}

bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
  return (SectionNumber <= 0 && SectionNumber >= -2);
}

uint16_t XCOFFObjectFile::getNumberOfSections() const {
  return is64Bit() ? fileHeader64()->NumberOfSections
                   : fileHeader32()->NumberOfSections;
}

int32_t XCOFFObjectFile::getTimeStamp() const {
  return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
}

uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
  return is64Bit() ? fileHeader64()->AuxHeaderSize
                   : fileHeader32()->AuxHeaderSize;
}

uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
  return fileHeader32()->SymbolTableOffset;
}

int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
  // As far as symbol table size is concerned, if this field is negative it is
  // to be treated as a 0. However since this field is also used for printing we
  // don't want to truncate any negative values.
  return fileHeader32()->NumberOfSymTableEntries;
}

uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
  return (fileHeader32()->NumberOfSymTableEntries >= 0
              ? fileHeader32()->NumberOfSymTableEntries
              : 0);
}

uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
  return fileHeader64()->SymbolTableOffset;
}

uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
  return fileHeader64()->NumberOfSymTableEntries;
}

uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
  return is64Bit() ? getNumberOfSymbolTableEntries64()
                   : getLogicalNumberOfSymbolTableEntries32();
}

uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
  const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
  return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
                       XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
}

void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
  if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
    report_fatal_error("Symbol table entry is outside of symbol table.");

  if (SymbolEntPtr >= getEndOfSymbolTableAddress())
    report_fatal_error("Symbol table entry is outside of symbol table.");

  ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
                     reinterpret_cast<const char *>(SymbolTblPtr);

  if (Offset % XCOFF::SymbolTableEntrySize != 0)
    report_fatal_error(
        "Symbol table entry position is not valid inside of symbol table.");
}

uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
  return (reinterpret_cast<const char *>(SymbolEntPtr) -
          reinterpret_cast<const char *>(SymbolTblPtr)) /
         XCOFF::SymbolTableEntrySize;
}

uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
  uint64_t Result = 0;
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
  if (XCOFFSym.isCsectSymbol()) {
    Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
        XCOFFSym.getXCOFFCsectAuxRef();
    if (!CsectAuxRefOrError)
      // TODO: report the error up the stack.
      consumeError(CsectAuxRefOrError.takeError());
    else {
      XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
      uint8_t SymType = CsectAuxRef.getSymbolType();
      if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM)
        Result = CsectAuxRef.getSectionOrLength();
    }
  }
  return Result;
}

uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
  return getAdvancedSymbolEntryAddress(
      reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
}

Expected<StringRef>
XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
  const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();

  if (Index >= NumberOfSymTableEntries)
    return createError("symbol index " + Twine(Index) +
                       " exceeds symbol count " +
                       Twine(NumberOfSymTableEntries));

  DataRefImpl SymDRI;
  SymDRI.p = getSymbolEntryAddressByIndex(Index);
  return getSymbolName(SymDRI);
}

uint16_t XCOFFObjectFile::getFlags() const {
  return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
}

const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
  return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
}

uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
  return reinterpret_cast<uintptr_t>(SectionHeaderTable);
}

int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
  return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
}

XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
    : ObjectFile(Type, Object) {
  assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
}

ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
  assert(is64Bit() && "64-bit interface called for non 64-bit file.");
  const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
  return ArrayRef<XCOFFSectionHeader64>(TablePtr,
                                        TablePtr + getNumberOfSections());
}

ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
  assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
  const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
  return ArrayRef<XCOFFSectionHeader32>(TablePtr,
                                        TablePtr + getNumberOfSections());
}

// In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
// section header contains the actual count of relocation entries in the s_paddr
// field. STYP_OVRFLO headers contain the section index of their corresponding
// sections as their raw "NumberOfRelocations" field value.
template <typename T>
Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries(
    const XCOFFSectionHeader<T> &Sec) const {
  const T &Section = static_cast<const T &>(Sec);
  if (is64Bit())
    return Section.NumberOfRelocations;

  uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1;
  if (Section.NumberOfRelocations < XCOFF::RelocOverflow)
    return Section.NumberOfRelocations;
  for (const auto &Sec : sections32()) {
    if (Sec.Flags == XCOFF::STYP_OVRFLO &&
        Sec.NumberOfRelocations == SectionIndex)
      return Sec.PhysicalAddress;
  }
  return errorCodeToError(object_error::parse_failed);
}

template <typename Shdr, typename Reloc>
Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const {
  uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
                                      Sec.FileOffsetToRelocationInfo);
  auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec);
  if (Error E = NumRelocEntriesOrErr.takeError())
    return std::move(E);

  uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
  static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 ||
                 sizeof(Reloc) == XCOFF::RelocationSerializationSize32),
                "Relocation structure is incorrect");
  auto RelocationOrErr =
      getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr),
                       NumRelocEntries * sizeof(Reloc));
  if (!RelocationOrErr)
    return createError(
        toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" +
        Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" +
        Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) +
        " go past the end of the file");

  const Reloc *StartReloc = RelocationOrErr.get();

  return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
}

template <typename ExceptEnt>
Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const {
  assert((is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) ||
         (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32)));

  Expected<uintptr_t> ExceptionSectOrErr =
      getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT);
  if (!ExceptionSectOrErr)
    return ExceptionSectOrErr.takeError();

  DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT);
  if (DRI.p == 0)
    return ArrayRef<ExceptEnt>();

  ExceptEnt *ExceptEntStart =
      reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr);
  return ArrayRef<ExceptEnt>(
      ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt));
}

template Expected<ArrayRef<ExceptionSectionEntry32>>
XCOFFObjectFile::getExceptionEntries() const;
template Expected<ArrayRef<ExceptionSectionEntry64>>
XCOFFObjectFile::getExceptionEntries() const;

Expected<XCOFFStringTable>
XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
  // If there is a string table, then the buffer must contain at least 4 bytes
  // for the string table's size. Not having a string table is not an error.
  if (Error E = Binary::checkOffset(
          Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
    consumeError(std::move(E));
    return XCOFFStringTable{0, nullptr};
  }

  // Read the size out of the buffer.
  uint32_t Size = support::endian::read32be(Obj->base() + Offset);

  // If the size is less then 4, then the string table is just a size and no
  // string data.
  if (Size <= 4)
    return XCOFFStringTable{4, nullptr};

  auto StringTableOrErr =
      getObject<char>(Obj->Data, Obj->base() + Offset, Size);
  if (!StringTableOrErr)
    return createError(toString(StringTableOrErr.takeError()) +
                       ": string table with offset 0x" +
                       Twine::utohexstr(Offset) + " and size 0x" +
                       Twine::utohexstr(Size) +
                       " goes past the end of the file");

  const char *StringTablePtr = StringTableOrErr.get();
  if (StringTablePtr[Size - 1] != '\0')
    return errorCodeToError(object_error::string_table_non_null_end);

  return XCOFFStringTable{Size, StringTablePtr};
}

// This function returns the import file table. Each entry in the import file
// table consists of: "path_name\0base_name\0archive_member_name\0".
Expected<StringRef> XCOFFObjectFile::getImportFileTable() const {
  Expected<uintptr_t> LoaderSectionAddrOrError =
      getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
  if (!LoaderSectionAddrOrError)
    return LoaderSectionAddrOrError.takeError();

  uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
  if (!LoaderSectionAddr)
    return StringRef();

  uint64_t OffsetToImportFileTable = 0;
  uint64_t LengthOfImportFileTable = 0;
  if (is64Bit()) {
    const LoaderSectionHeader64 *LoaderSec64 =
        viewAs<LoaderSectionHeader64>(LoaderSectionAddr);
    OffsetToImportFileTable = LoaderSec64->OffsetToImpid;
    LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl;
  } else {
    const LoaderSectionHeader32 *LoaderSec32 =
        viewAs<LoaderSectionHeader32>(LoaderSectionAddr);
    OffsetToImportFileTable = LoaderSec32->OffsetToImpid;
    LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl;
  }

  auto ImportTableOrErr = getObject<char>(
      Data,
      reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable),
      LengthOfImportFileTable);
  if (!ImportTableOrErr)
    return createError(
        toString(ImportTableOrErr.takeError()) +
        ": import file table with offset 0x" +
        Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
        " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
        " goes past the end of the file");

  const char *ImportTablePtr = ImportTableOrErr.get();
  if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0')
    return createError(
        ": import file name table with offset 0x" +
        Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
        " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
        " must end with a null terminator");

  return StringRef(ImportTablePtr, LengthOfImportFileTable);
}

Expected<std::unique_ptr<XCOFFObjectFile>>
XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
  // Can't use std::make_unique because of the private constructor.
  std::unique_ptr<XCOFFObjectFile> Obj;
  Obj.reset(new XCOFFObjectFile(Type, MBR));

  uint64_t CurOffset = 0;
  const auto *Base = Obj->base();
  MemoryBufferRef Data = Obj->Data;

  // Parse file header.
  auto FileHeaderOrErr =
      getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
  if (Error E = FileHeaderOrErr.takeError())
    return std::move(E);
  Obj->FileHeader = FileHeaderOrErr.get();

  CurOffset += Obj->getFileHeaderSize();

  if (Obj->getOptionalHeaderSize()) {
    auto AuxiliaryHeaderOrErr =
        getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize());
    if (Error E = AuxiliaryHeaderOrErr.takeError())
      return std::move(E);
    Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get();
  }

  CurOffset += Obj->getOptionalHeaderSize();

  // Parse the section header table if it is present.
  if (Obj->getNumberOfSections()) {
    uint64_t SectionHeadersSize =
        Obj->getNumberOfSections() * Obj->getSectionHeaderSize();
    auto SecHeadersOrErr =
        getObject<void>(Data, Base + CurOffset, SectionHeadersSize);
    if (!SecHeadersOrErr)
      return createError(toString(SecHeadersOrErr.takeError()) +
                         ": section headers with offset 0x" +
                         Twine::utohexstr(CurOffset) + " and size 0x" +
                         Twine::utohexstr(SectionHeadersSize) +
                         " go past the end of the file");

    Obj->SectionHeaderTable = SecHeadersOrErr.get();
  }

  const uint32_t NumberOfSymbolTableEntries =
      Obj->getNumberOfSymbolTableEntries();

  // If there is no symbol table we are done parsing the memory buffer.
  if (NumberOfSymbolTableEntries == 0)
    return std::move(Obj);

  // Parse symbol table.
  CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
                             : Obj->getSymbolTableOffset32();
  const uint64_t SymbolTableSize =
      static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
      NumberOfSymbolTableEntries;
  auto SymTableOrErr =
      getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
  if (!SymTableOrErr)
    return createError(
        toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" +
        Twine::utohexstr(CurOffset) + " and size 0x" +
        Twine::utohexstr(SymbolTableSize) + " goes past the end of the file");

  Obj->SymbolTblPtr = SymTableOrErr.get();
  CurOffset += SymbolTableSize;

  // Parse String table.
  Expected<XCOFFStringTable> StringTableOrErr =
      parseStringTable(Obj.get(), CurOffset);
  if (Error E = StringTableOrErr.takeError())
    return std::move(E);
  Obj->StringTable = StringTableOrErr.get();

  return std::move(Obj);
}

Expected<std::unique_ptr<ObjectFile>>
ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
                                  unsigned FileType) {
  return XCOFFObjectFile::create(FileType, MemBufRef);
}

bool XCOFFSymbolRef::isFunction() const {
  if (!isCsectSymbol())
    return false;

  if (getSymbolType() & FunctionSym)
    return true;

  Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
  if (!ExpCsectAuxEnt) {
    // If we could not get the CSECT auxiliary entry, then treat this symbol as
    // if it isn't a function. Consume the error and return `false` to move on.
    consumeError(ExpCsectAuxEnt.takeError());
    return false;
  }

  const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();

  // A function definition should be a label definition.
  // FIXME: This is not necessarily the case when -ffunction-sections is
  // enabled.
  if (!CsectAuxRef.isLabel())
    return false;

  if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR)
    return false;

  const int16_t SectNum = getSectionNumber();
  Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
  if (!SI) {
    // If we could not get the section, then this symbol should not be
    // a function. So consume the error and return `false` to move on.
    consumeError(SI.takeError());
    return false;
  }

  return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
}

bool XCOFFSymbolRef::isCsectSymbol() const {
  XCOFF::StorageClass SC = getStorageClass();
  return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
          SC == XCOFF::C_HIDEXT);
}

Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
  assert(isCsectSymbol() &&
         "Calling csect symbol interface with a non-csect symbol.");

  uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();

  Expected<StringRef> NameOrErr = getName();
  if (auto Err = NameOrErr.takeError())
    return std::move(Err);

  uint32_t SymbolIdx = OwningObjectPtr->getSymbolIndex(getEntryAddress());
  if (!NumberOfAuxEntries) {
    return createError("csect symbol \"" + *NameOrErr + "\" with index " +
                       Twine(SymbolIdx) + " contains no auxiliary entry");
  }

  if (!OwningObjectPtr->is64Bit()) {
    // In XCOFF32, the csect auxilliary entry is always the last auxiliary
    // entry for the symbol.
    uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
        getEntryAddress(), NumberOfAuxEntries);
    return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
  }

  // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
  // We need to iterate through all the auxiliary entries to find it.
  for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
    uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
        getEntryAddress(), Index);
    if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) ==
        XCOFF::SymbolAuxType::AUX_CSECT) {
#ifndef NDEBUG
      OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
#endif
      return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
    }
  }

  return createError(
      "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr +
      "\" with index " + Twine(SymbolIdx));
}

Expected<StringRef> XCOFFSymbolRef::getName() const {
  // A storage class value with the high-order bit on indicates that the name is
  // a symbolic debugger stabstring.
  if (getStorageClass() & 0x80)
    return StringRef("Unimplemented Debug Name");

  if (Entry32) {
    if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
      return generateXCOFFFixedNameStringRef(Entry32->SymbolName);

    return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset);
  }

  return OwningObjectPtr->getStringTableEntry(Entry64->Offset);
}

// Explictly instantiate template classes.
template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
template struct XCOFFSectionHeader<XCOFFSectionHeader64>;

template struct XCOFFRelocation<llvm::support::ubig32_t>;
template struct XCOFFRelocation<llvm::support::ubig64_t>;

template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>>
llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64,
                                           llvm::object::XCOFFRelocation64>(
    llvm::object::XCOFFSectionHeader64 const &) const;
template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>>
llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32,
                                           llvm::object::XCOFFRelocation32>(
    llvm::object::XCOFFSectionHeader32 const &) const;

bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
  if (Bytes.size() < 4)
    return false;

  return support::endian::read32be(Bytes.data()) == 0;
}

#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
#define GETVALUEWITHMASKSHIFT(X, S)                                            \
  ((Data & (TracebackTable::X)) >> (TracebackTable::S))

Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) {
  Error Err = Error::success();
  TBVectorExt TBTVecExt(TBvectorStrRef, Err);
  if (Err)
    return std::move(Err);
  return TBTVecExt;
}

TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) {
  const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
  Data = support::endian::read16be(Ptr);
  uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2);
  unsigned ParmsNum =
      GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift);

  ErrorAsOutParameter EAO(&Err);
  Expected<SmallString<32>> VecParmsTypeOrError =
      parseVectorParmsType(VecParmsTypeValue, ParmsNum);
  if (!VecParmsTypeOrError)
    Err = VecParmsTypeOrError.takeError();
  else
    VecParmsInfo = VecParmsTypeOrError.get();
}

uint8_t TBVectorExt::getNumberOfVRSaved() const {
  return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
}

bool TBVectorExt::isVRSavedOnStack() const {
  return GETVALUEWITHMASK(IsVRSavedOnStackMask);
}

bool TBVectorExt::hasVarArgs() const {
  return GETVALUEWITHMASK(HasVarArgsMask);
}

uint8_t TBVectorExt::getNumberOfVectorParms() const {
  return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
                               NumberOfVectorParmsShift);
}

bool TBVectorExt::hasVMXInstruction() const {
  return GETVALUEWITHMASK(HasVMXInstructionMask);
}
#undef GETVALUEWITHMASK
#undef GETVALUEWITHMASKSHIFT

Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr,
                                                          uint64_t &Size) {
  Error Err = Error::success();
  XCOFFTracebackTable TBT(Ptr, Size, Err);
  if (Err)
    return std::move(Err);
  return TBT;
}

XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
                                         Error &Err)
    : TBPtr(Ptr) {
  ErrorAsOutParameter EAO(&Err);
  DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
                   /*AddressSize=*/0);
  DataExtractor::Cursor Cur(/*Offset=*/0);

  // Skip 8 bytes of mandatory fields.
  DE.getU64(Cur);

  unsigned FixedParmsNum = getNumberOfFixedParms();
  unsigned FloatingParmsNum = getNumberOfFPParms();
  uint32_t ParamsTypeValue = 0;

  // Begin to parse optional fields.
  if (Cur && (FixedParmsNum + FloatingParmsNum) > 0)
    ParamsTypeValue = DE.getU32(Cur);

  if (Cur && hasTraceBackTableOffset())
    TraceBackTableOffset = DE.getU32(Cur);

  if (Cur && isInterruptHandler())
    HandlerMask = DE.getU32(Cur);

  if (Cur && hasControlledStorage()) {
    NumOfCtlAnchors = DE.getU32(Cur);
    if (Cur && NumOfCtlAnchors) {
      SmallVector<uint32_t, 8> Disp;
      Disp.reserve(*NumOfCtlAnchors);
      for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
        Disp.push_back(DE.getU32(Cur));
      if (Cur)
        ControlledStorageInfoDisp = std::move(Disp);
    }
  }

  if (Cur && isFuncNamePresent()) {
    uint16_t FunctionNameLen = DE.getU16(Cur);
    if (Cur)
      FunctionName = DE.getBytes(Cur, FunctionNameLen);
  }

  if (Cur && isAllocaUsed())
    AllocaRegister = DE.getU8(Cur);

  unsigned VectorParmsNum = 0;
  if (Cur && hasVectorInfo()) {
    StringRef VectorExtRef = DE.getBytes(Cur, 6);
    if (Cur) {
      Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef);
      if (!TBVecExtOrErr) {
        Err = TBVecExtOrErr.takeError();
        return;
      }
      VecExt = TBVecExtOrErr.get();
      VectorParmsNum = VecExt->getNumberOfVectorParms();
    }
  }

  // As long as there is no fixed-point or floating-point parameter, this
  // field remains not present even when hasVectorInfo gives true and
  // indicates the presence of vector parameters.
  if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) {
    Expected<SmallString<32>> ParmsTypeOrError =
        hasVectorInfo()
            ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum,
                                        FloatingParmsNum, VectorParmsNum)
            : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum);

    if (!ParmsTypeOrError) {
      Err = ParmsTypeOrError.takeError();
      return;
    }
    ParmsType = ParmsTypeOrError.get();
  }

  if (Cur && hasExtensionTable())
    ExtensionTable = DE.getU8(Cur);

  if (!Cur)
    Err = Cur.takeError();

  Size = Cur.tell();
}

#define GETBITWITHMASK(P, X)                                                   \
  (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
#define GETBITWITHMASKSHIFT(P, X, S)                                           \
  ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >>           \
   (TracebackTable::S))

uint8_t XCOFFTracebackTable::getVersion() const {
  return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
}

uint8_t XCOFFTracebackTable::getLanguageID() const {
  return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
}

bool XCOFFTracebackTable::isGlobalLinkage() const {
  return GETBITWITHMASK(0, IsGlobaLinkageMask);
}

bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
  return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
}

bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
  return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
}

bool XCOFFTracebackTable::isInternalProcedure() const {
  return GETBITWITHMASK(0, IsInternalProcedureMask);
}

bool XCOFFTracebackTable::hasControlledStorage() const {
  return GETBITWITHMASK(0, HasControlledStorageMask);
}

bool XCOFFTracebackTable::isTOCless() const {
  return GETBITWITHMASK(0, IsTOClessMask);
}

bool XCOFFTracebackTable::isFloatingPointPresent() const {
  return GETBITWITHMASK(0, IsFloatingPointPresentMask);
}

bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
  return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
}

bool XCOFFTracebackTable::isInterruptHandler() const {
  return GETBITWITHMASK(0, IsInterruptHandlerMask);
}

bool XCOFFTracebackTable::isFuncNamePresent() const {
  return GETBITWITHMASK(0, IsFunctionNamePresentMask);
}

bool XCOFFTracebackTable::isAllocaUsed() const {
  return GETBITWITHMASK(0, IsAllocaUsedMask);
}

uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
  return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
                             OnConditionDirectiveShift);
}

bool XCOFFTracebackTable::isCRSaved() const {
  return GETBITWITHMASK(0, IsCRSavedMask);
}

bool XCOFFTracebackTable::isLRSaved() const {
  return GETBITWITHMASK(0, IsLRSavedMask);
}

bool XCOFFTracebackTable::isBackChainStored() const {
  return GETBITWITHMASK(4, IsBackChainStoredMask);
}

bool XCOFFTracebackTable::isFixup() const {
  return GETBITWITHMASK(4, IsFixupMask);
}

uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
  return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
}

bool XCOFFTracebackTable::hasExtensionTable() const {
  return GETBITWITHMASK(4, HasExtensionTableMask);
}

bool XCOFFTracebackTable::hasVectorInfo() const {
  return GETBITWITHMASK(4, HasVectorInfoMask);
}

uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
  return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
}

uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
  return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
                             NumberOfFixedParmsShift);
}

uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
  return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
                             NumberOfFloatingPointParmsShift);
}

bool XCOFFTracebackTable::hasParmsOnStack() const {
  return GETBITWITHMASK(4, HasParmsOnStackMask);
}

#undef GETBITWITHMASK
#undef GETBITWITHMASKSHIFT
} // namespace object
} // namespace llvm
