//===- DWARFAcceleratorTable.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 "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"

#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <cstddef>
#include <cstdint>
#include <utility>

using namespace llvm;

namespace {
struct Atom {
  unsigned Value;
};

static raw_ostream &operator<<(raw_ostream &OS, const Atom &A) {
  StringRef Str = dwarf::AtomTypeString(A.Value);
  if (!Str.empty())
    return OS << Str;
  return OS << "DW_ATOM_unknown_" << format("%x", A.Value);
}
} // namespace

static Atom formatAtom(unsigned Atom) { return {Atom}; }

DWARFAcceleratorTable::~DWARFAcceleratorTable() = default;

llvm::Error AppleAcceleratorTable::extract() {
  uint32_t Offset = 0;

  // Check that we can at least read the header.
  if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength) + 4))
    return createStringError(errc::illegal_byte_sequence,
                             "Section too small: cannot read header.");

  Hdr.Magic = AccelSection.getU32(&Offset);
  Hdr.Version = AccelSection.getU16(&Offset);
  Hdr.HashFunction = AccelSection.getU16(&Offset);
  Hdr.BucketCount = AccelSection.getU32(&Offset);
  Hdr.HashCount = AccelSection.getU32(&Offset);
  Hdr.HeaderDataLength = AccelSection.getU32(&Offset);

  // Check that we can read all the hashes and offsets from the
  // section (see SourceLevelDebugging.rst for the structure of the index).
  // We need to substract one because we're checking for an *offset* which is
  // equal to the size for an empty table and hence pointer after the section.
  if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength +
                                  Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1))
    return createStringError(
        errc::illegal_byte_sequence,
        "Section too small: cannot read buckets and hashes.");

  HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
  uint32_t NumAtoms = AccelSection.getU32(&Offset);

  for (unsigned i = 0; i < NumAtoms; ++i) {
    uint16_t AtomType = AccelSection.getU16(&Offset);
    auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset));
    HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
  }

  IsValid = true;
  return Error::success();
}

uint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.BucketCount; }
uint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.HashCount; }
uint32_t AppleAcceleratorTable::getSizeHdr() { return sizeof(Hdr); }
uint32_t AppleAcceleratorTable::getHeaderDataLength() {
  return Hdr.HeaderDataLength;
}

ArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType,
                   AppleAcceleratorTable::HeaderData::Form>>
AppleAcceleratorTable::getAtomsDesc() {
  return HdrData.Atoms;
}

bool AppleAcceleratorTable::validateForms() {
  for (auto Atom : getAtomsDesc()) {
    DWARFFormValue FormValue(Atom.second);
    switch (Atom.first) {
    case dwarf::DW_ATOM_die_offset:
    case dwarf::DW_ATOM_die_tag:
    case dwarf::DW_ATOM_type_flags:
      if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) &&
           !FormValue.isFormClass(DWARFFormValue::FC_Flag)) ||
          FormValue.getForm() == dwarf::DW_FORM_sdata)
        return false;
      break;
    default:
      break;
    }
  }
  return true;
}

std::pair<uint32_t, dwarf::Tag>
AppleAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
  uint32_t DieOffset = dwarf::DW_INVALID_OFFSET;
  dwarf::Tag DieTag = dwarf::DW_TAG_null;
  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};

  for (auto Atom : getAtomsDesc()) {
    DWARFFormValue FormValue(Atom.second);
    FormValue.extractValue(AccelSection, &HashDataOffset, FormParams);
    switch (Atom.first) {
    case dwarf::DW_ATOM_die_offset:
      DieOffset = *FormValue.getAsUnsignedConstant();
      break;
    case dwarf::DW_ATOM_die_tag:
      DieTag = (dwarf::Tag)*FormValue.getAsUnsignedConstant();
      break;
    default:
      break;
    }
  }
  return {DieOffset, DieTag};
}

void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const {
  DictScope HeaderScope(W, "Header");
  W.printHex("Magic", Magic);
  W.printHex("Version", Version);
  W.printHex("Hash function", HashFunction);
  W.printNumber("Bucket count", BucketCount);
  W.printNumber("Hashes count", HashCount);
  W.printNumber("HeaderData length", HeaderDataLength);
}

