1e94042caSEugene Zelenko //===- DWARFAcceleratorTable.cpp ------------------------------------------===// 282af9438SZachary Turner // 382af9438SZachary Turner // The LLVM Compiler Infrastructure 482af9438SZachary Turner // 582af9438SZachary Turner // This file is distributed under the University of Illinois Open Source 682af9438SZachary Turner // License. See LICENSE.TXT for details. 782af9438SZachary Turner // 882af9438SZachary Turner //===----------------------------------------------------------------------===// 982af9438SZachary Turner 1082af9438SZachary Turner #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" 11264b5d9eSZachary Turner 126bda14b3SChandler Carruth #include "llvm/ADT/SmallVector.h" 13264b5d9eSZachary Turner #include "llvm/BinaryFormat/Dwarf.h" 14e94042caSEugene Zelenko #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" 15e94042caSEugene Zelenko #include "llvm/Support/Compiler.h" 1692ac9d3eSJonas Devlieghere #include "llvm/Support/DJB.h" 1782af9438SZachary Turner #include "llvm/Support/Format.h" 183c9a918cSPavel Labath #include "llvm/Support/ScopedPrinter.h" 1982af9438SZachary Turner #include "llvm/Support/raw_ostream.h" 20e94042caSEugene Zelenko #include <cstddef> 21e94042caSEugene Zelenko #include <cstdint> 22e94042caSEugene Zelenko #include <utility> 2382af9438SZachary Turner 24e94042caSEugene Zelenko using namespace llvm; 2582af9438SZachary Turner 263c9a918cSPavel Labath namespace { 273c9a918cSPavel Labath struct DwarfConstant { 283c9a918cSPavel Labath StringRef (*StringFn)(unsigned); 293c9a918cSPavel Labath StringRef Type; 303c9a918cSPavel Labath unsigned Value; 313c9a918cSPavel Labath }; 323c9a918cSPavel Labath 333c9a918cSPavel Labath static raw_ostream &operator<<(raw_ostream &OS, const DwarfConstant &C) { 343c9a918cSPavel Labath StringRef Str = C.StringFn(C.Value); 353c9a918cSPavel Labath if (!Str.empty()) 363c9a918cSPavel Labath return OS << Str; 373c9a918cSPavel Labath return OS << "DW_" << C.Type << "_Unknown_0x" << format("%x", C.Value); 383c9a918cSPavel Labath } 393c9a918cSPavel Labath } // namespace 403c9a918cSPavel Labath 413c9a918cSPavel Labath static DwarfConstant formatTag(unsigned Tag) { 423c9a918cSPavel Labath return {dwarf::TagString, "TAG", Tag}; 433c9a918cSPavel Labath } 443c9a918cSPavel Labath 453c9a918cSPavel Labath static DwarfConstant formatForm(unsigned Form) { 463c9a918cSPavel Labath return {dwarf::FormEncodingString, "FORM", Form}; 473c9a918cSPavel Labath } 483c9a918cSPavel Labath 493c9a918cSPavel Labath static DwarfConstant formatIndex(unsigned Idx) { 503c9a918cSPavel Labath return {dwarf::IndexString, "IDX", Idx}; 513c9a918cSPavel Labath } 523c9a918cSPavel Labath 533c9a918cSPavel Labath static DwarfConstant formatAtom(unsigned Atom) { 543c9a918cSPavel Labath return {dwarf::AtomTypeString, "ATOM", Atom}; 553c9a918cSPavel Labath } 563c9a918cSPavel Labath 573c9a918cSPavel Labath DWARFAcceleratorTable::~DWARFAcceleratorTable() = default; 583c9a918cSPavel Labath 599b36fd25SPavel Labath llvm::Error AppleAcceleratorTable::extract() { 6082af9438SZachary Turner uint32_t Offset = 0; 6182af9438SZachary Turner 6282af9438SZachary Turner // Check that we can at least read the header. 6382af9438SZachary Turner if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength)+4)) 64ba915897SJonas Devlieghere return make_error<StringError>("Section too small: cannot read header.", 65ba915897SJonas Devlieghere inconvertibleErrorCode()); 6682af9438SZachary Turner 6782af9438SZachary Turner Hdr.Magic = AccelSection.getU32(&Offset); 6882af9438SZachary Turner Hdr.Version = AccelSection.getU16(&Offset); 6982af9438SZachary Turner Hdr.HashFunction = AccelSection.getU16(&Offset); 70*394e8056SPavel Labath Hdr.BucketCount = AccelSection.getU32(&Offset); 71*394e8056SPavel Labath Hdr.HashCount = AccelSection.getU32(&Offset); 7282af9438SZachary Turner Hdr.HeaderDataLength = AccelSection.getU32(&Offset); 7382af9438SZachary Turner 7482af9438SZachary Turner // Check that we can read all the hashes and offsets from the 7582af9438SZachary Turner // section (see SourceLevelDebugging.rst for the structure of the index). 76ba915897SJonas Devlieghere // We need to substract one because we're checking for an *offset* which is 77ba915897SJonas Devlieghere // equal to the size for an empty table and hence pointer after the section. 7882af9438SZachary Turner if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength + 79*394e8056SPavel Labath Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1)) 80ba915897SJonas Devlieghere return make_error<StringError>( 81ba915897SJonas Devlieghere "Section too small: cannot read buckets and hashes.", 82ba915897SJonas Devlieghere inconvertibleErrorCode()); 8382af9438SZachary Turner 8482af9438SZachary Turner HdrData.DIEOffsetBase = AccelSection.getU32(&Offset); 8582af9438SZachary Turner uint32_t NumAtoms = AccelSection.getU32(&Offset); 8682af9438SZachary Turner 8782af9438SZachary Turner for (unsigned i = 0; i < NumAtoms; ++i) { 8882af9438SZachary Turner uint16_t AtomType = AccelSection.getU16(&Offset); 896c273763SGreg Clayton auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset)); 9082af9438SZachary Turner HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm)); 9182af9438SZachary Turner } 9282af9438SZachary Turner 9399fdb9d9SAdrian Prantl IsValid = true; 94ba915897SJonas Devlieghere return Error::success(); 9582af9438SZachary Turner } 9682af9438SZachary Turner 97*394e8056SPavel Labath uint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.BucketCount; } 98*394e8056SPavel Labath uint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.HashCount; } 999b36fd25SPavel Labath uint32_t AppleAcceleratorTable::getSizeHdr() { return sizeof(Hdr); } 1009b36fd25SPavel Labath uint32_t AppleAcceleratorTable::getHeaderDataLength() { 101e41823bbSSpyridoula Gravani return Hdr.HeaderDataLength; 102e41823bbSSpyridoula Gravani } 103e41823bbSSpyridoula Gravani 1049b36fd25SPavel Labath ArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType, 1059b36fd25SPavel Labath AppleAcceleratorTable::HeaderData::Form>> 1069b36fd25SPavel Labath AppleAcceleratorTable::getAtomsDesc() { 107837c110cSSpyridoula Gravani return HdrData.Atoms; 108837c110cSSpyridoula Gravani } 109837c110cSSpyridoula Gravani 1109b36fd25SPavel Labath bool AppleAcceleratorTable::validateForms() { 111837c110cSSpyridoula Gravani for (auto Atom : getAtomsDesc()) { 112837c110cSSpyridoula Gravani DWARFFormValue FormValue(Atom.second); 113837c110cSSpyridoula Gravani switch (Atom.first) { 114837c110cSSpyridoula Gravani case dwarf::DW_ATOM_die_offset: 11570d35e10SSpyridoula Gravani case dwarf::DW_ATOM_die_tag: 11670d35e10SSpyridoula Gravani case dwarf::DW_ATOM_type_flags: 117837c110cSSpyridoula Gravani if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) && 118837c110cSSpyridoula Gravani !FormValue.isFormClass(DWARFFormValue::FC_Flag)) || 119837c110cSSpyridoula Gravani FormValue.getForm() == dwarf::DW_FORM_sdata) 120837c110cSSpyridoula Gravani return false; 1210e6694d1SAdrian Prantl break; 122837c110cSSpyridoula Gravani default: 123837c110cSSpyridoula Gravani break; 124837c110cSSpyridoula Gravani } 125837c110cSSpyridoula Gravani } 126837c110cSSpyridoula Gravani return true; 127837c110cSSpyridoula Gravani } 128837c110cSSpyridoula Gravani 12970d35e10SSpyridoula Gravani std::pair<uint32_t, dwarf::Tag> 1309b36fd25SPavel Labath AppleAcceleratorTable::readAtoms(uint32_t &HashDataOffset) { 131837c110cSSpyridoula Gravani uint32_t DieOffset = dwarf::DW_INVALID_OFFSET; 13270d35e10SSpyridoula Gravani dwarf::Tag DieTag = dwarf::DW_TAG_null; 133e5400f8aSPaul Robinson DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; 134837c110cSSpyridoula Gravani 135837c110cSSpyridoula Gravani for (auto Atom : getAtomsDesc()) { 136837c110cSSpyridoula Gravani DWARFFormValue FormValue(Atom.second); 137e5400f8aSPaul Robinson FormValue.extractValue(AccelSection, &HashDataOffset, FormParams); 138837c110cSSpyridoula Gravani switch (Atom.first) { 139837c110cSSpyridoula Gravani case dwarf::DW_ATOM_die_offset: 140837c110cSSpyridoula Gravani DieOffset = *FormValue.getAsUnsignedConstant(); 141837c110cSSpyridoula Gravani break; 14270d35e10SSpyridoula Gravani case dwarf::DW_ATOM_die_tag: 14370d35e10SSpyridoula Gravani DieTag = (dwarf::Tag)*FormValue.getAsUnsignedConstant(); 14470d35e10SSpyridoula Gravani break; 145837c110cSSpyridoula Gravani default: 146837c110cSSpyridoula Gravani break; 147837c110cSSpyridoula Gravani } 148837c110cSSpyridoula Gravani } 14970d35e10SSpyridoula Gravani return {DieOffset, DieTag}; 150837c110cSSpyridoula Gravani } 151837c110cSSpyridoula Gravani 152*394e8056SPavel Labath void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const { 153*394e8056SPavel Labath DictScope HeaderScope(W, "Header"); 154*394e8056SPavel Labath W.printHex("Magic", Magic); 155*394e8056SPavel Labath W.printHex("Version", Version); 156*394e8056SPavel Labath W.printHex("Hash function", HashFunction); 157*394e8056SPavel Labath W.printNumber("Bucket count", BucketCount); 158*394e8056SPavel Labath W.printNumber("Hashes count", HashCount); 159*394e8056SPavel Labath W.printNumber("HeaderData length", HeaderDataLength); 160*394e8056SPavel Labath } 161*394e8056SPavel Labath 162*394e8056SPavel Labath bool AppleAcceleratorTable::dumpName(ScopedPrinter &W, 163*394e8056SPavel Labath SmallVectorImpl<DWARFFormValue> &AtomForms, 164*394e8056SPavel Labath uint32_t *DataOffset) const { 165*394e8056SPavel Labath DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; 166*394e8056SPavel Labath uint32_t NameOffset = *DataOffset; 167*394e8056SPavel Labath if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) { 168*394e8056SPavel Labath W.printString("Incorrectly terminated list."); 169*394e8056SPavel Labath return false; 170*394e8056SPavel Labath } 171*394e8056SPavel Labath unsigned StringOffset = AccelSection.getRelocatedValue(4, DataOffset); 172*394e8056SPavel Labath if (!StringOffset) 173*394e8056SPavel Labath return false; // End of list 174*394e8056SPavel Labath 175*394e8056SPavel Labath DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str()); 176*394e8056SPavel Labath W.startLine() << format("String: 0x%08x", StringOffset); 177*394e8056SPavel Labath W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n"; 178*394e8056SPavel Labath 179*394e8056SPavel Labath unsigned NumData = AccelSection.getU32(DataOffset); 180*394e8056SPavel Labath for (unsigned Data = 0; Data < NumData; ++Data) { 181*394e8056SPavel Labath ListScope DataScope(W, ("Data " + Twine(Data)).str()); 182*394e8056SPavel Labath unsigned i = 0; 183*394e8056SPavel Labath for (auto &Atom : AtomForms) { 184*394e8056SPavel Labath W.startLine() << format("Atom[%d]: ", i++); 185*394e8056SPavel Labath if (Atom.extractValue(AccelSection, DataOffset, FormParams)) 186*394e8056SPavel Labath Atom.dump(W.getOStream()); 187*394e8056SPavel Labath else 188*394e8056SPavel Labath W.getOStream() << "Error extracting the value"; 189*394e8056SPavel Labath W.getOStream() << "\n"; 190*394e8056SPavel Labath } 191*394e8056SPavel Labath } 192*394e8056SPavel Labath return true; // more entries follow 193*394e8056SPavel Labath } 194*394e8056SPavel Labath 1959b36fd25SPavel Labath LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const { 19699fdb9d9SAdrian Prantl if (!IsValid) 19799fdb9d9SAdrian Prantl return; 19899fdb9d9SAdrian Prantl 199*394e8056SPavel Labath ScopedPrinter W(OS); 20082af9438SZachary Turner 201*394e8056SPavel Labath Hdr.dump(W); 202*394e8056SPavel Labath 203*394e8056SPavel Labath W.printNumber("DIE offset base", HdrData.DIEOffsetBase); 204*394e8056SPavel Labath W.printNumber("Number of atoms", HdrData.Atoms.size()); 20582af9438SZachary Turner SmallVector<DWARFFormValue, 3> AtomForms; 206*394e8056SPavel Labath { 207*394e8056SPavel Labath ListScope AtomsScope(W, "Atoms"); 208*394e8056SPavel Labath unsigned i = 0; 20982af9438SZachary Turner for (const auto &Atom : HdrData.Atoms) { 210*394e8056SPavel Labath DictScope AtomScope(W, ("Atom " + Twine(i++)).str()); 211*394e8056SPavel Labath W.startLine() << "Type: " << formatAtom(Atom.first) << '\n'; 212*394e8056SPavel Labath W.startLine() << "Form: " << formatForm(Atom.second) << '\n'; 21382af9438SZachary Turner AtomForms.push_back(DWARFFormValue(Atom.second)); 21482af9438SZachary Turner } 215*394e8056SPavel Labath } 21682af9438SZachary Turner 21782af9438SZachary Turner // Now go through the actual tables and dump them. 21882af9438SZachary Turner uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength; 219*394e8056SPavel Labath unsigned HashesBase = Offset + Hdr.BucketCount * 4; 220*394e8056SPavel Labath unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4; 22182af9438SZachary Turner 222*394e8056SPavel Labath for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) { 22382af9438SZachary Turner unsigned Index = AccelSection.getU32(&Offset); 22482af9438SZachary Turner 225*394e8056SPavel Labath ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str()); 22682af9438SZachary Turner if (Index == UINT32_MAX) { 227*394e8056SPavel Labath W.printString("EMPTY"); 22882af9438SZachary Turner continue; 22982af9438SZachary Turner } 23082af9438SZachary Turner 231*394e8056SPavel Labath for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) { 23282af9438SZachary Turner unsigned HashOffset = HashesBase + HashIdx*4; 23382af9438SZachary Turner unsigned OffsetsOffset = OffsetsBase + HashIdx*4; 23482af9438SZachary Turner uint32_t Hash = AccelSection.getU32(&HashOffset); 23582af9438SZachary Turner 236*394e8056SPavel Labath if (Hash % Hdr.BucketCount != Bucket) 23782af9438SZachary Turner break; 23882af9438SZachary Turner 23982af9438SZachary Turner unsigned DataOffset = AccelSection.getU32(&OffsetsOffset); 240*394e8056SPavel Labath ListScope HashScope(W, ("Hash 0x" + Twine::utohexstr(Hash)).str()); 24182af9438SZachary Turner if (!AccelSection.isValidOffset(DataOffset)) { 242*394e8056SPavel Labath W.printString("Invalid section offset"); 24382af9438SZachary Turner continue; 24482af9438SZachary Turner } 245*394e8056SPavel Labath while (dumpName(W, AtomForms, &DataOffset)) 246*394e8056SPavel Labath /*empty*/; 24782af9438SZachary Turner } 24882af9438SZachary Turner } 24982af9438SZachary Turner } 25099fdb9d9SAdrian Prantl 2519b36fd25SPavel Labath AppleAcceleratorTable::ValueIterator::ValueIterator( 2529b36fd25SPavel Labath const AppleAcceleratorTable &AccelTable, unsigned Offset) 25399fdb9d9SAdrian Prantl : AccelTable(&AccelTable), DataOffset(Offset) { 25499fdb9d9SAdrian Prantl if (!AccelTable.AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) 25599fdb9d9SAdrian Prantl return; 25699fdb9d9SAdrian Prantl 25799fdb9d9SAdrian Prantl for (const auto &Atom : AccelTable.HdrData.Atoms) 25899fdb9d9SAdrian Prantl AtomForms.push_back(DWARFFormValue(Atom.second)); 25999fdb9d9SAdrian Prantl 26099fdb9d9SAdrian Prantl // Read the first entry. 26199fdb9d9SAdrian Prantl NumData = AccelTable.AccelSection.getU32(&DataOffset); 26299fdb9d9SAdrian Prantl Next(); 26399fdb9d9SAdrian Prantl } 26499fdb9d9SAdrian Prantl 2659b36fd25SPavel Labath void AppleAcceleratorTable::ValueIterator::Next() { 26699fdb9d9SAdrian Prantl assert(NumData > 0 && "attempted to increment iterator past the end"); 26799fdb9d9SAdrian Prantl auto &AccelSection = AccelTable->AccelSection; 26899fdb9d9SAdrian Prantl if (Data >= NumData || 26999fdb9d9SAdrian Prantl !AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) { 27099fdb9d9SAdrian Prantl NumData = 0; 27199fdb9d9SAdrian Prantl return; 27299fdb9d9SAdrian Prantl } 273e5400f8aSPaul Robinson DWARFFormParams FormParams = {AccelTable->Hdr.Version, 0, 274e5400f8aSPaul Robinson dwarf::DwarfFormat::DWARF32}; 27599fdb9d9SAdrian Prantl for (auto &Atom : AtomForms) 276e5400f8aSPaul Robinson Atom.extractValue(AccelSection, &DataOffset, FormParams); 27799fdb9d9SAdrian Prantl ++Data; 27899fdb9d9SAdrian Prantl } 27999fdb9d9SAdrian Prantl 2809b36fd25SPavel Labath iterator_range<AppleAcceleratorTable::ValueIterator> 2819b36fd25SPavel Labath AppleAcceleratorTable::equal_range(StringRef Key) const { 28299fdb9d9SAdrian Prantl if (!IsValid) 28399fdb9d9SAdrian Prantl return make_range(ValueIterator(), ValueIterator()); 28499fdb9d9SAdrian Prantl 28599fdb9d9SAdrian Prantl // Find the bucket. 28692ac9d3eSJonas Devlieghere unsigned HashValue = djbHash(Key); 287*394e8056SPavel Labath unsigned Bucket = HashValue % Hdr.BucketCount; 28899fdb9d9SAdrian Prantl unsigned BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength; 289*394e8056SPavel Labath unsigned HashesBase = BucketBase + Hdr.BucketCount * 4; 290*394e8056SPavel Labath unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4; 29199fdb9d9SAdrian Prantl 29299fdb9d9SAdrian Prantl unsigned BucketOffset = BucketBase + Bucket * 4; 29399fdb9d9SAdrian Prantl unsigned Index = AccelSection.getU32(&BucketOffset); 29499fdb9d9SAdrian Prantl 29599fdb9d9SAdrian Prantl // Search through all hashes in the bucket. 296*394e8056SPavel Labath for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) { 29799fdb9d9SAdrian Prantl unsigned HashOffset = HashesBase + HashIdx * 4; 29899fdb9d9SAdrian Prantl unsigned OffsetsOffset = OffsetsBase + HashIdx * 4; 29999fdb9d9SAdrian Prantl uint32_t Hash = AccelSection.getU32(&HashOffset); 30099fdb9d9SAdrian Prantl 301*394e8056SPavel Labath if (Hash % Hdr.BucketCount != Bucket) 30299fdb9d9SAdrian Prantl // We are already in the next bucket. 30399fdb9d9SAdrian Prantl break; 30499fdb9d9SAdrian Prantl 30599fdb9d9SAdrian Prantl unsigned DataOffset = AccelSection.getU32(&OffsetsOffset); 30699fdb9d9SAdrian Prantl unsigned StringOffset = AccelSection.getRelocatedValue(4, &DataOffset); 30799fdb9d9SAdrian Prantl if (!StringOffset) 30899fdb9d9SAdrian Prantl break; 30999fdb9d9SAdrian Prantl 31099fdb9d9SAdrian Prantl // Finally, compare the key. 31199fdb9d9SAdrian Prantl if (Key == StringSection.getCStr(&StringOffset)) 31299fdb9d9SAdrian Prantl return make_range({*this, DataOffset}, ValueIterator()); 31399fdb9d9SAdrian Prantl } 31499fdb9d9SAdrian Prantl return make_range(ValueIterator(), ValueIterator()); 31599fdb9d9SAdrian Prantl } 3163c9a918cSPavel Labath 3173c9a918cSPavel Labath void DWARFDebugNames::Header::dump(ScopedPrinter &W) const { 3183c9a918cSPavel Labath DictScope HeaderScope(W, "Header"); 3193c9a918cSPavel Labath W.printHex("Length", UnitLength); 3203c9a918cSPavel Labath W.printNumber("Version", Version); 3213c9a918cSPavel Labath W.printHex("Padding", Padding); 3223c9a918cSPavel Labath W.printNumber("CU count", CompUnitCount); 3233c9a918cSPavel Labath W.printNumber("Local TU count", LocalTypeUnitCount); 3243c9a918cSPavel Labath W.printNumber("Foreign TU count", ForeignTypeUnitCount); 3253c9a918cSPavel Labath W.printNumber("Bucket count", BucketCount); 3263c9a918cSPavel Labath W.printNumber("Name count", NameCount); 3273c9a918cSPavel Labath W.printHex("Abbreviations table size", AbbrevTableSize); 3283c9a918cSPavel Labath W.startLine() << "Augmentation: '" << AugmentationString << "'\n"; 3293c9a918cSPavel Labath } 3303c9a918cSPavel Labath 3313c9a918cSPavel Labath llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, 3323c9a918cSPavel Labath uint32_t *Offset) { 3333c9a918cSPavel Labath // Check that we can read the fixed-size part. 3343c9a918cSPavel Labath if (!AS.isValidOffset(*Offset + sizeof(Header) - 1)) 3353c9a918cSPavel Labath return make_error<StringError>("Section too small: cannot read header.", 3363c9a918cSPavel Labath inconvertibleErrorCode()); 3373c9a918cSPavel Labath 3383c9a918cSPavel Labath UnitLength = AS.getU32(Offset); 3393c9a918cSPavel Labath Version = AS.getU16(Offset); 3403c9a918cSPavel Labath Padding = AS.getU16(Offset); 3413c9a918cSPavel Labath CompUnitCount = AS.getU32(Offset); 3423c9a918cSPavel Labath LocalTypeUnitCount = AS.getU32(Offset); 3433c9a918cSPavel Labath ForeignTypeUnitCount = AS.getU32(Offset); 3443c9a918cSPavel Labath BucketCount = AS.getU32(Offset); 3453c9a918cSPavel Labath NameCount = AS.getU32(Offset); 3463c9a918cSPavel Labath AbbrevTableSize = AS.getU32(Offset); 3473c9a918cSPavel Labath AugmentationStringSize = AS.getU32(Offset); 3483c9a918cSPavel Labath 3493c9a918cSPavel Labath if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize)) 3503c9a918cSPavel Labath return make_error<StringError>( 3513c9a918cSPavel Labath "Section too small: cannot read header augmentation.", 3523c9a918cSPavel Labath inconvertibleErrorCode()); 3533c9a918cSPavel Labath AugmentationString.resize(AugmentationStringSize); 3543c9a918cSPavel Labath AS.getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()), 3553c9a918cSPavel Labath AugmentationStringSize); 3563c9a918cSPavel Labath *Offset = alignTo(*Offset, 4); 3573c9a918cSPavel Labath return Error::success(); 3583c9a918cSPavel Labath } 3593c9a918cSPavel Labath 3603c9a918cSPavel Labath void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const { 3613c9a918cSPavel Labath DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str()); 3623c9a918cSPavel Labath W.startLine() << "Tag: " << formatTag(Tag) << '\n'; 3633c9a918cSPavel Labath 3643c9a918cSPavel Labath for (const auto &Attr : Attributes) { 3653c9a918cSPavel Labath W.startLine() << formatIndex(Attr.Index) << ": " << formatForm(Attr.Form) 3663c9a918cSPavel Labath << '\n'; 3673c9a918cSPavel Labath } 3683c9a918cSPavel Labath } 3693c9a918cSPavel Labath 3703c9a918cSPavel Labath static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc() { 3713c9a918cSPavel Labath return {dwarf::Index(0), dwarf::Form(0)}; 3723c9a918cSPavel Labath } 3733c9a918cSPavel Labath 3743c9a918cSPavel Labath static bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE) { 3753c9a918cSPavel Labath return AE == sentinelAttrEnc(); 3763c9a918cSPavel Labath } 3773c9a918cSPavel Labath 3783c9a918cSPavel Labath static DWARFDebugNames::Abbrev sentinelAbbrev() { 3793c9a918cSPavel Labath return DWARFDebugNames::Abbrev(0, dwarf::Tag(0), {}); 3803c9a918cSPavel Labath } 3813c9a918cSPavel Labath 3823c9a918cSPavel Labath static bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) { 3833c9a918cSPavel Labath return Abbr.Code == 0; 3843c9a918cSPavel Labath } 3853c9a918cSPavel Labath 3863c9a918cSPavel Labath DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() { 3873c9a918cSPavel Labath return sentinelAbbrev(); 3883c9a918cSPavel Labath } 3893c9a918cSPavel Labath 3903c9a918cSPavel Labath DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() { 3913c9a918cSPavel Labath return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), {}); 3923c9a918cSPavel Labath } 3933c9a918cSPavel Labath 3943c9a918cSPavel Labath Expected<DWARFDebugNames::AttributeEncoding> 3953c9a918cSPavel Labath DWARFDebugNames::NameIndex::extractAttributeEncoding(uint32_t *Offset) { 3963c9a918cSPavel Labath if (*Offset >= EntriesBase) { 3973c9a918cSPavel Labath return make_error<StringError>("Incorrectly terminated abbreviation table.", 3983c9a918cSPavel Labath inconvertibleErrorCode()); 3993c9a918cSPavel Labath } 4003c9a918cSPavel Labath 4013c9a918cSPavel Labath uint32_t Index = Section.AccelSection.getULEB128(Offset); 4023c9a918cSPavel Labath uint32_t Form = Section.AccelSection.getULEB128(Offset); 4033c9a918cSPavel Labath return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form)); 4043c9a918cSPavel Labath } 4053c9a918cSPavel Labath 4063c9a918cSPavel Labath Expected<std::vector<DWARFDebugNames::AttributeEncoding>> 4073c9a918cSPavel Labath DWARFDebugNames::NameIndex::extractAttributeEncodings(uint32_t *Offset) { 4083c9a918cSPavel Labath std::vector<AttributeEncoding> Result; 4093c9a918cSPavel Labath for (;;) { 4103c9a918cSPavel Labath auto AttrEncOr = extractAttributeEncoding(Offset); 4113c9a918cSPavel Labath if (!AttrEncOr) 4123c9a918cSPavel Labath return AttrEncOr.takeError(); 4133c9a918cSPavel Labath if (isSentinel(*AttrEncOr)) 4143c9a918cSPavel Labath return std::move(Result); 4153c9a918cSPavel Labath 4163c9a918cSPavel Labath Result.emplace_back(*AttrEncOr); 4173c9a918cSPavel Labath } 4183c9a918cSPavel Labath } 4193c9a918cSPavel Labath 4203c9a918cSPavel Labath Expected<DWARFDebugNames::Abbrev> 4213c9a918cSPavel Labath DWARFDebugNames::NameIndex::extractAbbrev(uint32_t *Offset) { 4223c9a918cSPavel Labath if (*Offset >= EntriesBase) { 4233c9a918cSPavel Labath return make_error<StringError>("Incorrectly terminated abbreviation table.", 4243c9a918cSPavel Labath inconvertibleErrorCode()); 4253c9a918cSPavel Labath } 4263c9a918cSPavel Labath 4273c9a918cSPavel Labath uint32_t Code = Section.AccelSection.getULEB128(Offset); 4283c9a918cSPavel Labath if (Code == 0) 4293c9a918cSPavel Labath return sentinelAbbrev(); 4303c9a918cSPavel Labath 4313c9a918cSPavel Labath uint32_t Tag = Section.AccelSection.getULEB128(Offset); 4323c9a918cSPavel Labath auto AttrEncOr = extractAttributeEncodings(Offset); 4333c9a918cSPavel Labath if (!AttrEncOr) 4343c9a918cSPavel Labath return AttrEncOr.takeError(); 4353c9a918cSPavel Labath return Abbrev(Code, dwarf::Tag(Tag), std::move(*AttrEncOr)); 4363c9a918cSPavel Labath } 4373c9a918cSPavel Labath 4383c9a918cSPavel Labath Error DWARFDebugNames::NameIndex::extract() { 4393c9a918cSPavel Labath const DWARFDataExtractor &AS = Section.AccelSection; 4403c9a918cSPavel Labath uint32_t Offset = Base; 4413c9a918cSPavel Labath if (Error E = Hdr.extract(AS, &Offset)) 4423c9a918cSPavel Labath return E; 4433c9a918cSPavel Labath 4443c9a918cSPavel Labath CUsBase = Offset; 4453c9a918cSPavel Labath Offset += Hdr.CompUnitCount * 4; 4463c9a918cSPavel Labath Offset += Hdr.LocalTypeUnitCount * 4; 4473c9a918cSPavel Labath Offset += Hdr.ForeignTypeUnitCount * 8; 4483c9a918cSPavel Labath BucketsBase = Offset; 4493c9a918cSPavel Labath Offset += Hdr.BucketCount * 4; 4503c9a918cSPavel Labath HashesBase = Offset; 4513c9a918cSPavel Labath if (Hdr.BucketCount > 0) 4523c9a918cSPavel Labath Offset += Hdr.NameCount * 4; 4533c9a918cSPavel Labath StringOffsetsBase = Offset; 4543c9a918cSPavel Labath Offset += Hdr.NameCount * 4; 4553c9a918cSPavel Labath EntryOffsetsBase = Offset; 4563c9a918cSPavel Labath Offset += Hdr.NameCount * 4; 4573c9a918cSPavel Labath 4583c9a918cSPavel Labath if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize)) 4593c9a918cSPavel Labath return make_error<StringError>( 4603c9a918cSPavel Labath "Section too small: cannot read abbreviations.", 4613c9a918cSPavel Labath inconvertibleErrorCode()); 4623c9a918cSPavel Labath 4633c9a918cSPavel Labath EntriesBase = Offset + Hdr.AbbrevTableSize; 4643c9a918cSPavel Labath 4653c9a918cSPavel Labath for (;;) { 4663c9a918cSPavel Labath auto AbbrevOr = extractAbbrev(&Offset); 4673c9a918cSPavel Labath if (!AbbrevOr) 4683c9a918cSPavel Labath return AbbrevOr.takeError(); 4693c9a918cSPavel Labath if (isSentinel(*AbbrevOr)) 4703c9a918cSPavel Labath return Error::success(); 4713c9a918cSPavel Labath 4723c9a918cSPavel Labath if (!Abbrevs.insert(std::move(*AbbrevOr)).second) { 4733c9a918cSPavel Labath return make_error<StringError>("Duplicate abbreviation code.", 4743c9a918cSPavel Labath inconvertibleErrorCode()); 4753c9a918cSPavel Labath } 4763c9a918cSPavel Labath } 4773c9a918cSPavel Labath } 4783c9a918cSPavel Labath 4793c9a918cSPavel Labath DWARFDebugNames::Entry::Entry(const Abbrev &Abbr) : Abbr(Abbr) { 4803c9a918cSPavel Labath // This merely creates form values. It is up to the caller 4813c9a918cSPavel Labath // (NameIndex::getEntry) to populate them. 4823c9a918cSPavel Labath Values.reserve(Abbr.Attributes.size()); 4833c9a918cSPavel Labath for (const auto &Attr : Abbr.Attributes) 4843c9a918cSPavel Labath Values.emplace_back(Attr.Form); 4853c9a918cSPavel Labath } 4863c9a918cSPavel Labath 4873c9a918cSPavel Labath void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const { 4883c9a918cSPavel Labath W.printHex("Abbrev", Abbr.Code); 4893c9a918cSPavel Labath W.startLine() << "Tag: " << formatTag(Abbr.Tag) << "\n"; 4903c9a918cSPavel Labath 4913c9a918cSPavel Labath assert(Abbr.Attributes.size() == Values.size()); 4923c9a918cSPavel Labath for (uint32_t I = 0, E = Values.size(); I < E; ++I) { 4933c9a918cSPavel Labath W.startLine() << formatIndex(Abbr.Attributes[I].Index) << ": "; 4943c9a918cSPavel Labath Values[I].dump(W.getOStream()); 4953c9a918cSPavel Labath W.getOStream() << '\n'; 4963c9a918cSPavel Labath } 4973c9a918cSPavel Labath } 4983c9a918cSPavel Labath 4993c9a918cSPavel Labath char DWARFDebugNames::SentinelError::ID; 5003c9a918cSPavel Labath std::error_code DWARFDebugNames::SentinelError::convertToErrorCode() const { 5013c9a918cSPavel Labath return inconvertibleErrorCode(); 5023c9a918cSPavel Labath } 5033c9a918cSPavel Labath 5043c9a918cSPavel Labath uint32_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const { 5053c9a918cSPavel Labath assert(CU < Hdr.CompUnitCount); 5063c9a918cSPavel Labath uint32_t Offset = CUsBase + 4 * CU; 5073c9a918cSPavel Labath return Section.AccelSection.getRelocatedValue(4, &Offset); 5083c9a918cSPavel Labath } 5093c9a918cSPavel Labath 5103c9a918cSPavel Labath uint32_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const { 5113c9a918cSPavel Labath assert(TU < Hdr.LocalTypeUnitCount); 5123c9a918cSPavel Labath uint32_t Offset = CUsBase + Hdr.CompUnitCount * 4; 5133c9a918cSPavel Labath return Section.AccelSection.getRelocatedValue(4, &Offset); 5143c9a918cSPavel Labath } 5153c9a918cSPavel Labath 5163c9a918cSPavel Labath uint64_t DWARFDebugNames::NameIndex::getForeignTUOffset(uint32_t TU) const { 5173c9a918cSPavel Labath assert(TU < Hdr.ForeignTypeUnitCount); 5183c9a918cSPavel Labath uint32_t Offset = CUsBase + (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) * 4; 5193c9a918cSPavel Labath return Section.AccelSection.getU64(&Offset); 5203c9a918cSPavel Labath } 5213c9a918cSPavel Labath 5223c9a918cSPavel Labath Expected<DWARFDebugNames::Entry> 5233c9a918cSPavel Labath DWARFDebugNames::NameIndex::getEntry(uint32_t *Offset) const { 5243c9a918cSPavel Labath const DWARFDataExtractor &AS = Section.AccelSection; 5253c9a918cSPavel Labath if (!AS.isValidOffset(*Offset)) 5263c9a918cSPavel Labath return make_error<StringError>("Incorrectly terminated entry list", 5273c9a918cSPavel Labath inconvertibleErrorCode()); 5283c9a918cSPavel Labath 5293c9a918cSPavel Labath uint32_t AbbrevCode = AS.getULEB128(Offset); 5303c9a918cSPavel Labath if (AbbrevCode == 0) 5313c9a918cSPavel Labath return make_error<SentinelError>(); 5323c9a918cSPavel Labath 5333c9a918cSPavel Labath const auto AbbrevIt = Abbrevs.find_as(AbbrevCode); 5343c9a918cSPavel Labath if (AbbrevIt == Abbrevs.end()) 5353c9a918cSPavel Labath return make_error<StringError>("Invalid abbreviation", 5363c9a918cSPavel Labath inconvertibleErrorCode()); 5373c9a918cSPavel Labath 5383c9a918cSPavel Labath Entry E(*AbbrevIt); 5393c9a918cSPavel Labath 5403c9a918cSPavel Labath DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; 5413c9a918cSPavel Labath for (auto &Value : E.Values) { 5423c9a918cSPavel Labath if (!Value.extractValue(AS, Offset, FormParams)) 5433c9a918cSPavel Labath return make_error<StringError>("Error extracting index attribute values", 5443c9a918cSPavel Labath inconvertibleErrorCode()); 5453c9a918cSPavel Labath } 5463c9a918cSPavel Labath return std::move(E); 5473c9a918cSPavel Labath } 5483c9a918cSPavel Labath 5493c9a918cSPavel Labath DWARFDebugNames::NameTableEntry 5503c9a918cSPavel Labath DWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const { 5513c9a918cSPavel Labath assert(0 < Index && Index <= Hdr.NameCount); 5523c9a918cSPavel Labath uint32_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1); 5533c9a918cSPavel Labath uint32_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1); 5543c9a918cSPavel Labath const DWARFDataExtractor &AS = Section.AccelSection; 5553c9a918cSPavel Labath 5563c9a918cSPavel Labath uint32_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset); 5573c9a918cSPavel Labath uint32_t EntryOffset = AS.getU32(&EntryOffsetOffset); 5583c9a918cSPavel Labath EntryOffset += EntriesBase; 5593c9a918cSPavel Labath return {StringOffset, EntryOffset}; 5603c9a918cSPavel Labath } 5613c9a918cSPavel Labath 5623c9a918cSPavel Labath uint32_t 5633c9a918cSPavel Labath DWARFDebugNames::NameIndex::getBucketArrayEntry(uint32_t Bucket) const { 5643c9a918cSPavel Labath assert(Bucket < Hdr.BucketCount); 5653c9a918cSPavel Labath uint32_t BucketOffset = BucketsBase + 4 * Bucket; 5663c9a918cSPavel Labath return Section.AccelSection.getU32(&BucketOffset); 5673c9a918cSPavel Labath } 5683c9a918cSPavel Labath 5693c9a918cSPavel Labath uint32_t DWARFDebugNames::NameIndex::getHashArrayEntry(uint32_t Index) const { 5703c9a918cSPavel Labath assert(0 < Index && Index <= Hdr.NameCount); 5713c9a918cSPavel Labath uint32_t HashOffset = HashesBase + 4 * (Index - 1); 5723c9a918cSPavel Labath return Section.AccelSection.getU32(&HashOffset); 5733c9a918cSPavel Labath } 5743c9a918cSPavel Labath 5753c9a918cSPavel Labath // Returns true if we should continue scanning for entries, false if this is the 5763c9a918cSPavel Labath // last (sentinel) entry). In case of a parsing error we also return false, as 5773c9a918cSPavel Labath // it's not possible to recover this entry list (but the other lists may still 5783c9a918cSPavel Labath // parse OK). 5793c9a918cSPavel Labath bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W, 5803c9a918cSPavel Labath uint32_t *Offset) const { 5813c9a918cSPavel Labath uint32_t EntryId = *Offset; 5823c9a918cSPavel Labath auto EntryOr = getEntry(Offset); 5833c9a918cSPavel Labath if (!EntryOr) { 5843c9a918cSPavel Labath handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {}, 5853c9a918cSPavel Labath [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); }); 5863c9a918cSPavel Labath return false; 5873c9a918cSPavel Labath } 5883c9a918cSPavel Labath 5893c9a918cSPavel Labath DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str()); 5903c9a918cSPavel Labath EntryOr->dump(W); 5913c9a918cSPavel Labath return true; 5923c9a918cSPavel Labath } 5933c9a918cSPavel Labath 5943c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W, uint32_t Index, 5953c9a918cSPavel Labath Optional<uint32_t> Hash) const { 5963c9a918cSPavel Labath const DataExtractor &SS = Section.StringSection; 5973c9a918cSPavel Labath NameTableEntry NTE = getNameTableEntry(Index); 5983c9a918cSPavel Labath 5993c9a918cSPavel Labath DictScope NameScope(W, ("Name " + Twine(Index)).str()); 6003c9a918cSPavel Labath if (Hash) 6013c9a918cSPavel Labath W.printHex("Hash", *Hash); 6023c9a918cSPavel Labath 6033c9a918cSPavel Labath W.startLine() << format("String: 0x%08x", NTE.StringOffset); 6043c9a918cSPavel Labath W.getOStream() << " \"" << SS.getCStr(&NTE.StringOffset) << "\"\n"; 6053c9a918cSPavel Labath 6063c9a918cSPavel Labath while (dumpEntry(W, &NTE.EntryOffset)) 6073c9a918cSPavel Labath /*empty*/; 6083c9a918cSPavel Labath } 6093c9a918cSPavel Labath 6103c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const { 6113c9a918cSPavel Labath ListScope CUScope(W, "Compilation Unit offsets"); 6123c9a918cSPavel Labath for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU) 6133c9a918cSPavel Labath W.startLine() << format("CU[%u]: 0x%08x\n", CU, getCUOffset(CU)); 6143c9a918cSPavel Labath } 6153c9a918cSPavel Labath 6163c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const { 6173c9a918cSPavel Labath if (Hdr.LocalTypeUnitCount == 0) 6183c9a918cSPavel Labath return; 6193c9a918cSPavel Labath 6203c9a918cSPavel Labath ListScope TUScope(W, "Local Type Unit offsets"); 6213c9a918cSPavel Labath for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU) 6223c9a918cSPavel Labath W.startLine() << format("LocalTU[%u]: 0x%08x\n", TU, getLocalTUOffset(TU)); 6233c9a918cSPavel Labath } 6243c9a918cSPavel Labath 6253c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const { 6263c9a918cSPavel Labath if (Hdr.ForeignTypeUnitCount == 0) 6273c9a918cSPavel Labath return; 6283c9a918cSPavel Labath 6293c9a918cSPavel Labath ListScope TUScope(W, "Foreign Type Unit signatures"); 6303c9a918cSPavel Labath for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) { 6313c9a918cSPavel Labath W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU, 6323c9a918cSPavel Labath getForeignTUOffset(TU)); 6333c9a918cSPavel Labath } 6343c9a918cSPavel Labath } 6353c9a918cSPavel Labath 6363c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const { 6373c9a918cSPavel Labath ListScope AbbrevsScope(W, "Abbreviations"); 6383c9a918cSPavel Labath for (const auto &Abbr : Abbrevs) 6393c9a918cSPavel Labath Abbr.dump(W); 6403c9a918cSPavel Labath } 6413c9a918cSPavel Labath 6423c9a918cSPavel Labath void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W, 6433c9a918cSPavel Labath uint32_t Bucket) const { 6443c9a918cSPavel Labath ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str()); 6453c9a918cSPavel Labath uint32_t Index = getBucketArrayEntry(Bucket); 6463c9a918cSPavel Labath if (Index == 0) { 6473c9a918cSPavel Labath W.printString("EMPTY"); 6483c9a918cSPavel Labath return; 6493c9a918cSPavel Labath } 6503c9a918cSPavel Labath if (Index > Hdr.NameCount) { 6513c9a918cSPavel Labath W.printString("Name index is invalid"); 6523c9a918cSPavel Labath return; 6533c9a918cSPavel Labath } 6543c9a918cSPavel Labath 6553c9a918cSPavel Labath for (; Index <= Hdr.NameCount; ++Index) { 6563c9a918cSPavel Labath uint32_t Hash = getHashArrayEntry(Index); 6573c9a918cSPavel Labath if (Hash % Hdr.BucketCount != Bucket) 6583c9a918cSPavel Labath break; 6593c9a918cSPavel Labath 6603c9a918cSPavel Labath dumpName(W, Index, Hash); 6613c9a918cSPavel Labath } 6623c9a918cSPavel Labath } 6633c9a918cSPavel Labath 6643c9a918cSPavel Labath LLVM_DUMP_METHOD void DWARFDebugNames::NameIndex::dump(ScopedPrinter &W) const { 6653c9a918cSPavel Labath DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str()); 6663c9a918cSPavel Labath Hdr.dump(W); 6673c9a918cSPavel Labath dumpCUs(W); 6683c9a918cSPavel Labath dumpLocalTUs(W); 6693c9a918cSPavel Labath dumpForeignTUs(W); 6703c9a918cSPavel Labath dumpAbbreviations(W); 6713c9a918cSPavel Labath 6723c9a918cSPavel Labath if (Hdr.BucketCount > 0) { 6733c9a918cSPavel Labath for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) 6743c9a918cSPavel Labath dumpBucket(W, Bucket); 6753c9a918cSPavel Labath return; 6763c9a918cSPavel Labath } 6773c9a918cSPavel Labath 6783c9a918cSPavel Labath W.startLine() << "Hash table not present\n"; 6793c9a918cSPavel Labath for (uint32_t Index = 1; Index <= Hdr.NameCount; ++Index) 6803c9a918cSPavel Labath dumpName(W, Index, None); 6813c9a918cSPavel Labath } 6823c9a918cSPavel Labath 6833c9a918cSPavel Labath llvm::Error DWARFDebugNames::extract() { 6843c9a918cSPavel Labath uint32_t Offset = 0; 6853c9a918cSPavel Labath while (AccelSection.isValidOffset(Offset)) { 6863c9a918cSPavel Labath NameIndex Next(*this, Offset); 6873c9a918cSPavel Labath if (llvm::Error E = Next.extract()) 6883c9a918cSPavel Labath return E; 6893c9a918cSPavel Labath Offset = Next.getNextUnitOffset(); 6903c9a918cSPavel Labath NameIndices.push_back(std::move(Next)); 6913c9a918cSPavel Labath } 6923c9a918cSPavel Labath return Error::success(); 6933c9a918cSPavel Labath } 6943c9a918cSPavel Labath 6953c9a918cSPavel Labath LLVM_DUMP_METHOD void DWARFDebugNames::dump(raw_ostream &OS) const { 6963c9a918cSPavel Labath ScopedPrinter W(OS); 6973c9a918cSPavel Labath for (const NameIndex &NI : NameIndices) 6983c9a918cSPavel Labath NI.dump(W); 6993c9a918cSPavel Labath } 700