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