Optional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset(
    Optional<DWARFFormValue> Value) const {
  if (!Value)
    return None;

  switch (Value->getForm()) {
  case dwarf::DW_FORM_ref1:
  case dwarf::DW_FORM_ref2:
  case dwarf::DW_FORM_ref4:
  case dwarf::DW_FORM_ref8:
  case dwarf::DW_FORM_ref_udata:
    return Value->getRawUValue() + DIEOffsetBase;
  default:
    return Value->getAsSectionOffset();
  }
}

bool AppleAcceleratorTable::dumpName(ScopedPrinter &W,
                                     SmallVectorImpl<DWARFFormValue> &AtomForms,
                                     uint32_t *DataOffset) const {
  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
  uint32_t NameOffset = *DataOffset;
  if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) {
    W.printString("Incorrectly terminated list.");
    return false;
  }
  unsigned StringOffset = AccelSection.getRelocatedValue(4, DataOffset);
  if (!StringOffset)
    return false; // End of list

  DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str());
  W.startLine() << format("String: 0x%08x", StringOffset);
  W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n";

  unsigned NumData = AccelSection.getU32(DataOffset);
  for (unsigned Data = 0; Data < NumData; ++Data) {
    ListScope DataScope(W, ("Data " + Twine(Data)).str());
    unsigned i = 0;
    for (auto &Atom : AtomForms) {
      W.startLine() << format("Atom[%d]: ", i);
      if (Atom.extractValue(AccelSection, DataOffset, FormParams)) {
        Atom.dump(W.getOStream());
        if (Optional<uint64_t> Val = Atom.getAsUnsignedConstant()) {
          StringRef Str = dwarf::AtomValueString(HdrData.Atoms[i].first, *Val);
          if (!Str.empty())
            W.getOStream() << " (" << Str << ")";
        }
      } else
        W.getOStream() << "Error extracting the value";
      W.getOStream() << "\n";
      i++;
    }
  }
  return true; // more entries follow
}

LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const {
  if (!IsValid)
    return;

  ScopedPrinter W(OS);

  Hdr.dump(W);

  W.printNumber("DIE offset base", HdrData.DIEOffsetBase);
  W.printNumber("Number of atoms", uint64_t(HdrData.Atoms.size()));
  SmallVector<DWARFFormValue, 3> AtomForms;
  {
    ListScope AtomsScope(W, "Atoms");
    unsigned i = 0;
    for (const auto &Atom : HdrData.Atoms) {
      DictScope AtomScope(W, ("Atom " + Twine(i++)).str());
      W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';
      W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';
      AtomForms.push_back(DWARFFormValue(Atom.second));
    }
  }

  // Now go through the actual tables and dump them.
  uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
  unsigned HashesBase = Offset + Hdr.BucketCount * 4;
  unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4;

  for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) {
    unsigned Index = AccelSection.getU32(&Offset);

    ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
    if (Index == UINT32_MAX) {
      W.printString("EMPTY");
      continue;
    }

    for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
      unsigned HashOffset = HashesBase + HashIdx*4;
      unsigned OffsetsOffset = OffsetsBase + HashIdx*4;
      uint32_t Hash = AccelSection.getU32(&HashOffset);

      if (Hash % Hdr.BucketCount != Bucket)
        break;

      unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
      ListScope HashScope(W, ("Hash 0x" + Twine::utohexstr(Hash)).str());
      if (!AccelSection.isValidOffset(DataOffset)) {
        W.printString("Invalid section offset");
        continue;
      }
      while (dumpName(W, AtomForms, &DataOffset))
        /*empty*/;
    }
  }
}

AppleAcceleratorTable::Entry::Entry(
    const AppleAcceleratorTable::HeaderData &HdrData)
    : HdrData(&HdrData) {
  Values.reserve(HdrData.Atoms.size());
  for (const auto &Atom : HdrData.Atoms)
    Values.push_back(DWARFFormValue(Atom.second));
}

