1321369Sdim//===- DWARFAcceleratorTable.cpp ------------------------------------------===//
2283625Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6283625Sdim//
7283625Sdim//===----------------------------------------------------------------------===//
8283625Sdim
9283625Sdim#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
10321369Sdim
11321369Sdim#include "llvm/ADT/SmallVector.h"
12321369Sdim#include "llvm/BinaryFormat/Dwarf.h"
13321369Sdim#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
14321369Sdim#include "llvm/Support/Compiler.h"
15341825Sdim#include "llvm/Support/DJB.h"
16344779Sdim#include "llvm/Support/Errc.h"
17283625Sdim#include "llvm/Support/Format.h"
18341825Sdim#include "llvm/Support/FormatVariadic.h"
19341825Sdim#include "llvm/Support/ScopedPrinter.h"
20283625Sdim#include "llvm/Support/raw_ostream.h"
21321369Sdim#include <cstddef>
22321369Sdim#include <cstdint>
23321369Sdim#include <utility>
24283625Sdim
25321369Sdimusing namespace llvm;
26283625Sdim
27341825Sdimnamespace {
28341825Sdimstruct Atom {
29341825Sdim  unsigned Value;
30341825Sdim};
31341825Sdim
32341825Sdimstatic raw_ostream &operator<<(raw_ostream &OS, const Atom &A) {
33341825Sdim  StringRef Str = dwarf::AtomTypeString(A.Value);
34341825Sdim  if (!Str.empty())
35341825Sdim    return OS << Str;
36341825Sdim  return OS << "DW_ATOM_unknown_" << format("%x", A.Value);
37341825Sdim}
38341825Sdim} // namespace
39341825Sdim
40341825Sdimstatic Atom formatAtom(unsigned Atom) { return {Atom}; }
41341825Sdim
42341825SdimDWARFAcceleratorTable::~DWARFAcceleratorTable() = default;
43341825Sdim
44353358SdimError AppleAcceleratorTable::extract() {
45360784Sdim  uint64_t Offset = 0;
46283625Sdim
47283625Sdim  // Check that we can at least read the header.
48344779Sdim  if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength) + 4))
49344779Sdim    return createStringError(errc::illegal_byte_sequence,
50344779Sdim                             "Section too small: cannot read header.");
51283625Sdim
52283625Sdim  Hdr.Magic = AccelSection.getU32(&Offset);
53283625Sdim  Hdr.Version = AccelSection.getU16(&Offset);
54283625Sdim  Hdr.HashFunction = AccelSection.getU16(&Offset);
55341825Sdim  Hdr.BucketCount = AccelSection.getU32(&Offset);
56341825Sdim  Hdr.HashCount = AccelSection.getU32(&Offset);
57283625Sdim  Hdr.HeaderDataLength = AccelSection.getU32(&Offset);
58283625Sdim
59283625Sdim  // Check that we can read all the hashes and offsets from the
60283625Sdim  // section (see SourceLevelDebugging.rst for the structure of the index).
61327952Sdim  // We need to substract one because we're checking for an *offset* which is
62327952Sdim  // equal to the size for an empty table and hence pointer after the section.
63283625Sdim  if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength +
64341825Sdim                                  Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1))
65344779Sdim    return createStringError(
66344779Sdim        errc::illegal_byte_sequence,
67344779Sdim        "Section too small: cannot read buckets and hashes.");
68283625Sdim
69283625Sdim  HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
70283625Sdim  uint32_t NumAtoms = AccelSection.getU32(&Offset);
71283625Sdim
72283625Sdim  for (unsigned i = 0; i < NumAtoms; ++i) {
73283625Sdim    uint16_t AtomType = AccelSection.getU16(&Offset);
74314564Sdim    auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset));
75283625Sdim    HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
76283625Sdim  }
77283625Sdim
78327952Sdim  IsValid = true;
79327952Sdim  return Error::success();
80283625Sdim}
81283625Sdim
82341825Sdimuint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.BucketCount; }
83341825Sdimuint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.HashCount; }
84341825Sdimuint32_t AppleAcceleratorTable::getSizeHdr() { return sizeof(Hdr); }
85341825Sdimuint32_t AppleAcceleratorTable::getHeaderDataLength() {
86321369Sdim  return Hdr.HeaderDataLength;
87321369Sdim}
88321369Sdim
89341825SdimArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType,
90341825Sdim                   AppleAcceleratorTable::HeaderData::Form>>
91341825SdimAppleAcceleratorTable::getAtomsDesc() {
92321369Sdim  return HdrData.Atoms;
93321369Sdim}
94321369Sdim
95341825Sdimbool AppleAcceleratorTable::validateForms() {
96321369Sdim  for (auto Atom : getAtomsDesc()) {
97321369Sdim    DWARFFormValue FormValue(Atom.second);
98321369Sdim    switch (Atom.first) {
99321369Sdim    case dwarf::DW_ATOM_die_offset:
100327952Sdim    case dwarf::DW_ATOM_die_tag:
101327952Sdim    case dwarf::DW_ATOM_type_flags:
102321369Sdim      if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) &&
103321369Sdim           !FormValue.isFormClass(DWARFFormValue::FC_Flag)) ||
104321369Sdim          FormValue.getForm() == dwarf::DW_FORM_sdata)
105321369Sdim        return false;
106327952Sdim      break;
107321369Sdim    default:
108321369Sdim      break;
109321369Sdim    }
110321369Sdim  }
111321369Sdim  return true;
112321369Sdim}
113321369Sdim
114360784Sdimstd::pair<uint64_t, dwarf::Tag>
115360784SdimAppleAcceleratorTable::readAtoms(uint64_t *HashDataOffset) {
116360784Sdim  uint64_t DieOffset = dwarf::DW_INVALID_OFFSET;
117327952Sdim  dwarf::Tag DieTag = dwarf::DW_TAG_null;
118341825Sdim  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
119321369Sdim
120321369Sdim  for (auto Atom : getAtomsDesc()) {
121321369Sdim    DWARFFormValue FormValue(Atom.second);
122360784Sdim    FormValue.extractValue(AccelSection, HashDataOffset, FormParams);
123321369Sdim    switch (Atom.first) {
124321369Sdim    case dwarf::DW_ATOM_die_offset:
125321369Sdim      DieOffset = *FormValue.getAsUnsignedConstant();
126321369Sdim      break;
127327952Sdim    case dwarf::DW_ATOM_die_tag:
128327952Sdim      DieTag = (dwarf::Tag)*FormValue.getAsUnsignedConstant();
129327952Sdim      break;
130321369Sdim    default:
131321369Sdim      break;
132321369Sdim    }
133321369Sdim  }
134327952Sdim  return {DieOffset, DieTag};
135321369Sdim}
136321369Sdim
137341825Sdimvoid AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const {
138341825Sdim  DictScope HeaderScope(W, "Header");
139341825Sdim  W.printHex("Magic", Magic);
140341825Sdim  W.printHex("Version", Version);
141341825Sdim  W.printHex("Hash function", HashFunction);
142341825Sdim  W.printNumber("Bucket count", BucketCount);
143341825Sdim  W.printNumber("Hashes count", HashCount);
144341825Sdim  W.printNumber("HeaderData length", HeaderDataLength);
145341825Sdim}
146341825Sdim
147341825SdimOptional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset(
148341825Sdim    Optional<DWARFFormValue> Value) const {
149341825Sdim  if (!Value)
150341825Sdim    return None;
151341825Sdim
152341825Sdim  switch (Value->getForm()) {
153341825Sdim  case dwarf::DW_FORM_ref1:
154341825Sdim  case dwarf::DW_FORM_ref2:
155341825Sdim  case dwarf::DW_FORM_ref4:
156341825Sdim  case dwarf::DW_FORM_ref8:
157341825Sdim  case dwarf::DW_FORM_ref_udata:
158341825Sdim    return Value->getRawUValue() + DIEOffsetBase;
159341825Sdim  default:
160341825Sdim    return Value->getAsSectionOffset();
161341825Sdim  }
162341825Sdim}
163341825Sdim
164341825Sdimbool AppleAcceleratorTable::dumpName(ScopedPrinter &W,
165341825Sdim                                     SmallVectorImpl<DWARFFormValue> &AtomForms,
166360784Sdim                                     uint64_t *DataOffset) const {
167341825Sdim  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
168360784Sdim  uint64_t NameOffset = *DataOffset;
169341825Sdim  if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) {
170341825Sdim    W.printString("Incorrectly terminated list.");
171341825Sdim    return false;
172341825Sdim  }
173360784Sdim  uint64_t StringOffset = AccelSection.getRelocatedValue(4, DataOffset);
174341825Sdim  if (!StringOffset)
175341825Sdim    return false; // End of list
176341825Sdim
177341825Sdim  DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str());
178360784Sdim  W.startLine() << format("String: 0x%08" PRIx64, StringOffset);
179341825Sdim  W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n";
180341825Sdim
181341825Sdim  unsigned NumData = AccelSection.getU32(DataOffset);
182341825Sdim  for (unsigned Data = 0; Data < NumData; ++Data) {
183341825Sdim    ListScope DataScope(W, ("Data " + Twine(Data)).str());
184341825Sdim    unsigned i = 0;
185341825Sdim    for (auto &Atom : AtomForms) {
186341825Sdim      W.startLine() << format("Atom[%d]: ", i);
187341825Sdim      if (Atom.extractValue(AccelSection, DataOffset, FormParams)) {
188341825Sdim        Atom.dump(W.getOStream());
189341825Sdim        if (Optional<uint64_t> Val = Atom.getAsUnsignedConstant()) {
190341825Sdim          StringRef Str = dwarf::AtomValueString(HdrData.Atoms[i].first, *Val);
191341825Sdim          if (!Str.empty())
192341825Sdim            W.getOStream() << " (" << Str << ")";
193341825Sdim        }
194341825Sdim      } else
195341825Sdim        W.getOStream() << "Error extracting the value";
196341825Sdim      W.getOStream() << "\n";
197341825Sdim      i++;
198341825Sdim    }
199341825Sdim  }
200341825Sdim  return true; // more entries follow
201341825Sdim}
202341825Sdim
203341825SdimLLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const {
204327952Sdim  if (!IsValid)
205327952Sdim    return;
206327952Sdim
207341825Sdim  ScopedPrinter W(OS);
208283625Sdim
209341825Sdim  Hdr.dump(W);
210341825Sdim
211341825Sdim  W.printNumber("DIE offset base", HdrData.DIEOffsetBase);
212341825Sdim  W.printNumber("Number of atoms", uint64_t(HdrData.Atoms.size()));
213283625Sdim  SmallVector<DWARFFormValue, 3> AtomForms;
214341825Sdim  {
215341825Sdim    ListScope AtomsScope(W, "Atoms");
216341825Sdim    unsigned i = 0;
217341825Sdim    for (const auto &Atom : HdrData.Atoms) {
218341825Sdim      DictScope AtomScope(W, ("Atom " + Twine(i++)).str());
219341825Sdim      W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';
220341825Sdim      W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';
221341825Sdim      AtomForms.push_back(DWARFFormValue(Atom.second));
222341825Sdim    }
223283625Sdim  }
224283625Sdim
225283625Sdim  // Now go through the actual tables and dump them.
226360784Sdim  uint64_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
227360784Sdim  uint64_t HashesBase = Offset + Hdr.BucketCount * 4;
228360784Sdim  uint64_t OffsetsBase = HashesBase + Hdr.HashCount * 4;
229283625Sdim
230341825Sdim  for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) {
231283625Sdim    unsigned Index = AccelSection.getU32(&Offset);
232283625Sdim
233341825Sdim    ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
234283625Sdim    if (Index == UINT32_MAX) {
235341825Sdim      W.printString("EMPTY");
236283625Sdim      continue;
237283625Sdim    }
238283625Sdim
239341825Sdim    for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
240360784Sdim      uint64_t HashOffset = HashesBase + HashIdx*4;
241360784Sdim      uint64_t OffsetsOffset = OffsetsBase + HashIdx*4;
242283625Sdim      uint32_t Hash = AccelSection.getU32(&HashOffset);
243283625Sdim
244341825Sdim      if (Hash % Hdr.BucketCount != Bucket)
245283625Sdim        break;
246283625Sdim
247360784Sdim      uint64_t DataOffset = AccelSection.getU32(&OffsetsOffset);
248341825Sdim      ListScope HashScope(W, ("Hash 0x" + Twine::utohexstr(Hash)).str());
249283625Sdim      if (!AccelSection.isValidOffset(DataOffset)) {
250341825Sdim        W.printString("Invalid section offset");
251283625Sdim        continue;
252283625Sdim      }
253341825Sdim      while (dumpName(W, AtomForms, &DataOffset))
254341825Sdim        /*empty*/;
255283625Sdim    }
256283625Sdim  }
257283625Sdim}
258327952Sdim
259341825SdimAppleAcceleratorTable::Entry::Entry(
260341825Sdim    const AppleAcceleratorTable::HeaderData &HdrData)
261341825Sdim    : HdrData(&HdrData) {
262341825Sdim  Values.reserve(HdrData.Atoms.size());
263341825Sdim  for (const auto &Atom : HdrData.Atoms)
264341825Sdim    Values.push_back(DWARFFormValue(Atom.second));
265341825Sdim}
266341825Sdim
267341825Sdimvoid AppleAcceleratorTable::Entry::extract(
268360784Sdim    const AppleAcceleratorTable &AccelTable, uint64_t *Offset) {
269341825Sdim
270341825Sdim  dwarf::FormParams FormParams = {AccelTable.Hdr.Version, 0,
271341825Sdim                                  dwarf::DwarfFormat::DWARF32};
272341825Sdim  for (auto &Atom : Values)
273341825Sdim    Atom.extractValue(AccelTable.AccelSection, Offset, FormParams);
274341825Sdim}
275341825Sdim
276341825SdimOptional<DWARFFormValue>
277341825SdimAppleAcceleratorTable::Entry::lookup(HeaderData::AtomType Atom) const {
278341825Sdim  assert(HdrData && "Dereferencing end iterator?");
279341825Sdim  assert(HdrData->Atoms.size() == Values.size());
280360784Sdim  for (auto Tuple : zip_first(HdrData->Atoms, Values)) {
281341825Sdim    if (std::get<0>(Tuple).first == Atom)
282341825Sdim      return std::get<1>(Tuple);
283341825Sdim  }
284341825Sdim  return None;
285341825Sdim}
286341825Sdim
287341825SdimOptional<uint64_t> AppleAcceleratorTable::Entry::getDIESectionOffset() const {
288341825Sdim  return HdrData->extractOffset(lookup(dwarf::DW_ATOM_die_offset));
289341825Sdim}
290341825Sdim
291341825SdimOptional<uint64_t> AppleAcceleratorTable::Entry::getCUOffset() const {
292341825Sdim  return HdrData->extractOffset(lookup(dwarf::DW_ATOM_cu_offset));
293341825Sdim}
294341825Sdim
295341825SdimOptional<dwarf::Tag> AppleAcceleratorTable::Entry::getTag() const {
296341825Sdim  Optional<DWARFFormValue> Tag = lookup(dwarf::DW_ATOM_die_tag);
297341825Sdim  if (!Tag)
298341825Sdim    return None;
299341825Sdim  if (Optional<uint64_t> Value = Tag->getAsUnsignedConstant())
300341825Sdim    return dwarf::Tag(*Value);
301341825Sdim  return None;
302341825Sdim}
303341825Sdim
304341825SdimAppleAcceleratorTable::ValueIterator::ValueIterator(
305360784Sdim    const AppleAcceleratorTable &AccelTable, uint64_t Offset)
306341825Sdim    : AccelTable(&AccelTable), Current(AccelTable.HdrData), DataOffset(Offset) {
307327952Sdim  if (!AccelTable.AccelSection.isValidOffsetForDataOfSize(DataOffset, 4))
308327952Sdim    return;
309327952Sdim
310327952Sdim  // Read the first entry.
311327952Sdim  NumData = AccelTable.AccelSection.getU32(&DataOffset);
312327952Sdim  Next();
313327952Sdim}
314327952Sdim
315341825Sdimvoid AppleAcceleratorTable::ValueIterator::Next() {
316327952Sdim  assert(NumData > 0 && "attempted to increment iterator past the end");
317327952Sdim  auto &AccelSection = AccelTable->AccelSection;
318327952Sdim  if (Data >= NumData ||
319327952Sdim      !AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) {
320327952Sdim    NumData = 0;
321341825Sdim    DataOffset = 0;
322327952Sdim    return;
323327952Sdim  }
324341825Sdim  Current.extract(*AccelTable, &DataOffset);
325327952Sdim  ++Data;
326327952Sdim}
327327952Sdim
328341825Sdimiterator_range<AppleAcceleratorTable::ValueIterator>
329341825SdimAppleAcceleratorTable::equal_range(StringRef Key) const {
330327952Sdim  if (!IsValid)
331327952Sdim    return make_range(ValueIterator(), ValueIterator());
332327952Sdim
333327952Sdim  // Find the bucket.
334341825Sdim  unsigned HashValue = djbHash(Key);
335341825Sdim  unsigned Bucket = HashValue % Hdr.BucketCount;
336360784Sdim  uint64_t BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength;
337360784Sdim  uint64_t HashesBase = BucketBase + Hdr.BucketCount * 4;
338360784Sdim  uint64_t OffsetsBase = HashesBase + Hdr.HashCount * 4;
339327952Sdim
340360784Sdim  uint64_t BucketOffset = BucketBase + Bucket * 4;
341327952Sdim  unsigned Index = AccelSection.getU32(&BucketOffset);
342327952Sdim
343327952Sdim  // Search through all hashes in the bucket.
344341825Sdim  for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
345360784Sdim    uint64_t HashOffset = HashesBase + HashIdx * 4;
346360784Sdim    uint64_t OffsetsOffset = OffsetsBase + HashIdx * 4;
347327952Sdim    uint32_t Hash = AccelSection.getU32(&HashOffset);
348327952Sdim
349341825Sdim    if (Hash % Hdr.BucketCount != Bucket)
350327952Sdim      // We are already in the next bucket.
351327952Sdim      break;
352327952Sdim
353360784Sdim    uint64_t DataOffset = AccelSection.getU32(&OffsetsOffset);
354360784Sdim    uint64_t StringOffset = AccelSection.getRelocatedValue(4, &DataOffset);
355327952Sdim    if (!StringOffset)
356327952Sdim      break;
357327952Sdim
358327952Sdim    // Finally, compare the key.
359327952Sdim    if (Key == StringSection.getCStr(&StringOffset))
360327952Sdim      return make_range({*this, DataOffset}, ValueIterator());
361327952Sdim  }
362327952Sdim  return make_range(ValueIterator(), ValueIterator());
363327952Sdim}
364341825Sdim
365341825Sdimvoid DWARFDebugNames::Header::dump(ScopedPrinter &W) const {
366341825Sdim  DictScope HeaderScope(W, "Header");
367341825Sdim  W.printHex("Length", UnitLength);
368341825Sdim  W.printNumber("Version", Version);
369341825Sdim  W.printHex("Padding", Padding);
370341825Sdim  W.printNumber("CU count", CompUnitCount);
371341825Sdim  W.printNumber("Local TU count", LocalTypeUnitCount);
372341825Sdim  W.printNumber("Foreign TU count", ForeignTypeUnitCount);
373341825Sdim  W.printNumber("Bucket count", BucketCount);
374341825Sdim  W.printNumber("Name count", NameCount);
375341825Sdim  W.printHex("Abbreviations table size", AbbrevTableSize);
376341825Sdim  W.startLine() << "Augmentation: '" << AugmentationString << "'\n";
377341825Sdim}
378341825Sdim
379353358SdimError DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
380360784Sdim                                             uint64_t *Offset) {
381341825Sdim  // Check that we can read the fixed-size part.
382341825Sdim  if (!AS.isValidOffset(*Offset + sizeof(HeaderPOD) - 1))
383344779Sdim    return createStringError(errc::illegal_byte_sequence,
384344779Sdim                             "Section too small: cannot read header.");
385341825Sdim
386341825Sdim  UnitLength = AS.getU32(Offset);
387341825Sdim  Version = AS.getU16(Offset);
388341825Sdim  Padding = AS.getU16(Offset);
389341825Sdim  CompUnitCount = AS.getU32(Offset);
390341825Sdim  LocalTypeUnitCount = AS.getU32(Offset);
391341825Sdim  ForeignTypeUnitCount = AS.getU32(Offset);
392341825Sdim  BucketCount = AS.getU32(Offset);
393341825Sdim  NameCount = AS.getU32(Offset);
394341825Sdim  AbbrevTableSize = AS.getU32(Offset);
395341825Sdim  AugmentationStringSize = alignTo(AS.getU32(Offset), 4);
396341825Sdim
397341825Sdim  if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize))
398344779Sdim    return createStringError(
399344779Sdim        errc::illegal_byte_sequence,
400344779Sdim        "Section too small: cannot read header augmentation.");
401341825Sdim  AugmentationString.resize(AugmentationStringSize);
402341825Sdim  AS.getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()),
403341825Sdim           AugmentationStringSize);
404341825Sdim  return Error::success();
405341825Sdim}
406341825Sdim
407341825Sdimvoid DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const {
408341825Sdim  DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str());
409341825Sdim  W.startLine() << formatv("Tag: {0}\n", Tag);
410341825Sdim
411341825Sdim  for (const auto &Attr : Attributes)
412341825Sdim    W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
413341825Sdim}
414341825Sdim
415341825Sdimstatic constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc() {
416341825Sdim  return {dwarf::Index(0), dwarf::Form(0)};
417341825Sdim}
418341825Sdim
419341825Sdimstatic bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE) {
420341825Sdim  return AE == sentinelAttrEnc();
421341825Sdim}
422341825Sdim
423341825Sdimstatic DWARFDebugNames::Abbrev sentinelAbbrev() {
424341825Sdim  return DWARFDebugNames::Abbrev(0, dwarf::Tag(0), {});
425341825Sdim}
426341825Sdim
427341825Sdimstatic bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) {
428341825Sdim  return Abbr.Code == 0;
429341825Sdim}
430341825Sdim
431341825SdimDWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() {
432341825Sdim  return sentinelAbbrev();
433341825Sdim}
434341825Sdim
435341825SdimDWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() {
436341825Sdim  return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), {});
437341825Sdim}
438341825Sdim
439341825SdimExpected<DWARFDebugNames::AttributeEncoding>
440360784SdimDWARFDebugNames::NameIndex::extractAttributeEncoding(uint64_t *Offset) {
441341825Sdim  if (*Offset >= EntriesBase) {
442344779Sdim    return createStringError(errc::illegal_byte_sequence,
443344779Sdim                             "Incorrectly terminated abbreviation table.");
444341825Sdim  }
445341825Sdim
446341825Sdim  uint32_t Index = Section.AccelSection.getULEB128(Offset);
447341825Sdim  uint32_t Form = Section.AccelSection.getULEB128(Offset);
448341825Sdim  return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form));
449341825Sdim}
450341825Sdim
451341825SdimExpected<std::vector<DWARFDebugNames::AttributeEncoding>>
452360784SdimDWARFDebugNames::NameIndex::extractAttributeEncodings(uint64_t *Offset) {
453341825Sdim  std::vector<AttributeEncoding> Result;
454341825Sdim  for (;;) {
455341825Sdim    auto AttrEncOr = extractAttributeEncoding(Offset);
456341825Sdim    if (!AttrEncOr)
457341825Sdim      return AttrEncOr.takeError();
458341825Sdim    if (isSentinel(*AttrEncOr))
459341825Sdim      return std::move(Result);
460341825Sdim
461341825Sdim    Result.emplace_back(*AttrEncOr);
462341825Sdim  }
463341825Sdim}
464341825Sdim
465341825SdimExpected<DWARFDebugNames::Abbrev>
466360784SdimDWARFDebugNames::NameIndex::extractAbbrev(uint64_t *Offset) {
467341825Sdim  if (*Offset >= EntriesBase) {
468344779Sdim    return createStringError(errc::illegal_byte_sequence,
469344779Sdim                             "Incorrectly terminated abbreviation table.");
470341825Sdim  }
471341825Sdim
472341825Sdim  uint32_t Code = Section.AccelSection.getULEB128(Offset);
473341825Sdim  if (Code == 0)
474341825Sdim    return sentinelAbbrev();
475341825Sdim
476341825Sdim  uint32_t Tag = Section.AccelSection.getULEB128(Offset);
477341825Sdim  auto AttrEncOr = extractAttributeEncodings(Offset);
478341825Sdim  if (!AttrEncOr)
479341825Sdim    return AttrEncOr.takeError();
480341825Sdim  return Abbrev(Code, dwarf::Tag(Tag), std::move(*AttrEncOr));
481341825Sdim}
482341825Sdim
483341825SdimError DWARFDebugNames::NameIndex::extract() {
484341825Sdim  const DWARFDataExtractor &AS = Section.AccelSection;
485360784Sdim  uint64_t Offset = Base;
486341825Sdim  if (Error E = Hdr.extract(AS, &Offset))
487341825Sdim    return E;
488341825Sdim
489341825Sdim  CUsBase = Offset;
490341825Sdim  Offset += Hdr.CompUnitCount * 4;
491341825Sdim  Offset += Hdr.LocalTypeUnitCount * 4;
492341825Sdim  Offset += Hdr.ForeignTypeUnitCount * 8;
493341825Sdim  BucketsBase = Offset;
494341825Sdim  Offset += Hdr.BucketCount * 4;
495341825Sdim  HashesBase = Offset;
496341825Sdim  if (Hdr.BucketCount > 0)
497341825Sdim    Offset += Hdr.NameCount * 4;
498341825Sdim  StringOffsetsBase = Offset;
499341825Sdim  Offset += Hdr.NameCount * 4;
500341825Sdim  EntryOffsetsBase = Offset;
501341825Sdim  Offset += Hdr.NameCount * 4;
502341825Sdim
503341825Sdim  if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
504344779Sdim    return createStringError(errc::illegal_byte_sequence,
505344779Sdim                             "Section too small: cannot read abbreviations.");
506341825Sdim
507341825Sdim  EntriesBase = Offset + Hdr.AbbrevTableSize;
508341825Sdim
509341825Sdim  for (;;) {
510341825Sdim    auto AbbrevOr = extractAbbrev(&Offset);
511341825Sdim    if (!AbbrevOr)
512341825Sdim      return AbbrevOr.takeError();
513341825Sdim    if (isSentinel(*AbbrevOr))
514341825Sdim      return Error::success();
515341825Sdim
516344779Sdim    if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
517344779Sdim      return createStringError(errc::invalid_argument,
518344779Sdim                               "Duplicate abbreviation code.");
519341825Sdim  }
520341825Sdim}
521353358Sdim
522341825SdimDWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
523341825Sdim    : NameIdx(&NameIdx), Abbr(&Abbr) {
524341825Sdim  // This merely creates form values. It is up to the caller
525341825Sdim  // (NameIndex::getEntry) to populate them.
526341825Sdim  Values.reserve(Abbr.Attributes.size());
527341825Sdim  for (const auto &Attr : Abbr.Attributes)
528341825Sdim    Values.emplace_back(Attr.Form);
529341825Sdim}
530341825Sdim
531341825SdimOptional<DWARFFormValue>
532341825SdimDWARFDebugNames::Entry::lookup(dwarf::Index Index) const {
533341825Sdim  assert(Abbr->Attributes.size() == Values.size());
534360784Sdim  for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
535341825Sdim    if (std::get<0>(Tuple).Index == Index)
536341825Sdim      return std::get<1>(Tuple);
537341825Sdim  }
538341825Sdim  return None;
539341825Sdim}
540341825Sdim
541341825SdimOptional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
542341825Sdim  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
543341825Sdim    return Off->getAsReferenceUVal();
544341825Sdim  return None;
545341825Sdim}
546341825Sdim
547341825SdimOptional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
548341825Sdim  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
549341825Sdim    return Off->getAsUnsignedConstant();
550341825Sdim  // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
551341825Sdim  // implicitly refer to the single CU.
552341825Sdim  if (NameIdx->getCUCount() == 1)
553341825Sdim    return 0;
554341825Sdim  return None;
555341825Sdim}
556341825Sdim
557341825SdimOptional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
558341825Sdim  Optional<uint64_t> Index = getCUIndex();
559341825Sdim  if (!Index || *Index >= NameIdx->getCUCount())
560341825Sdim    return None;
561341825Sdim  return NameIdx->getCUOffset(*Index);
562341825Sdim}
563341825Sdim
564341825Sdimvoid DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
565341825Sdim  W.printHex("Abbrev", Abbr->Code);
566341825Sdim  W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
567341825Sdim  assert(Abbr->Attributes.size() == Values.size());
568360784Sdim  for (auto Tuple : zip_first(Abbr->Attributes, Values)) {
569341825Sdim    W.startLine() << formatv("{0}: ", std::get<0>(Tuple).Index);
570341825Sdim    std::get<1>(Tuple).dump(W.getOStream());
571341825Sdim    W.getOStream() << '\n';
572341825Sdim  }
573341825Sdim}
574341825Sdim
575341825Sdimchar DWARFDebugNames::SentinelError::ID;
576341825Sdimstd::error_code DWARFDebugNames::SentinelError::convertToErrorCode() const {
577341825Sdim  return inconvertibleErrorCode();
578341825Sdim}
579341825Sdim
580360784Sdimuint64_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const {
581341825Sdim  assert(CU < Hdr.CompUnitCount);
582360784Sdim  uint64_t Offset = CUsBase + 4 * CU;
583341825Sdim  return Section.AccelSection.getRelocatedValue(4, &Offset);
584341825Sdim}
585341825Sdim
586360784Sdimuint64_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const {
587341825Sdim  assert(TU < Hdr.LocalTypeUnitCount);
588360784Sdim  uint64_t Offset = CUsBase + 4 * (Hdr.CompUnitCount + TU);
589341825Sdim  return Section.AccelSection.getRelocatedValue(4, &Offset);
590341825Sdim}
591341825Sdim
592341825Sdimuint64_t DWARFDebugNames::NameIndex::getForeignTUSignature(uint32_t TU) const {
593341825Sdim  assert(TU < Hdr.ForeignTypeUnitCount);
594360784Sdim  uint64_t Offset =
595353358Sdim      CUsBase + 4 * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU;
596341825Sdim  return Section.AccelSection.getU64(&Offset);
597341825Sdim}
598341825Sdim
599341825SdimExpected<DWARFDebugNames::Entry>
600360784SdimDWARFDebugNames::NameIndex::getEntry(uint64_t *Offset) const {
601341825Sdim  const DWARFDataExtractor &AS = Section.AccelSection;
602341825Sdim  if (!AS.isValidOffset(*Offset))
603344779Sdim    return createStringError(errc::illegal_byte_sequence,
604344779Sdim                             "Incorrectly terminated entry list.");
605341825Sdim
606341825Sdim  uint32_t AbbrevCode = AS.getULEB128(Offset);
607341825Sdim  if (AbbrevCode == 0)
608341825Sdim    return make_error<SentinelError>();
609341825Sdim
610341825Sdim  const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
611341825Sdim  if (AbbrevIt == Abbrevs.end())
612344779Sdim    return createStringError(errc::invalid_argument, "Invalid abbreviation.");
613341825Sdim
614341825Sdim  Entry E(*this, *AbbrevIt);
615341825Sdim
616341825Sdim  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
617341825Sdim  for (auto &Value : E.Values) {
618341825Sdim    if (!Value.extractValue(AS, Offset, FormParams))
619344779Sdim      return createStringError(errc::io_error,
620344779Sdim                               "Error extracting index attribute values.");
621341825Sdim  }
622341825Sdim  return std::move(E);
623341825Sdim}
624341825Sdim
625341825SdimDWARFDebugNames::NameTableEntry
626341825SdimDWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const {
627341825Sdim  assert(0 < Index && Index <= Hdr.NameCount);
628360784Sdim  uint64_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1);
629360784Sdim  uint64_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1);
630341825Sdim  const DWARFDataExtractor &AS = Section.AccelSection;
631341825Sdim
632360784Sdim  uint64_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset);
633360784Sdim  uint64_t EntryOffset = AS.getU32(&EntryOffsetOffset);
634341825Sdim  EntryOffset += EntriesBase;
635341825Sdim  return {Section.StringSection, Index, StringOffset, EntryOffset};
636341825Sdim}
637341825Sdim
638341825Sdimuint32_t
639341825SdimDWARFDebugNames::NameIndex::getBucketArrayEntry(uint32_t Bucket) const {
640341825Sdim  assert(Bucket < Hdr.BucketCount);
641360784Sdim  uint64_t BucketOffset = BucketsBase + 4 * Bucket;
642341825Sdim  return Section.AccelSection.getU32(&BucketOffset);
643341825Sdim}
644341825Sdim
645341825Sdimuint32_t DWARFDebugNames::NameIndex::getHashArrayEntry(uint32_t Index) const {
646341825Sdim  assert(0 < Index && Index <= Hdr.NameCount);
647360784Sdim  uint64_t HashOffset = HashesBase + 4 * (Index - 1);
648341825Sdim  return Section.AccelSection.getU32(&HashOffset);
649341825Sdim}
650341825Sdim
651341825Sdim// Returns true if we should continue scanning for entries, false if this is the
652341825Sdim// last (sentinel) entry). In case of a parsing error we also return false, as
653341825Sdim// it's not possible to recover this entry list (but the other lists may still
654341825Sdim// parse OK).
655341825Sdimbool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
656360784Sdim                                           uint64_t *Offset) const {
657360784Sdim  uint64_t EntryId = *Offset;
658341825Sdim  auto EntryOr = getEntry(Offset);
659341825Sdim  if (!EntryOr) {
660341825Sdim    handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
661341825Sdim                    [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
662341825Sdim    return false;
663341825Sdim  }
664341825Sdim
665341825Sdim  DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
666341825Sdim  EntryOr->dump(W);
667341825Sdim  return true;
668341825Sdim}
669341825Sdim
670341825Sdimvoid DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
671341825Sdim                                          const NameTableEntry &NTE,
672341825Sdim                                          Optional<uint32_t> Hash) const {
673341825Sdim  DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
674341825Sdim  if (Hash)
675341825Sdim    W.printHex("Hash", *Hash);
676341825Sdim
677360784Sdim  W.startLine() << format("String: 0x%08" PRIx64, NTE.getStringOffset());
678341825Sdim  W.getOStream() << " \"" << NTE.getString() << "\"\n";
679341825Sdim
680360784Sdim  uint64_t EntryOffset = NTE.getEntryOffset();
681341825Sdim  while (dumpEntry(W, &EntryOffset))
682341825Sdim    /*empty*/;
683341825Sdim}
684341825Sdim
685341825Sdimvoid DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
686341825Sdim  ListScope CUScope(W, "Compilation Unit offsets");
687341825Sdim  for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
688360784Sdim    W.startLine() << format("CU[%u]: 0x%08" PRIx64 "\n", CU, getCUOffset(CU));
689341825Sdim}
690341825Sdim
691341825Sdimvoid DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
692341825Sdim  if (Hdr.LocalTypeUnitCount == 0)
693341825Sdim    return;
694341825Sdim
695341825Sdim  ListScope TUScope(W, "Local Type Unit offsets");
696341825Sdim  for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
697360784Sdim    W.startLine() << format("LocalTU[%u]: 0x%08" PRIx64 "\n", TU,
698360784Sdim                            getLocalTUOffset(TU));
699341825Sdim}
700341825Sdim
701341825Sdimvoid DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
702341825Sdim  if (Hdr.ForeignTypeUnitCount == 0)
703341825Sdim    return;
704341825Sdim
705341825Sdim  ListScope TUScope(W, "Foreign Type Unit signatures");
706341825Sdim  for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
707341825Sdim    W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,
708341825Sdim                            getForeignTUSignature(TU));
709341825Sdim  }
710341825Sdim}
711341825Sdim
712341825Sdimvoid DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
713341825Sdim  ListScope AbbrevsScope(W, "Abbreviations");
714341825Sdim  for (const auto &Abbr : Abbrevs)
715341825Sdim    Abbr.dump(W);
716341825Sdim}
717341825Sdim
718341825Sdimvoid DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
719341825Sdim                                            uint32_t Bucket) const {
720341825Sdim  ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
721341825Sdim  uint32_t Index = getBucketArrayEntry(Bucket);
722341825Sdim  if (Index == 0) {
723341825Sdim    W.printString("EMPTY");
724341825Sdim    return;
725341825Sdim  }
726341825Sdim  if (Index > Hdr.NameCount) {
727341825Sdim    W.printString("Name index is invalid");
728341825Sdim    return;
729341825Sdim  }
730341825Sdim
731341825Sdim  for (; Index <= Hdr.NameCount; ++Index) {
732341825Sdim    uint32_t Hash = getHashArrayEntry(Index);
733341825Sdim    if (Hash % Hdr.BucketCount != Bucket)
734341825Sdim      break;
735341825Sdim
736341825Sdim    dumpName(W, getNameTableEntry(Index), Hash);
737341825Sdim  }
738341825Sdim}
739341825Sdim
740341825SdimLLVM_DUMP_METHOD void DWARFDebugNames::NameIndex::dump(ScopedPrinter &W) const {
741341825Sdim  DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
742341825Sdim  Hdr.dump(W);
743341825Sdim  dumpCUs(W);
744341825Sdim  dumpLocalTUs(W);
745341825Sdim  dumpForeignTUs(W);
746341825Sdim  dumpAbbreviations(W);
747341825Sdim
748341825Sdim  if (Hdr.BucketCount > 0) {
749341825Sdim    for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
750341825Sdim      dumpBucket(W, Bucket);
751341825Sdim    return;
752341825Sdim  }
753341825Sdim
754341825Sdim  W.startLine() << "Hash table not present\n";
755341825Sdim  for (NameTableEntry NTE : *this)
756341825Sdim    dumpName(W, NTE, None);
757341825Sdim}
758341825Sdim
759353358SdimError DWARFDebugNames::extract() {
760360784Sdim  uint64_t Offset = 0;
761341825Sdim  while (AccelSection.isValidOffset(Offset)) {
762341825Sdim    NameIndex Next(*this, Offset);
763353358Sdim    if (Error E = Next.extract())
764341825Sdim      return E;
765341825Sdim    Offset = Next.getNextUnitOffset();
766341825Sdim    NameIndices.push_back(std::move(Next));
767341825Sdim  }
768341825Sdim  return Error::success();
769341825Sdim}
770341825Sdim
771341825Sdimiterator_range<DWARFDebugNames::ValueIterator>
772341825SdimDWARFDebugNames::NameIndex::equal_range(StringRef Key) const {
773341825Sdim  return make_range(ValueIterator(*this, Key), ValueIterator());
774341825Sdim}
775341825Sdim
776341825SdimLLVM_DUMP_METHOD void DWARFDebugNames::dump(raw_ostream &OS) const {
777341825Sdim  ScopedPrinter W(OS);
778341825Sdim  for (const NameIndex &NI : NameIndices)
779341825Sdim    NI.dump(W);
780341825Sdim}
781341825Sdim
782360784SdimOptional<uint64_t>
783341825SdimDWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
784341825Sdim  const Header &Hdr = CurrentIndex->Hdr;
785341825Sdim  if (Hdr.BucketCount == 0) {
786341825Sdim    // No Hash Table, We need to search through all names in the Name Index.
787341825Sdim    for (NameTableEntry NTE : *CurrentIndex) {
788341825Sdim      if (NTE.getString() == Key)
789341825Sdim        return NTE.getEntryOffset();
790341825Sdim    }
791341825Sdim    return None;
792341825Sdim  }
793341825Sdim
794341825Sdim  // The Name Index has a Hash Table, so use that to speed up the search.
795341825Sdim  // Compute the Key Hash, if it has not been done already.
796341825Sdim  if (!Hash)
797341825Sdim    Hash = caseFoldingDjbHash(Key);
798341825Sdim  uint32_t Bucket = *Hash % Hdr.BucketCount;
799341825Sdim  uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
800341825Sdim  if (Index == 0)
801341825Sdim    return None; // Empty bucket
802341825Sdim
803341825Sdim  for (; Index <= Hdr.NameCount; ++Index) {
804341825Sdim    uint32_t Hash = CurrentIndex->getHashArrayEntry(Index);
805341825Sdim    if (Hash % Hdr.BucketCount != Bucket)
806341825Sdim      return None; // End of bucket
807341825Sdim
808341825Sdim    NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
809341825Sdim    if (NTE.getString() == Key)
810341825Sdim      return NTE.getEntryOffset();
811341825Sdim  }
812341825Sdim  return None;
813341825Sdim}
814341825Sdim
815341825Sdimbool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
816341825Sdim  auto EntryOr = CurrentIndex->getEntry(&DataOffset);
817341825Sdim  if (!EntryOr) {
818341825Sdim    consumeError(EntryOr.takeError());
819341825Sdim    return false;
820341825Sdim  }
821341825Sdim  CurrentEntry = std::move(*EntryOr);
822341825Sdim  return true;
823341825Sdim}
824341825Sdim
825341825Sdimbool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
826360784Sdim  Optional<uint64_t> Offset = findEntryOffsetInCurrentIndex();
827341825Sdim  if (!Offset)
828341825Sdim    return false;
829341825Sdim  DataOffset = *Offset;
830341825Sdim  return getEntryAtCurrentOffset();
831341825Sdim}
832341825Sdim
833341825Sdimvoid DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
834341825Sdim  for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
835341825Sdim       CurrentIndex != End; ++CurrentIndex) {
836341825Sdim    if (findInCurrentIndex())
837341825Sdim      return;
838341825Sdim  }
839341825Sdim  setEnd();
840341825Sdim}
841341825Sdim
842341825Sdimvoid DWARFDebugNames::ValueIterator::next() {
843341825Sdim  assert(CurrentIndex && "Incrementing an end() iterator?");
844341825Sdim
845341825Sdim  // First try the next entry in the current Index.
846341825Sdim  if (getEntryAtCurrentOffset())
847341825Sdim    return;
848341825Sdim
849341825Sdim  // If we're a local iterator or we have reached the last Index, we're done.
850341825Sdim  if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
851341825Sdim    setEnd();
852341825Sdim    return;
853341825Sdim  }
854341825Sdim
855341825Sdim  // Otherwise, try the next index.
856341825Sdim  ++CurrentIndex;
857341825Sdim  searchFromStartOfCurrentIndex();
858341825Sdim}
859341825Sdim
860341825SdimDWARFDebugNames::ValueIterator::ValueIterator(const DWARFDebugNames &AccelTable,
861341825Sdim                                              StringRef Key)
862341825Sdim    : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false), Key(Key) {
863341825Sdim  searchFromStartOfCurrentIndex();
864341825Sdim}
865341825Sdim
866341825SdimDWARFDebugNames::ValueIterator::ValueIterator(
867341825Sdim    const DWARFDebugNames::NameIndex &NI, StringRef Key)
868341825Sdim    : CurrentIndex(&NI), IsLocal(true), Key(Key) {
869341825Sdim  if (!findInCurrentIndex())
870341825Sdim    setEnd();
871341825Sdim}
872341825Sdim
873341825Sdimiterator_range<DWARFDebugNames::ValueIterator>
874341825SdimDWARFDebugNames::equal_range(StringRef Key) const {
875341825Sdim  if (NameIndices.empty())
876341825Sdim    return make_range(ValueIterator(), ValueIterator());
877341825Sdim  return make_range(ValueIterator(*this, Key), ValueIterator());
878341825Sdim}
879341825Sdim
880341825Sdimconst DWARFDebugNames::NameIndex *
881360784SdimDWARFDebugNames::getCUNameIndex(uint64_t CUOffset) {
882341825Sdim  if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) {
883341825Sdim    for (const auto &NI : *this) {
884341825Sdim      for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
885341825Sdim        CUToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
886341825Sdim    }
887341825Sdim  }
888341825Sdim  return CUToNameIndex.lookup(CUOffset);
889341825Sdim}
890