void AppleAcceleratorTable::Entry::extract(
    const AppleAcceleratorTable &AccelTable, uint32_t *Offset) {

  dwarf::FormParams FormParams = {AccelTable.Hdr.Version, 0,
                                  dwarf::DwarfFormat::DWARF32};
  for (auto &Atom : Values)
    Atom.extractValue(AccelTable.AccelSection, Offset, FormParams);
}

Optional<DWARFFormValue>
AppleAcceleratorTable::Entry::lookup(HeaderData::AtomType Atom) const {
  assert(HdrData && "Dereferencing end iterator?");
  assert(HdrData->Atoms.size() == Values.size());
  for (const auto &Tuple : zip_first(HdrData->Atoms, Values)) {
    if (std::get<0>(Tuple).first == Atom)
      return std::get<1>(Tuple);
  }
  return None;
}

Optional<uint64_t> AppleAcceleratorTable::Entry::getDIESectionOffset() const {
  return HdrData->extractOffset(lookup(dwarf::DW_ATOM_die_offset));
}

Optional<uint64_t> AppleAcceleratorTable::Entry::getCUOffset() const {
  return HdrData->extractOffset(lookup(dwarf::DW_ATOM_cu_offset));
}

Optional<dwarf::Tag> AppleAcceleratorTable::Entry::getTag() const {
  Optional<DWARFFormValue> Tag = lookup(dwarf::DW_ATOM_die_tag);
  if (!Tag)
    return None;
  if (Optional<uint64_t> Value = Tag->getAsUnsignedConstant())
    return dwarf::Tag(*Value);
  return None;
}

AppleAcceleratorTable::ValueIterator::ValueIterator(
    const AppleAcceleratorTable &AccelTable, unsigned Offset)
    : AccelTable(&AccelTable), Current(AccelTable.HdrData), DataOffset(Offset) {
  if (!AccelTable.AccelSection.isValidOffsetForDataOfSize(DataOffset, 4))
    return;

  // Read the first entry.
  NumData = AccelTable.AccelSection.getU32(&DataOffset);
  Next();
}

void AppleAcceleratorTable::ValueIterator::Next() {
  assert(NumData > 0 && "attempted to increment iterator past the end");
  auto &AccelSection = AccelTable->AccelSection;
  if (Data >= NumData ||
      !AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) {
    NumData = 0;
    DataOffset = 0;
    return;
  }
  Current.extract(*AccelTable, &DataOffset);
  ++Data;
}

iterator_range<AppleAcceleratorTable::ValueIterator>
AppleAcceleratorTable::equal_range(StringRef Key) const {
  if (!IsValid)
    return make_range(ValueIterator(), ValueIterator());

  // Find the bucket.
  unsigned HashValue = djbHash(Key);
  unsigned Bucket = HashValue % Hdr.BucketCount;
  unsigned BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength;
  unsigned HashesBase = BucketBase + Hdr.BucketCount * 4;
  unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4;

  unsigned BucketOffset = BucketBase + Bucket * 4;
  unsigned Index = AccelSection.getU32(&BucketOffset);

  // Search through all hashes in the bucket.
  for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
    unsigned HashOffset = HashesBase + HashIdx * 4;
    unsigned OffsetsOffset = OffsetsBase + HashIdx * 4;
    uint32_t Hash = AccelSection.getU32(&HashOffset);

    if (Hash % Hdr.BucketCount != Bucket)
      // We are already in the next bucket.
      break;

    unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
    unsigned StringOffset = AccelSection.getRelocatedValue(4, &DataOffset);
    if (!StringOffset)
      break;

    // Finally, compare the key.
    if (Key == StringSection.getCStr(&StringOffset))
      return make_range({*this, DataOffset}, ValueIterator());
  }
  return make_range(ValueIterator(), ValueIterator());
}

void DWARFDebugNames::Header::dump(ScopedPrinter &W) const {
  DictScope HeaderScope(W, "Header");
  W.printHex("Length", UnitLength);
  W.printNumber("Version", Version);
  W.printHex("Padding", Padding);
  W.printNumber("CU count", CompUnitCount);
  W.printNumber("Local TU count", LocalTypeUnitCount);
  W.printNumber("Foreign TU count", ForeignTypeUnitCount);
  W.printNumber("Bucket count", BucketCount);
  W.printNumber("Name count", NameCount);
  W.printHex("Abbreviations table size", AbbrevTableSize);
  W.startLine() << "Augmentation: '" << AugmentationString << "'\n";
}

llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
                                             uint32_t *Offset) {
  // Check that we can read the fixed-size part.
  if (!AS.isValidOffset(*Offset + sizeof(HeaderPOD) - 1))
    return createStringError(errc::illegal_byte_sequence,
                             "Section too small: cannot read header.");

  UnitLength = AS.getU32(Offset);
  Version = AS.getU16(Offset);
  Padding = AS.getU16(Offset);
  CompUnitCount = AS.getU32(Offset);
  LocalTypeUnitCount = AS.getU32(Offset);
  ForeignTypeUnitCount = AS.getU32(Offset);
  BucketCount = AS.getU32(Offset);
  NameCount = AS.getU32(Offset);
  AbbrevTableSize = AS.getU32(Offset);
  AugmentationStringSize = alignTo(AS.getU32(Offset), 4);

  if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize))
    return createStringError(
        errc::illegal_byte_sequence,
        "Section too small: cannot read header augmentation.");
  AugmentationString.resize(AugmentationStringSize);
  AS.getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()),
           AugmentationStringSize);
  return Error::success();
}

void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const {
  DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str());
  W.startLine() << formatv("Tag: {0}\n", Tag);

  for (const auto &Attr : Attributes)
    W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
}

static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc() {
  return {dwarf::Index(0), dwarf::Form(0)};
}

static bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE) {
  return AE == sentinelAttrEnc();
}

static DWARFDebugNames::Abbrev sentinelAbbrev() {
  return DWARFDebugNames::Abbrev(0, dwarf::Tag(0), {});
}

static bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) {
  return Abbr.Code == 0;
}

DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() {
  return sentinelAbbrev();
}

DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() {
  return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), {});
}

Expected<DWARFDebugNames::AttributeEncoding>
DWARFDebugNames::NameIndex::extractAttributeEncoding(uint32_t *Offset) {
  if (*Offset >= EntriesBase) {
    return createStringError(errc::illegal_byte_sequence,
                             "Incorrectly terminated abbreviation table.");
  }

  uint32_t Index = Section.AccelSection.getULEB128(Offset);
  uint32_t Form = Section.AccelSection.getULEB128(Offset);
  return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form));
}

Expected<std::vector<DWARFDebugNames::AttributeEncoding>>
DWARFDebugNames::NameIndex::extractAttributeEncodings(uint32_t *Offset) {
  std::vector<AttributeEncoding> Result;
  for (;;) {
    auto AttrEncOr = extractAttributeEncoding(Offset);
    if (!AttrEncOr)
      return AttrEncOr.takeError();
    if (isSentinel(*AttrEncOr))
      return std::move(Result);

    Result.emplace_back(*AttrEncOr);
  }
}

Expected<DWARFDebugNames::Abbrev>
DWARFDebugNames::NameIndex::extractAbbrev(uint32_t *Offset) {
  if (*Offset >= EntriesBase) {
    return createStringError(errc::illegal_byte_sequence,
                             "Incorrectly terminated abbreviation table.");
  }

  uint32_t Code = Section.AccelSection.getULEB128(Offset);
  if (Code == 0)
    return sentinelAbbrev();

  uint32_t Tag = Section.AccelSection.getULEB128(Offset);
  auto AttrEncOr = extractAttributeEncodings(Offset);
  if (!AttrEncOr)
    return AttrEncOr.takeError();
  return Abbrev(Code, dwarf::Tag(Tag), std::move(*AttrEncOr));
}

Error DWARFDebugNames::NameIndex::extract() {
  const DWARFDataExtractor &AS = Section.AccelSection;
  uint32_t Offset = Base;
  if (Error E = Hdr.extract(AS, &Offset))
    return E;

  CUsBase = Offset;
  Offset += Hdr.CompUnitCount * 4;
  Offset += Hdr.LocalTypeUnitCount * 4;
  Offset += Hdr.ForeignTypeUnitCount * 8;
  BucketsBase = Offset;
  Offset += Hdr.BucketCount * 4;
  HashesBase = Offset;
  if (Hdr.BucketCount > 0)
    Offset += Hdr.NameCount * 4;
  StringOffsetsBase = Offset;
  Offset += Hdr.NameCount * 4;
  EntryOffsetsBase = Offset;
  Offset += Hdr.NameCount * 4;

  if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
    return createStringError(errc::illegal_byte_sequence,
                             "Section too small: cannot read abbreviations.");

  EntriesBase = Offset + Hdr.AbbrevTableSize;

  for (;;) {
    auto AbbrevOr = extractAbbrev(&Offset);
    if (!AbbrevOr)
      return AbbrevOr.takeError();
    if (isSentinel(*AbbrevOr))
      return Error::success();

    if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
      return createStringError(errc::invalid_argument,
                               "Duplicate abbreviation code.");
  }
}
DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
    : NameIdx(&NameIdx), Abbr(&Abbr) {
  // This merely creates form values. It is up to the caller
  // (NameIndex::getEntry) to populate them.
  Values.reserve(Abbr.Attributes.size());
  for (const auto &Attr : Abbr.Attributes)
    Values.emplace_back(Attr.Form);
}

Optional<DWARFFormValue>
DWARFDebugNames::Entry::lookup(dwarf::Index Index) const {
  assert(Abbr->Attributes.size() == Values.size());
  for (const auto &Tuple : zip_first(Abbr->Attributes, Values)) {
    if (std::get<0>(Tuple).Index == Index)
      return std::get<1>(Tuple);
  }
  return None;
}

Optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
    return Off->getAsReferenceUVal();
  return None;
}

Optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
    return Off->getAsUnsignedConstant();
  // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
  // implicitly refer to the single CU.
  if (NameIdx->getCUCount() == 1)
    return 0;
  return None;
}

Optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
  Optional<uint64_t> Index = getCUIndex();
  if (!Index || *Index >= NameIdx->getCUCount())
    return None;
  return NameIdx->getCUOffset(*Index);
}

void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
  W.printHex("Abbrev", Abbr->Code);
  W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
  assert(Abbr->Attributes.size() == Values.size());
  for (const auto &Tuple : zip_first(Abbr->Attributes, Values)) {
    W.startLine() << formatv("{0}: ", std::get<0>(Tuple).Index);
    std::get<1>(Tuple).dump(W.getOStream());
    W.getOStream() << '\n';
  }
}

char DWARFDebugNames::SentinelError::ID;
std::error_code DWARFDebugNames::SentinelError::convertToErrorCode() const {
  return inconvertibleErrorCode();
}

uint32_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const {
  assert(CU < Hdr.CompUnitCount);
  uint32_t Offset = CUsBase + 4 * CU;
  return Section.AccelSection.getRelocatedValue(4, &Offset);
}

uint32_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const {
  assert(TU < Hdr.LocalTypeUnitCount);
  uint32_t Offset = CUsBase + Hdr.CompUnitCount * 4;
  return Section.AccelSection.getRelocatedValue(4, &Offset);
}

uint64_t DWARFDebugNames::NameIndex::getForeignTUSignature(uint32_t TU) const {
  assert(TU < Hdr.ForeignTypeUnitCount);
  uint32_t Offset = CUsBase + (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) * 4;
  return Section.AccelSection.getU64(&Offset);
}

Expected<DWARFDebugNames::Entry>
DWARFDebugNames::NameIndex::getEntry(uint32_t *Offset) const {
  const DWARFDataExtractor &AS = Section.AccelSection;
  if (!AS.isValidOffset(*Offset))
    return createStringError(errc::illegal_byte_sequence,
                             "Incorrectly terminated entry list.");

  uint32_t AbbrevCode = AS.getULEB128(Offset);
  if (AbbrevCode == 0)
    return make_error<SentinelError>();

  const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
  if (AbbrevIt == Abbrevs.end())
    return createStringError(errc::invalid_argument, "Invalid abbreviation.");

  Entry E(*this, *AbbrevIt);

  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
  for (auto &Value : E.Values) {
    if (!Value.extractValue(AS, Offset, FormParams))
      return createStringError(errc::io_error,
                               "Error extracting index attribute values.");
  }
  return std::move(E);
}

DWARFDebugNames::NameTableEntry
DWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const {
  assert(0 < Index && Index <= Hdr.NameCount);
  uint32_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1);
  uint32_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1);
  const DWARFDataExtractor &AS = Section.AccelSection;

  uint32_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset);
  uint32_t EntryOffset = AS.getU32(&EntryOffsetOffset);
  EntryOffset += EntriesBase;
  return {Section.StringSection, Index, StringOffset, EntryOffset};
}

uint32_t
DWARFDebugNames::NameIndex::getBucketArrayEntry(uint32_t Bucket) const {
  assert(Bucket < Hdr.BucketCount);
  uint32_t BucketOffset = BucketsBase + 4 * Bucket;
  return Section.AccelSection.getU32(&BucketOffset);
}

uint32_t DWARFDebugNames::NameIndex::getHashArrayEntry(uint32_t Index) const {
  assert(0 < Index && Index <= Hdr.NameCount);
  uint32_t HashOffset = HashesBase + 4 * (Index - 1);
  return Section.AccelSection.getU32(&HashOffset);
}

// Returns true if we should continue scanning for entries, false if this is the
// last (sentinel) entry). In case of a parsing error we also return false, as
// it's not possible to recover this entry list (but the other lists may still
// parse OK).
bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
                                           uint32_t *Offset) const {
  uint32_t EntryId = *Offset;
  auto EntryOr = getEntry(Offset);
  if (!EntryOr) {
    handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
                    [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
    return false;
  }

  DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
  EntryOr->dump(W);
  return true;
}

void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
                                          const NameTableEntry &NTE,
                                          Optional<uint32_t> Hash) const {
  DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
  if (Hash)
    W.printHex("Hash", *Hash);

  W.startLine() << format("String: 0x%08x", NTE.getStringOffset());
  W.getOStream() << " \"" << NTE.getString() << "\"\n";

  uint32_t EntryOffset = NTE.getEntryOffset();
  while (dumpEntry(W, &EntryOffset))
    /*empty*/;
}

void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
  ListScope CUScope(W, "Compilation Unit offsets");
  for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
    W.startLine() << format("CU[%u]: 0x%08x\n", CU, getCUOffset(CU));
}

void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
  if (Hdr.LocalTypeUnitCount == 0)
    return;

  ListScope TUScope(W, "Local Type Unit offsets");
  for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
    W.startLine() << format("LocalTU[%u]: 0x%08x\n", TU, getLocalTUOffset(TU));
}

void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
  if (Hdr.ForeignTypeUnitCount == 0)
    return;

  ListScope TUScope(W, "Foreign Type Unit signatures");
  for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
    W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,
                            getForeignTUSignature(TU));
  }
}

void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
  ListScope AbbrevsScope(W, "Abbreviations");
  for (const auto &Abbr : Abbrevs)
    Abbr.dump(W);
}

void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
                                            uint32_t Bucket) const {
  ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
  uint32_t Index = getBucketArrayEntry(Bucket);
  if (Index == 0) {
    W.printString("EMPTY");
    return;
  }
  if (Index > Hdr.NameCount) {
    W.printString("Name index is invalid");
    return;
  }

  for (; Index <= Hdr.NameCount; ++Index) {
    uint32_t Hash = getHashArrayEntry(Index);
    if (Hash % Hdr.BucketCount != Bucket)
      break;

    dumpName(W, getNameTableEntry(Index), Hash);
  }
}

LLVM_DUMP_METHOD void DWARFDebugNames::NameIndex::dump(ScopedPrinter &W) const {
  DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
  Hdr.dump(W);
  dumpCUs(W);
  dumpLocalTUs(W);
  dumpForeignTUs(W);
  dumpAbbreviations(W);

  if (Hdr.BucketCount > 0) {
    for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
      dumpBucket(W, Bucket);
    return;
  }

  W.startLine() << "Hash table not present\n";
  for (NameTableEntry NTE : *this)
    dumpName(W, NTE, None);
}

llvm::Error DWARFDebugNames::extract() {
  uint32_t Offset = 0;
  while (AccelSection.isValidOffset(Offset)) {
    NameIndex Next(*this, Offset);
    if (llvm::Error E = Next.extract())
      return E;
    Offset = Next.getNextUnitOffset();
    NameIndices.push_back(std::move(Next));
  }
  return Error::success();
}

iterator_range<DWARFDebugNames::ValueIterator>
DWARFDebugNames::NameIndex::equal_range(StringRef Key) const {
  return make_range(ValueIterator(*this, Key), ValueIterator());
}

LLVM_DUMP_METHOD void DWARFDebugNames::dump(raw_ostream &OS) const {
  ScopedPrinter W(OS);
  for (const NameIndex &NI : NameIndices)
    NI.dump(W);
}

Optional<uint32_t>
DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
  const Header &Hdr = CurrentIndex->Hdr;
  if (Hdr.BucketCount == 0) {
    // No Hash Table, We need to search through all names in the Name Index.
    for (NameTableEntry NTE : *CurrentIndex) {
      if (NTE.getString() == Key)
        return NTE.getEntryOffset();
    }
    return None;
  }

  // The Name Index has a Hash Table, so use that to speed up the search.
  // Compute the Key Hash, if it has not been done already.
  if (!Hash)
    Hash = caseFoldingDjbHash(Key);
  uint32_t Bucket = *Hash % Hdr.BucketCount;
  uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
  if (Index == 0)
    return None; // Empty bucket

  for (; Index <= Hdr.NameCount; ++Index) {
    uint32_t Hash = CurrentIndex->getHashArrayEntry(Index);
    if (Hash % Hdr.BucketCount != Bucket)
      return None; // End of bucket

    NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
    if (NTE.getString() == Key)
      return NTE.getEntryOffset();
  }
  return None;
}

bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
  auto EntryOr = CurrentIndex->getEntry(&DataOffset);
  if (!EntryOr) {
    consumeError(EntryOr.takeError());
    return false;
  }
  CurrentEntry = std::move(*EntryOr);
  return true;
}

bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
  Optional<uint32_t> Offset = findEntryOffsetInCurrentIndex();
  if (!Offset)
    return false;
  DataOffset = *Offset;
  return getEntryAtCurrentOffset();
}

void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
  for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
       CurrentIndex != End; ++CurrentIndex) {
    if (findInCurrentIndex())
      return;
  }
  setEnd();
}

void DWARFDebugNames::ValueIterator::next() {
  assert(CurrentIndex && "Incrementing an end() iterator?");

  // First try the next entry in the current Index.
  if (getEntryAtCurrentOffset())
    return;

  // If we're a local iterator or we have reached the last Index, we're done.
  if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
    setEnd();
    return;
  }

  // Otherwise, try the next index.
  ++CurrentIndex;
  searchFromStartOfCurrentIndex();
}

DWARFDebugNames::ValueIterator::ValueIterator(const DWARFDebugNames &AccelTable,
                                              StringRef Key)
    : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false), Key(Key) {
  searchFromStartOfCurrentIndex();
}

DWARFDebugNames::ValueIterator::ValueIterator(
    const DWARFDebugNames::NameIndex &NI, StringRef Key)
    : CurrentIndex(&NI), IsLocal(true), Key(Key) {
  if (!findInCurrentIndex())
    setEnd();
}

iterator_range<DWARFDebugNames::ValueIterator>
DWARFDebugNames::equal_range(StringRef Key) const {
  if (NameIndices.empty())
    return make_range(ValueIterator(), ValueIterator());
  return make_range(ValueIterator(*this, Key), ValueIterator());
}

const DWARFDebugNames::NameIndex *
DWARFDebugNames::getCUNameIndex(uint32_t CUOffset) {
  if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) {
    for (const auto &NI : *this) {
      for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
        CUToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
    }
  }
  return CUToNameIndex.lookup(CUOffset);
}
